[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "content": "name: 🐛 Bug Report\ndescription: Create a bug report\ntype: Bug\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thank you for taking the time to fill out this bug report!\n        Please fill out the form below...\n  - type: textarea\n    id: description\n    attributes:\n      label: Bug Description\n      description: Please provide a clear and concise description of what the bug is.\n      placeholder: The bug is...\n    validations:\n      required: true\n  - type: textarea\n    id: reproduce\n    attributes:\n      label: Steps to Reproduce\n      description: Provide steps to reproduce this bug.\n      placeholder: |\n        1.\n        2.\n        3.\n    validations:\n      required: true\n  - type: textarea\n    id: debug\n    attributes:\n      label: Backtrace\n      description: If your bug produces a backtrace, please include it here.\n      render: shell\n\n  - type: input\n    id: os_version\n    attributes:\n      label: Your operating system and version\n    validations:\n      required: true\n  - type: input\n    id: py_version\n    attributes:\n      label: Your Python version (`python --version`)\n      placeholder: ex. Python 3.10.0\n    validations:\n      required: true\n  - type: input\n    id: rust_version\n    attributes:\n      label: Your Rust version (`rustc --version`)\n      placeholder: ex. rustc 1.55.0 (c8dfcfe04 2021-09-06)\n    validations:\n      required: true\n  - type: input\n    id: pyo3_version\n    attributes:\n      label: Your PyO3 version\n      placeholder: ex. 0.14.0\n    validations:\n      required: true\n  - type: textarea\n    id: install_method\n    attributes:\n      label: How did you install python? Did you use a virtualenv?\n      placeholder: |\n        apt\n        pyenv\n        pacman\n        brew\n        python.org installer\n        microsoft store\n        etc...\n    validations:\n      required: true\n  - type: textarea\n    id: additional-info\n    attributes:\n      label: Additional Info\n      description: Any additional info that you think might be useful or relevant to this bug\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\ncontact_links:\n  - name: ❓ Question\n    url: https://github.com/PyO3/pyo3/discussions\n    about: Ask and answer questions about PyO3 on Discussions\n  - name: 🔧 Troubleshooting\n    url: https://github.com/PyO3/pyo3/discussions\n    about: For troubleshooting help, see the Discussions\n  - name: 👋 Chat\n    url: https://discord.gg/33kcChzH7f\n    about: Engage with PyO3's users and developers on Discord\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: 💡 Feature request\nabout: Suggest an idea for this project\ntype: Feature\n---\n\n<!--\nThank you for sharing your idea!\n\nPlease describe your idea in depth. If you're not sure what to write, imagine the following:\n  - How is this important to you? How would you use it?\n  - Can you think of any alternatives?\n  - Do you have any ideas about how it can be implemented? Are you willing/able to implement it? Do you need mentoring?\n-->\n"
  },
  {
    "path": ".github/actions/fetch-merge-base/action.yml",
    "content": "name: 'Fetch Merge Base'\ndescription: 'Fetches the merge base between two branches, deepening the git checkout until complete'\ninputs:\n  base_ref:\n    description: 'The base branch reference'\n    required: true\n  head_ref:\n    description: 'The head branch reference'\n    required: true\noutputs:\n  merge_base:\n    description: 'The merge base commit SHA'\n    value: ${{ steps.fetch_merge_base.outputs.merge_base }}\nruns:\n  using: \"composite\"\n  steps:\n  - name: Fetch Merge Base\n    id: fetch_merge_base\n    shell: bash\n    run: |\n      # fetch the merge commit between the PR base and head\n      git fetch -u --progress --depth=1 origin \"+$BASE_REF:$BASE_REF\" \"+$HEAD_REF:$HEAD_REF\"\n      while [ -z \"$(git merge-base \"$BASE_REF\" \"$HEAD_REF\")\" ]; do\n        git fetch -u -q --deepen=\"10\" origin \"$BASE_REF\" \"$HEAD_REF\";\n      done\n\n      MERGE_BASE=$(git merge-base \"$BASE_REF\" \"$HEAD_REF\")\n      echo \"merge_base=$MERGE_BASE\" >> $GITHUB_OUTPUT\n    env:\n      BASE_REF: \"${{ inputs.base_ref }}\"\n      HEAD_REF: \"${{ inputs.head_ref }}\"\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where the package manifests are located.\n# Please see the documentation for all configuration options:\n# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\n\nversion: 2\nupdates:\n  - package-ecosystem: \"cargo\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n\n  - package-ecosystem: \"cargo\"\n    directory: \"/pyo3-benches/\"\n    schedule:\n      interval: \"weekly\"\n\n  - package-ecosystem: \"cargo\"\n    directory: \"/pyo3-ffi-check/\"\n    schedule:\n      interval: \"weekly\"\n\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n    labels:\n      # dependabot default labels\n      - \"dependencies\"\n      - \"github-actions\"\n      # additional labels\n      - \"CI-skip-changelog\"\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "Thank you for contributing to PyO3!\n\nBy submitting these contributions you agree for them to be dual-licensed under PyO3's [MIT OR Apache-2.0 license](https://github.com/PyO3/pyo3#license).\n\nPlease consider adding the following to your pull request:\n - an entry for this PR in newsfragments - see [https://pyo3.rs/main/contributing.html#documenting-changes]\n   - or start the PR title with `docs:` if this is a docs-only change to skip the check\n   - or start the PR title with `ci:` if this is a ci-only change to skip the check\n - docs to all new functions and / or detail in the guide\n - tests for all new or changed functions\n\nPyO3's CI pipeline will check your pull request, thus make sure you have checked the `Contributing.md` guidelines. To run most of its tests locally, you can run `nox`. See `nox --list-sessions` for a list of supported actions.\n"
  },
  {
    "path": ".github/workflows/benches.yml",
    "content": "name: benches\n\non:\n  push:\n    branches:\n      - \"main\"\n  pull_request:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}-benches\n  cancel-in-progress: true\n\nenv:\n  UV_PYTHON: \"3.14t\"\n\njobs:\n  benchmarks:\n    runs-on: ubuntu-24.04\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: astral-sh/setup-uv@v7\n        with:\n          # codspeed action needs to be run from within the final Python environment\n          activate-environment: true\n          save-cache: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - uses: dtolnay/rust-toolchain@stable\n        with:\n          components: rust-src\n\n      - uses: Swatinem/rust-cache@v2\n        with:\n          workspaces: |\n            .\n            pyo3-benches\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n          cache-all-crates: \"true\"\n          cache-workspace-crates: \"true\"\n\n      - uses: taiki-e/install-action@v2\n        with:\n          tool: cargo-codspeed\n\n      - name: Run the benchmarks\n        uses: CodSpeedHQ/action@v4\n        with:\n          run: uvx nox -s codspeed\n          token: ${{ secrets.CODSPEED_TOKEN }}\n          mode: simulation\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "content": "on:\n  workflow_call:\n    inputs:\n      os:\n        required: true\n        type: string\n      python-version:\n        required: true\n        type: string\n      python-architecture:\n        required: true\n        type: string\n      rust:\n        required: true\n        type: string\n      rust-target:\n        required: true\n        type: string\n      MSRV:\n        required: true\n        type: string\n      verbose:\n        type: boolean\n        default: false\n\nenv:\n  NOX_DEFAULT_VENV_BACKEND: uv\n\njobs:\n  build:\n    continue-on-error: ${{ endsWith(inputs.python-version, '-dev') || contains(fromJSON('[\"3.7\", \"3.8\"]'), inputs.python-version) || contains(fromJSON('[\"beta\", \"nightly\"]'), inputs.rust) }}\n    runs-on: ${{ inputs.os }}\n    if: ${{ !(startsWith(inputs.python-version, 'graalpy') && startsWith(inputs.os, 'windows')) }}\n    steps:\n      - uses: actions/checkout@v6.0.2\n        with:\n          # For PRs, we need to run on the real PR head, not the resultant merge of the PR into the target branch.\n          #\n          # This is necessary for coverage reporting to make sense; we then get exactly the coverage change\n          # between the base branch and the real PR head.\n          #\n          # If it were run on the merge commit the problem is that the coverage potentially does not align\n          # with the commit diff, because the merge may affect line numbers.\n          ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}\n\n      # installs using setup-python do not work for arm macOS 3.9 and below\n      - if: ${{ !(inputs.os == 'macos-latest' && contains(fromJSON('[\"3.7\", \"3.8\", \"3.9\"]'), inputs.python-version) && inputs.python-architecture == 'x64') }}\n        name: Set up Python ${{ inputs.python-version }}\n        uses: actions/setup-python@v6\n        with:\n          python-version: ${{ inputs.python-version }}\n          architecture: ${{ inputs.python-architecture }}\n          # PyPy can have FFI changes within Python versions, which creates pain in CI\n          check-latest: ${{ startsWith(inputs.python-version, 'pypy') }}\n\n      # workaround for the above, only available for 3.9\n      - if: ${{ inputs.os == 'macos-latest' && contains(fromJSON('[\"3.9\"]'), inputs.python-version) && inputs.python-architecture == 'x64' }}\n        name: Set up Python ${{ inputs.python-version }}\n        uses: astral-sh/setup-uv@v7\n        with:\n          python-version: cpython-${{ inputs.python-version }}-macos-x86-64\n          save-cache: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n\n      - name: Install nox\n        run: python -m pip install --upgrade pip && pip install nox[uv]\n\n      - name: Install Rust toolchain\n        uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ inputs.rust }}\n          targets: ${{ inputs.rust-target }}\n          # rust-src needed to correctly format errors, see #1865\n          components: rust-src,llvm-tools-preview\n\n      # On windows 32 bit, we are running on an x64 host, so we need to specifically set the target\n      # NB we don't do this for *all* jobs because it breaks coverage of proc macros to have an\n      # explicit target set.\n      - name: Set Rust target for Windows 32-bit\n        if: inputs.os == 'windows-latest' && inputs.python-architecture == 'x86'\n        shell: bash\n        run: |\n          echo \"CARGO_BUILD_TARGET=i686-pc-windows-msvc\" >> $GITHUB_ENV\n\n      # windows on arm image contains x86-64 libclang\n      - name: Install LLVM and Clang\n        if: inputs.os == 'windows-11-arm'\n        uses: KyleMayes/install-llvm-action@v2\n        with:\n          # to match windows-2022 images\n          version: \"18\"\n\n      - name: Install zoneinfo backport for Python 3.7 / 3.8\n        if: contains(fromJSON('[\"3.7\", \"3.8\"]'), inputs.python-version)\n        run: python -m pip install backports.zoneinfo\n\n      - uses: Swatinem/rust-cache@v2\n        with:\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n\n      - if: inputs.os == 'ubuntu-latest'\n        name: Prepare LD_LIBRARY_PATH (Ubuntu only)\n        run: echo LD_LIBRARY_PATH=${pythonLocation}/lib >> $GITHUB_ENV\n\n      - if: inputs.rust == inputs.MSRV\n        name: Prepare MSRV package versions\n        run: nox -s set-msrv-package-versions\n\n      - if: inputs.rust != 'stable'\n        name: Ignore changed error messages when using trybuild\n        run: echo \"TRYBUILD=overwrite\" >> \"$GITHUB_ENV\"\n\n      - uses: dorny/paths-filter@v4\n        if: ${{ inputs.rust == 'stable' && !startsWith(inputs.python-version, 'graalpy') }}\n        id: ffi-changes\n        with:\n          base: ${{ github.event.merge_group.base_ref }}\n          ref: ${{ github.event.merge_group.head_ref }}\n          filters: |\n            changed:\n              - 'pyo3-ffi/**'\n              - 'pyo3-ffi-check/**'\n              - '.github/workflows/ci.yml'\n              - '.github/workflows/build.yml'\n\n      - name: Run pyo3-ffi-check\n        # TODO: investigate graalpy failures\n        if: ${{ endsWith(inputs.python-version, '-dev') || (steps.ffi-changes.outputs.changed == 'true' && inputs.rust == 'stable' && !startsWith(inputs.python-version, 'graalpy')) }}\n        run: nox -s ffi-check\n\n      - name: Install cargo-llvm-cov\n        uses: taiki-e/install-action@cargo-llvm-cov\n\n      - name: Prepare coverage environment\n        run: |\n          cargo llvm-cov clean --workspace --profraw-only\n          nox -s set-coverage-env\n\n      - name: Build docs\n        run: nox -s docs\n\n      - name: Run Rust tests\n        run: nox -s test-rust\n\n      - name: Test python examples and tests\n        shell: bash\n        run: nox -s test-py\n        env:\n          CARGO_TARGET_DIR: ${{ github.workspace }}/target\n\n      - name: Generate coverage report\n        # needs investigation why llvm-cov fails on windows-11-arm\n        continue-on-error: ${{ inputs.os == 'windows-11-arm' }}\n        run: cargo llvm-cov\n          --package=pyo3\n          --package=pyo3-build-config\n          --package=pyo3-macros-backend\n          --package=pyo3-macros\n          --package=pyo3-ffi\n          report --codecov --output-path coverage.json\n\n      - name: Upload coverage report\n        uses: codecov/codecov-action@v5\n        # needs investigation why llvm-cov fails on windows-11-arm\n        continue-on-error: ${{ inputs.os == 'windows-11-arm' }}\n        with:\n          files: coverage.json\n          name: ${{ inputs.os }}/${{ inputs.python-version }}/${{ inputs.rust }}\n          token: ${{ secrets.CODECOV_TOKEN }}\n\n    env:\n      CARGO_TERM_VERBOSE: ${{ inputs.verbose }}\n      RUST_BACKTRACE: 1\n      RUSTFLAGS: \"-D warnings\"\n      RUSTDOCFLAGS: \"-D warnings\"\n"
  },
  {
    "path": ".github/workflows/cache-cleanup.yml",
    "content": "name: CI Cache Cleanup\non:\n  pull_request_target:\n    types:\n      - closed\n\njobs:\n  cleanup:\n    runs-on: ubuntu-latest\n    permissions:\n      actions: write\n    steps:\n      - name: Cleanup\n        run: |\n          gh extension install actions/gh-actions-cache\n\n          echo \"Fetching list of cache key\"\n          cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )\n\n          ## Setting this to not fail the workflow while deleting cache keys.\n          set +e\n          echo \"Deleting caches...\"\n          for cacheKey in $cacheKeysForPR\n          do\n              gh actions-cache delete -R $REPO -B $BRANCH --confirm -- $cacheKey\n          done\n          echo \"Done\"\n        env:\n          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          REPO: ${{ github.repository }}\n          BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge\n"
  },
  {
    "path": ".github/workflows/changelog.yml",
    "content": "name: changelog\n\non:\n  pull_request:\n    types: [opened, synchronize, labeled, unlabeled, edited]\n\njobs:\n  check:\n    name: Check changelog entry\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: '3.14'\n      - run: python -m pip install --upgrade pip && pip install nox[uv]\n      - run: nox -s check-changelog\n"
  },
  {
    "path": ".github/workflows/ci-cache-warmup.yml",
    "content": "name: CI Cache Warmup\n\non:\n  push:\n    branches:\n      - main\n\njobs:\n  cross-compilation-windows:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - uses: dtolnay/rust-toolchain@stable\n        with:\n          targets: x86_64-pc-windows-gnu,x86_64-pc-windows-msvc\n          components: rust-src\n      - uses: actions/cache/restore@v5\n        with:\n          # https://github.com/PyO3/maturin/discussions/1953\n          path: ~/.cache/cargo-xwin\n          key: cargo-xwin-cache\n      - name: Test cross compile to Windows\n        run: |\n          set -ex\n          sudo apt-get install -y mingw-w64 llvm\n          pip install nox\n          nox -s test-cross-compilation-windows\n      - uses: actions/cache/save@v5\n        with:\n          path: ~/.cache/cargo-xwin\n          key: cargo-xwin-cache\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  pull_request:\n  merge_group:\n    types: [checks_requested]\n  workflow_dispatch:\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref_name }}\n  cancel-in-progress: true\n\nenv:\n  CARGO_TERM_COLOR: always\n\njobs:\n  fmt:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - run: python -m pip install --upgrade pip && pip install nox[uv]\n      - uses: dtolnay/rust-toolchain@stable\n        with:\n          components: rustfmt\n      - name: Check python formatting and lints (ruff)\n        run: nox -s ruff\n      - name: Check rust formatting (rustfmt)\n        run: nox -s rustfmt\n      - name: Check markdown formatting (rumdl)\n        run: nox -s rumdl\n\n  resolve:\n    runs-on: ubuntu-latest\n    outputs:\n      MSRV: ${{ steps.resolve-msrv.outputs.MSRV }}\n      verbose: ${{ runner.debug == '1' }}\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - name: resolve MSRV\n        id: resolve-msrv\n        run: echo MSRV=`python -c 'import tomllib; print(tomllib.load(open(\"Cargo.toml\", \"rb\"))[\"workspace\"][\"package\"][\"rust-version\"])'` >> $GITHUB_OUTPUT\n\n  semver-checks:\n    if: github.event_name == 'pull_request'\n    needs: [fmt]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - name: Fetch merge base\n        id: fetch_merge_base\n        uses: ./.github/actions/fetch-merge-base\n        with:\n          base_ref: \"refs/heads/${{ github.event.pull_request.base.ref }}\"\n          head_ref: \"refs/pull/${{ github.event.pull_request.number }}/merge\"\n      - uses: obi1kenobi/cargo-semver-checks-action@v2\n        with:\n          baseline-rev: ${{ steps.fetch_merge_base.outputs.merge_base }}\n\n  check-msrv:\n    needs: [fmt, resolve]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ needs.resolve.outputs.MSRV }}\n          components: rust-src\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - uses: Swatinem/rust-cache@v2\n        with:\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - run: python -m pip install --upgrade pip && pip install nox[uv]\n      # This is a smoke test to confirm that CI will run on MSRV (including dev dependencies)\n      - name: Check with MSRV package versions\n        run: |\n          nox -s set-msrv-package-versions\n          nox -s check-all\n\n    env:\n      CARGO_BUILD_TARGET: x86_64-unknown-linux-gnu\n\n  clippy:\n    needs: [fmt]\n    runs-on: ubuntu-24.04-arm\n    strategy:\n      # If one platform fails, allow the rest to keep testing if `CI-no-fail-fast` label is present\n      fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }}\n      matrix:\n        rust: [stable]\n        target:\n          [\n            \"aarch64-apple-darwin\",\n            \"x86_64-unknown-linux-gnu\",\n            \"aarch64-unknown-linux-gnu\",\n            \"powerpc64le-unknown-linux-gnu\",\n            \"s390x-unknown-linux-gnu\",\n            \"wasm32-wasip1\",\n            \"x86_64-pc-windows-msvc\",\n            \"i686-pc-windows-msvc\",\n            \"aarch64-pc-windows-msvc\",\n          ]\n        include:\n          # Run beta clippy as a way to detect any incoming lints which may affect downstream users\n          - rust: beta\n            target: \"x86_64-unknown-linux-gnu\"\n    name: clippy/${{ matrix.target }}/${{ matrix.rust }}\n    continue-on-error: ${{ matrix.rust != 'stable' }}\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: ${{ matrix.rust }}\n          targets: ${{ matrix.target }}\n          components: clippy,rust-src\n      - uses: astral-sh/setup-uv@v7\n        with:\n          save-cache: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - run: uvx nox -s clippy-all\n    env:\n      CARGO_BUILD_TARGET: ${{ matrix.target }}\n\n  build-pr:\n    if: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-build-full') && github.event_name == 'pull_request' }}\n    name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }} rust-${{ matrix.rust }}\n    needs: [fmt, resolve]\n    uses: ./.github/workflows/build.yml\n    with:\n      os: ${{ matrix.platform.os }}\n      python-version: ${{ matrix.python-version }}\n      python-architecture: ${{ matrix.platform.python-architecture }}\n      rust: ${{ matrix.rust }}\n      rust-target: ${{ matrix.platform.rust-target }}\n      MSRV: ${{ needs.resolve.outputs.MSRV }}\n      verbose: ${{ needs.resolve.outputs.verbose == 'true' }}\n    secrets: inherit\n    strategy:\n      # If one platform fails, allow the rest to keep testing if `CI-no-fail-fast` label is present\n      fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }}\n      matrix:\n        rust: [stable]\n        python-version: [\"3.14\"]\n        platform:\n          [\n            {\n              os: \"macos-latest\",\n              python-architecture: \"arm64\",\n              rust-target: \"aarch64-apple-darwin\",\n            },\n            {\n              os: \"ubuntu-latest\",\n              python-architecture: \"x64\",\n              rust-target: \"x86_64-unknown-linux-gnu\",\n            },\n            {\n              os: \"ubuntu-24.04-arm\",\n              python-architecture: \"arm64\",\n              rust-target: \"aarch64-unknown-linux-gnu\",\n            },\n            {\n              os: \"windows-latest\",\n              python-architecture: \"x64\",\n              rust-target: \"x86_64-pc-windows-msvc\",\n            },\n            {\n              os: \"windows-latest\",\n              python-architecture: \"x86\",\n              rust-target: \"i686-pc-windows-msvc\",\n            },\n            {\n              os: \"windows-11-arm\",\n              python-architecture: \"arm64\",\n              rust-target: \"aarch64-pc-windows-msvc\",\n            },\n          ]\n        include:\n          # Test nightly Rust on PRs so that PR authors have a chance to fix nightly\n          # failures, as nightly does not block merge.\n          - rust: nightly\n            python-version: \"3.14\"\n            platform:\n              {\n                os: \"ubuntu-latest\",\n                python-architecture: \"x64\",\n                rust-target: \"x86_64-unknown-linux-gnu\",\n              }\n          # Also test free-threaded Python just for latest Python version, on ubuntu\n          # (run for all OSes on build-full)\n          - rust: stable\n            python-version: \"3.14t\"\n            platform:\n              {\n                os: \"ubuntu-latest\",\n                python-architecture: \"x64\",\n                rust-target: \"x86_64-unknown-linux-gnu\",\n              }\n\n  build-full:\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }} rust-${{ matrix.rust }}\n    needs: [fmt, resolve]\n    uses: ./.github/workflows/build.yml\n    with:\n      os: ${{ matrix.platform.os }}\n      python-version: ${{ matrix.python-version }}\n      python-architecture: ${{ matrix.platform.python-architecture }}\n      rust: ${{ matrix.rust }}\n      rust-target: ${{ matrix.platform.rust-target }}\n      MSRV: ${{ needs.resolve.outputs.MSRV }}\n      verbose: ${{ needs.resolve.outputs.verbose == 'true' }}\n    secrets: inherit\n    strategy:\n      # If one platform fails, allow the rest to keep testing if `CI-no-fail-fast` label is present\n      fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }}\n      matrix:\n        rust: [stable]\n        python-version:\n          [\n            \"3.7\",\n            \"3.8\",\n            \"3.9\",\n            \"3.10\",\n            \"3.11\",\n            \"3.12\",\n            \"3.13\",\n            \"3.14\",\n            \"3.14t\",\n            \"3.15-dev\",\n            \"3.15t-dev\",\n            \"pypy3.11\",\n            \"graalpy25.0\",\n          ]\n        platform:\n          [\n            {\n              os: \"macos-latest\",\n              python-architecture: \"arm64\",\n              rust-target: \"aarch64-apple-darwin\",\n            },\n            {\n              os: \"ubuntu-latest\",\n              python-architecture: \"x64\",\n              rust-target: \"x86_64-unknown-linux-gnu\",\n            },\n            {\n              os: \"windows-latest\",\n              python-architecture: \"x64\",\n              rust-target: \"x86_64-pc-windows-msvc\",\n            },\n          ]\n        include:\n          # Test minimal supported Rust version\n          - rust: ${{ needs.resolve.outputs.MSRV }}\n            python-version: \"3.14\"\n            platform:\n              {\n                os: \"ubuntu-latest\",\n                python-architecture: \"x64\",\n                rust-target: \"x86_64-unknown-linux-gnu\",\n              }\n\n          # Test the `nightly` feature\n          - rust: nightly\n            python-version: \"3.14\"\n            platform:\n              {\n                os: \"ubuntu-latest\",\n                python-architecture: \"x64\",\n                rust-target: \"x86_64-unknown-linux-gnu\",\n              }\n\n          # Run rust beta to help catch toolchain regressions\n          - rust: beta\n            python-version: \"3.14\"\n            platform:\n              {\n                os: \"ubuntu-latest\",\n                python-architecture: \"x64\",\n                rust-target: \"x86_64-unknown-linux-gnu\",\n              }\n\n          # Test 32-bit Windows and x64 macOS only with the latest Python version\n          - rust: stable\n            python-version: \"3.14\"\n            platform:\n              {\n                os: \"windows-latest\",\n                python-architecture: \"x86\",\n                rust-target: \"i686-pc-windows-msvc\",\n              }\n          - rust: stable\n            python-version: \"3.14\"\n            platform:\n              {\n                os: \"macos-latest\",\n                python-architecture: \"x64\",\n                rust-target: \"x86_64-apple-darwin\",\n              }\n          # ubuntu-latest (24.04) no longer supports 3.7, so run on 22.04\n          - rust: stable\n            python-version: \"3.7\"\n            platform:\n              {\n                os: \"ubuntu-22.04\",\n                python-architecture: \"x64\",\n                rust-target: \"x86_64-unknown-linux-gnu\",\n              }\n\n          # arm64 macOS Python not available on GitHub Actions until 3.10, test older versions on x64\n          - rust: stable\n            python-version: \"3.7\"\n            platform:\n              {\n                os: \"macos-15-intel\",\n                python-architecture: \"x64\",\n                rust-target: \"x86_64-apple-darwin\",\n              }\n          - rust: stable\n            python-version: \"3.8\"\n            platform:\n              {\n                os: \"macos-15-intel\",\n                python-architecture: \"x64\",\n                rust-target: \"x86_64-apple-darwin\",\n              }\n          - rust: stable\n            python-version: \"3.9\"\n            platform:\n              {\n                os: \"macos-15-intel\",\n                python-architecture: \"x64\",\n                rust-target: \"x86_64-apple-darwin\",\n              }\n          # test latest Python on arm64 linux & windows runners\n          - rust: stable\n            python-version: \"3.14\"\n            platform:\n              {\n                os: \"ubuntu-24.04-arm\",\n                python-architecture: \"arm64\",\n                rust-target: \"aarch64-unknown-linux-gnu\",\n              }\n          - rust: stable\n            python-version: \"3.14\"\n            platform:\n              {\n                os: \"windows-11-arm\",\n                python-architecture: \"arm64\",\n                rust-target: \"aarch64-pc-windows-msvc\",\n              }\n        exclude:\n          # ubuntu-latest (24.04) no longer supports 3.7\n          - python-version: \"3.7\"\n            platform: { os: \"ubuntu-latest\" }\n          # arm64 macOS Python not available on GitHub Actions until 3.10\n          - rust: stable\n            python-version: \"3.7\"\n            platform:\n              {\n                os: \"macos-latest\",\n                python-architecture: \"arm64\",\n                rust-target: \"aarch64-apple-darwin\",\n              }\n          - rust: stable\n            python-version: \"3.8\"\n            platform:\n              {\n                os: \"macos-latest\",\n                python-architecture: \"arm64\",\n                rust-target: \"aarch64-apple-darwin\",\n              }\n          - rust: stable\n            python-version: \"3.9\"\n            platform:\n              {\n                os: \"macos-latest\",\n                python-architecture: \"arm64\",\n                rust-target: \"aarch64-apple-darwin\",\n              }\n\n  valgrind:\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    needs: [fmt]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - uses: Swatinem/rust-cache@v2\n        with:\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - uses: dtolnay/rust-toolchain@stable\n      - uses: taiki-e/install-action@valgrind\n      - run: python -m pip install --upgrade pip && pip install nox[uv]\n      - run: nox -s test-rust -- release skip-full\n    env:\n      CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER: valgrind --leak-check=no --error-exitcode=1\n      RUST_BACKTRACE: 1\n      TRYBUILD: overwrite\n\n  careful:\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    needs: [fmt]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - uses: Swatinem/rust-cache@v2\n        with:\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - uses: dtolnay/rust-toolchain@nightly\n        with:\n          components: rust-src\n      - uses: taiki-e/install-action@cargo-careful\n      - run: python -m pip install --upgrade pip && pip install nox[uv]\n      - run: nox -s test-rust -- careful skip-full\n    env:\n      RUST_BACKTRACE: 1\n      TRYBUILD: overwrite\n\n  docsrs:\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    needs: [fmt]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - uses: Swatinem/rust-cache@v2\n        with:\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - uses: dtolnay/rust-toolchain@nightly\n        with:\n          components: rust-src\n      - run: cargo rustdoc --lib --no-default-features --features full,jiff-02 -Zunstable-options --config \"build.rustdocflags=[\\\"--cfg\\\", \\\"docsrs\\\"]\"\n\n  emscripten:\n    name: emscripten\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    needs: [fmt]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: 3.14\n        id: setup-python\n      - name: Install Rust toolchain\n        uses: dtolnay/rust-toolchain@stable\n        with:\n          targets: wasm32-unknown-emscripten\n          components: rust-src\n      - uses: actions/setup-node@v6\n        with:\n          node-version: 24\n      - run: python -m pip install --upgrade pip && pip install nox[uv]\n      - uses: actions/cache/restore@v5\n        id: cache\n        with:\n          path: |\n            .nox/emscripten\n          key: emscripten-${{ hashFiles('emscripten/*') }}-${{ hashFiles('noxfile.py') }}-${{ steps.setup-python.outputs.python-path }}\n      - uses: Swatinem/rust-cache@v2\n        with:\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - name: Build\n        if: steps.cache.outputs.cache-hit != 'true'\n        run: nox -s build-emscripten\n      - name: Test\n        run: nox -s test-emscripten\n      - uses: actions/cache/save@v5\n        if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n        with:\n          path: |\n            .nox/emscripten\n          key: emscripten-${{ hashFiles('emscripten/*') }}-${{ hashFiles('noxfile.py') }}-${{ steps.setup-python.outputs.python-path }}\n\n  wasm32-wasip1:\n    name: wasm32-wasip1\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    needs: [fmt]\n    runs-on: ubuntu-latest\n    env:\n      WASI_SDK_PATH: \"/opt/wasi-sdk\"\n      CPYTHON_PATH: \"${{ github.workspace }}/wasi/cpython\"\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: 3.14\n        id: setup-python\n      - name: Install Rust toolchain\n        uses: dtolnay/rust-toolchain@stable\n        with:\n          targets: wasm32-wasip1\n          components: rust-src\n      - name: \"Install wasmtime\"\n        uses: bytecodealliance/actions/wasmtime/setup@v1\n      - name: \"Install WASI SDK\"\n        run: |\n          mkdir ${{ env.WASI_SDK_PATH }} && \\\n          curl -s -S --location https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-24/wasi-sdk-24.0-x86_64-linux.tar.gz | \\\n          tar --strip-components 1 --directory ${{ env.WASI_SDK_PATH }} --extract --gunzip\n          $WASI_SDK_PATH/bin/clang --version\n      - uses: actions/cache/restore@v5\n        id: cache-wasip1-python\n        with:\n          path: ${{ env.CPYTHON_PATH }}/cross-build/\n          key: wasm32-wasip1-python\n      - uses: actions/checkout@v6.0.2\n        with:\n          repository: python/cpython\n          ref: 3.14\n          path: ${{ env.CPYTHON_PATH }}\n          fetch-depth: 1\n      - name: Build\n        run: |\n          cd ${{ env.CPYTHON_PATH }}\n          cat >> Tools/wasm/wasi/config.site-wasm32-wasi <<'EOF'\n\n          # Force-disable POSIX dynamic loading for WASI\n          ac_cv_func_dlopen=no\n          ac_cv_lib_dl_dlopen=no\n          EOF\n          python Tools/wasm/wasi build --quiet -- --config-cache\n          cp cross-build/wasm32-wasip1/libpython3.14.a \\\n             cross-build/wasm32-wasip1/Modules/_hacl/libHacl_HMAC.a \\\n             cross-build/wasm32-wasip1/Modules/_decimal/libmpdec/libmpdec.a \\\n             cross-build/wasm32-wasip1/Modules/expat/libexpat.a \\\n             cross-build/wasm32-wasip1/build/lib.wasi-wasm32-3.14/\n      - uses: Swatinem/rust-cache@v2\n        with:\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - name: Test\n        env:\n          PYO3_CROSS_LIB_DIR: ${{ env.CPYTHON_PATH }}/cross-build/wasm32-wasip1/build/lib.wasi-wasm32-3.14/\n          CARGO_BUILD_TARGET: wasm32-wasip1\n          CARGO_TARGET_WASM32_WASIP1_RUNNER: wasmtime run --dir ${{ env.CPYTHON_PATH }}::/ --env PYTHONPATH=/lib\n          RUSTFLAGS: >\n            -C link-arg=-L${{ env.WASI_SDK_PATH }}/share/wasi-sysroot/lib/wasm32-wasi\n            -C link-arg=-lwasi-emulated-signal\n            -C link-arg=-lwasi-emulated-process-clocks\n            -C link-arg=-lwasi-emulated-getpid\n            -C link-arg=-lmpdec\n            -C link-arg=-lHacl_HMAC\n            -C link-arg=-lexpat\n        run: RUSTDOCFLAGS=$RUSTFLAGS cargo test\n      - uses: actions/cache/save@v5\n        if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n        with:\n          path: ${{ env.CPYTHON_PATH }}/cross-build/\n          key: ${{ steps.cache-wasip1-python.outputs.cache-primary-key }}\n\n  test-debug:\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    needs: [fmt]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: Swatinem/rust-cache@v2\n        with:\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - uses: dtolnay/rust-toolchain@stable\n        with:\n          components: rust-src\n      - name: Install python3 standalone debug build with nox\n        run: |\n          PBS_RELEASE=\"20241219\"\n          PBS_PYTHON_VERSION=\"3.13.1\"\n          PBS_ARCHIVE=\"cpython-${PBS_PYTHON_VERSION}+${PBS_RELEASE}-x86_64-unknown-linux-gnu-debug-full.tar.zst\"\n          wget \"https://github.com/indygreg/python-build-standalone/releases/download/${PBS_RELEASE}/${PBS_ARCHIVE}\"\n          tar -I zstd -xf \"${PBS_ARCHIVE}\"\n          ls -l $(pwd)/python/install/bin\n          ls -l $(pwd)/python/install/lib\n          echo PATH=$(pwd)/python/install/bin:$PATH >> $GITHUB_ENV\n          echo LD_LIBRARY_PATH=$(pwd)/python/install/lib:$LD_LIBRARY_PATH >> $GITHUB_ENV\n          echo PYTHONHOME=$(pwd)/python/install >> $GITHUB_ENV\n          echo PYO3_PYTHON=$(pwd)/python/install/bin/python3 >> $GITHUB_ENV\n      - run: python3 -m sysconfig\n      - run: python3 -m pip install --upgrade pip && pip install nox[uv]\n      - run: |\n          PYO3_CONFIG_FILE=$(mktemp)\n          cat > $PYO3_CONFIG_FILE << EOF\n          implementation=CPython\n          version=3.13\n          shared=true\n          abi3=false\n          lib_name=python3.13d\n          lib_dir=${{ github.workspace }}/python/install/lib\n          executable=${{ github.workspace }}/python/install/bin/python3\n          pointer_width=64\n          build_flags=Py_DEBUG,Py_REF_DEBUG\n          suppress_build_script_link_lines=false\n          EOF\n          echo PYO3_CONFIG_FILE=$PYO3_CONFIG_FILE >> $GITHUB_ENV\n      - run: python3 -m nox -s test\n\n  test-version-limits:\n    needs: [fmt]\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - uses: Swatinem/rust-cache@v2\n        with:\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - uses: dtolnay/rust-toolchain@stable\n      - run: python3 -m pip install --upgrade pip && pip install nox[uv]\n      - run: python3 -m nox -s test-version-limits\n\n  check-feature-powerset:\n    needs: [fmt, resolve]\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    runs-on: ubuntu-latest\n    name: check-feature-powerset ${{ matrix.rust }}\n    strategy:\n      # run on stable and MSRV to check that all combinations of features are expected to build fine on our supported\n      # range of compilers\n      matrix:\n        rust: [\"stable\"]\n        include:\n          - rust: ${{ needs.resolve.outputs.MSRV }}\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - uses: Swatinem/rust-cache@v2\n        with:\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - uses: dtolnay/rust-toolchain@master\n        with:\n          toolchain: stable\n      - uses: taiki-e/install-action@v2\n        with:\n          tool: cargo-hack,cargo-minimal-versions\n      - run: python3 -m pip install --upgrade pip && pip install nox[uv]\n      - run: python3 -m nox -s check-feature-powerset -- ${{ matrix.rust != 'stable' && 'minimal-versions' || '' }}\n\n  test-cross-compilation:\n    needs: [fmt]\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    runs-on: ${{ matrix.os }}\n    name: test-cross-compilation ${{ matrix.os }} -> ${{ matrix.target }}\n    strategy:\n      # If one platform fails, allow the rest to keep testing if `CI-no-fail-fast` label is present\n      fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }}\n      matrix:\n        include:\n          # ubuntu \"cross compile\" to itself\n          - os: \"ubuntu-latest\"\n            target: \"x86_64-unknown-linux-gnu\"\n            flags: \"-i python3.13\"\n            manylinux: auto\n          # ubuntu x86_64 -> aarch64\n          - os: \"ubuntu-latest\"\n            target: \"aarch64-unknown-linux-gnu\"\n            flags: \"-i python3.13\"\n            manylinux: auto\n          # ubuntu x86_64 -> windows x86_64\n          - os: \"ubuntu-latest\"\n            target: \"x86_64-pc-windows-gnu\"\n            # TODO: remove pyo3/generate-import-lib feature when maturin supports cross compiling to Windows without it\n            flags: \"-i python3.13 --features pyo3/generate-import-lib\"\n          # windows x86_64 -> aarch64\n          - os: \"windows-latest\"\n            target: \"aarch64-pc-windows-msvc\"\n            flags: \"-i python3.13 --features pyo3/generate-import-lib\"\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - uses: Swatinem/rust-cache@v2\n        with:\n          workspaces: examples/maturin-starter\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n          key: ${{ matrix.target }}\n      - name: Setup cross-compiler\n        if: ${{ matrix.target == 'x86_64-pc-windows-gnu' }}\n        run: sudo apt-get install -y mingw-w64 llvm\n      - name: Compile version-specific library\n        uses: PyO3/maturin-action@v1\n        with:\n          target: ${{ matrix.target }}\n          manylinux: ${{ matrix.manylinux }}\n          args: --release -m examples/maturin-starter/Cargo.toml ${{ matrix.flags }}\n      - name: Compile abi3 library\n        uses: PyO3/maturin-action@v1\n        with:\n          target: ${{ matrix.target }}\n          manylinux: ${{ matrix.manylinux }}\n          args: --release -m examples/maturin-starter/Cargo.toml --features abi3 ${{ matrix.flags }}\n\n  test-cross-compilation-windows:\n    needs: [fmt]\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - uses: dtolnay/rust-toolchain@stable\n        with:\n          targets: x86_64-pc-windows-gnu,x86_64-pc-windows-msvc\n          components: rust-src\n      # load cache (prepared in ci-cache-warmup.yml)\n      - uses: actions/cache/restore@v5\n        with:\n          path: ~/.cache/cargo-xwin\n          key: cargo-xwin-cache\n      - name: Test cross compile to Windows\n        run: |\n          set -ex\n          sudo apt-get install -y mingw-w64 llvm\n          pip install nox\n          nox -s test-cross-compilation-windows\n\n  test-introspection:\n    needs: [fmt]\n    if: ${{ contains(github.event.pull_request.labels.*.name, 'CI-test-introspection') || contains(github.event.pull_request.labels.*.name, 'CI-build-full') || github.event_name != 'pull_request' }}\n    strategy:\n      matrix:\n        platform:\n          [\n            {\n              os: \"macos-latest\",\n              python-architecture: \"arm64\",\n              rust-target: \"aarch64-apple-darwin\",\n            },\n            {\n              os: \"ubuntu-latest\",\n              python-architecture: \"x64\",\n              rust-target: \"x86_64-unknown-linux-gnu\",\n            },\n            {\n              os: \"windows-latest\",\n              python-architecture: \"x64\",\n              rust-target: \"x86_64-pc-windows-msvc\",\n            },\n            {\n              os: \"windows-latest\",\n              python-architecture: \"x86\",\n              rust-target: \"i686-pc-windows-msvc\",\n            },\n          ]\n    runs-on: ${{ matrix.platform.os }}\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: dtolnay/rust-toolchain@stable\n        with:\n          targets: ${{ matrix.platform.rust-target }}\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n          architecture: ${{ matrix.platform.python-architecture }}\n      - uses: Swatinem/rust-cache@v2\n        with:\n          save-if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n      - run: python -m pip install --upgrade pip && pip install nox[uv]\n      - run: nox -s test-introspection\n    env:\n      CARGO_BUILD_TARGET: ${{ matrix.platform.rust-target }}\n\n  test-introspection-pr:\n    needs: [fmt]\n    if: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-build-full') && github.event_name == 'pull_request' }}\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: dtolnay/rust-toolchain@stable\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - run: python -m pip install --upgrade pip && pip install nox[uv]\n      - run: nox -s test-introspection\n\n  mypy-pytests:\n    needs: [fmt]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: dtolnay/rust-toolchain@stable\n        with:\n          components: rust-src\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n      - run: python -m pip install --upgrade pip && pip install nox[uv]\n      - run: nox -s mypy\n        working-directory: pytests\n\n  conclusion:\n    needs:\n      - fmt\n      - check-msrv\n      - clippy\n      - build-pr\n      - build-full\n      - valgrind\n      - careful\n      - docsrs\n      - emscripten\n      - test-debug\n      - test-version-limits\n      - check-feature-powerset\n      - test-cross-compilation\n      - test-cross-compilation-windows\n      - test-introspection\n    if: always()\n    runs-on: ubuntu-latest\n    steps:\n      - name: Result\n        run: |\n          jq -C <<< \"${needs}\"\n          # Check if all needs were successful or skipped.\n          \"$(jq -r 'all(.result as $result | ([\"success\", \"skipped\"] | contains([$result])))' <<< \"${needs}\")\"\n        env:\n          needs: ${{ toJson(needs) }}\n"
  },
  {
    "path": ".github/workflows/coverage-pr-base.yml",
    "content": "# This runs as a separate job because it needs to run on the `pull_request_target` event\n# in order to access the CODECOV_TOKEN secret.\n#\n# This is safe because this doesn't run arbitrary code from PRs.\n\nname: Set Codecov PR base\non:\n  # See safety note / doc at the top of this file.\n  pull_request_target:\n\njobs:\n  coverage-pr-base:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: '3.14'\n      - name: Fetch merge base\n        id: fetch_merge_base\n        uses: ./.github/actions/fetch-merge-base\n        with:\n          base_ref: \"refs/heads/${{ github.event.pull_request.base.ref }}\"\n          head_ref: \"refs/pull/${{ github.event.pull_request.number }}/head\"\n      - name: Set PR base on codecov\n        run: |\n          pip install codecov-cli\n          codecovcli pr-base-picking \\\n            --base-sha ${{ steps.fetch_merge_base.outputs.merge_base }} \\\n            --pr ${{ github.event.number }} \\\n            --slug PyO3/pyo3 \\\n            --token ${{ secrets.CODECOV_TOKEN }} \\\n            --service github\n"
  },
  {
    "path": ".github/workflows/netlify-build.yml",
    "content": "name: netlify-build\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n  release:\n    types: [published]\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}\n  cancel-in-progress: true\n\nenv:\n  CARGO_TERM_COLOR: always\n\njobs:\n  guide-build:\n    runs-on: ubuntu-latest\n    outputs:\n      tag_name: ${{ steps.prepare_tag.outputs.tag_name }}\n    steps:\n      - uses: actions/checkout@v6.0.2\n      - uses: actions/setup-python@v6\n        with:\n          python-version: \"3.14\"\n\n      - uses: dtolnay/rust-toolchain@nightly\n\n      - name: Setup mdBook\n        uses: taiki-e/install-action@v2\n        with:\n          tool: mdbook@0.5, mdbook-tabs@0.3, lychee\n\n      - name: Prepare tag\n        id: prepare_tag\n        run: |\n          TAG_NAME=\"${GITHUB_REF##*/}\"\n          echo \"tag_name=${TAG_NAME}\" >> $GITHUB_OUTPUT\n\n      - name: Restore lychee cache\n        id: restore-cache\n        uses: actions/cache/restore@v5\n        with:\n          path: .lycheecache\n          key: lychee\n\n      # This builds the book in target/guide/.\n      - name: Build the guide\n        run: |\n          python -m pip install --upgrade pip && pip install nox[uv]\n          nox -s ${{ github.event_name == 'release' && 'build-guide' || 'check-guide' }}\n        env:\n          PYO3_VERSION_TAG: ${{ steps.prepare_tag.outputs.tag_name }}\n          # allows lychee to get better rate limits from github\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n\n      - name: Save lychee cache\n        uses: actions/cache/save@v5\n        if: ${{ github.ref == 'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'CI-save-pr-cache') }}\n        with:\n          path: .lycheecache\n          key: ${{ steps.restore-cache.outputs.cache-primary-key }}\n\n      # We store the versioned guides on GitHub's gh-pages branch for convenience\n      # (the full gh-pages branch is pulled in the build-netlify-site step)\n      - name: Deploy the guide\n        if: ${{ github.event_name == 'release' }}\n        uses: peaceiris/actions-gh-pages@v4\n        with:\n          github_token: ${{ secrets.GITHUB_TOKEN }}\n          publish_dir: ./target/guide/\n          destination_dir: ${{ steps.prepare_tag.outputs.tag_name }}\n          full_commit_message: \"Upload documentation for ${{ steps.prepare_tag.outputs.tag_name }}\"\n\n      - name: Get current PyO3 version\n        run: |\n          PYO3_VERSION=$(cargo search pyo3 --limit 1 | head -1 | tr -s ' ' | cut -d ' ' -f 3 | tr -d '\"')\n          echo \"PYO3_VERSION=${PYO3_VERSION}\" >> $GITHUB_ENV\n\n      - name: Build the site\n        run: |\n          python -m pip install --upgrade pip && pip install nox[uv] towncrier requests\n          nox -s build-netlify-site -- ${{ (github.ref != 'refs/heads/main' && '--preview') || '' }}\n\n      # Upload the built site as an artifact for deploy workflow to consume\n      - name: Upload Build Artifact\n        uses: actions/upload-artifact@v7\n        with:\n          name: site\n          path: ./netlify_build\n"
  },
  {
    "path": ".github/workflows/netlify-deploy.yml",
    "content": "# This runs as a separate job because it needs to run on the `workflow_run` event\n# in order to access the netlify secrets.\n#\n# This is safe because this doesn't run arbitrary code from PRs.\n\nname: netlify-deploy\n\non:\n  workflow_run:\n    workflows: [\"netlify-build\"]\n    types:\n      - completed\n\nenv:\n  CARGO_TERM_COLOR: always\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    if: github.event.workflow_run.conclusion == 'success'\n    environment: netlify\n\n    steps:\n      - name: Download Build Artifact\n        uses: actions/download-artifact@v8\n        with:\n          name: site\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          run-id: ${{ github.event.workflow_run.id }}\n\n      - name: Install netlify-cli\n        run: |\n          npm install -g netlify-cli\n\n      - name: Deploy to Netlify\n        run: |\n          ls -la\n          DEBUG=* netlify deploy \\\n              --site ${{ secrets.NETLIFY_SITE_ID }} \\\n              --auth ${{ secrets.NETLIFY_TOKEN }} \\\n              ${{ ((github.event.workflow_run.head_repository.full_name == 'PyO3/pyo3') && (github.event.workflow_run.head_branch == 'main') && '--prod') || '' }} \\\n              --json | tee deploy_output.json\n\n      # credit: https://www.raulmelo.me/en/blog/deploying-netlify-github-actions-guide\n      - name: Generate URL Preview\n        id: url_preview\n        if: ${{ github.event.workflow_run.event == 'pull_request' }}\n        run: |\n          NETLIFY_PREVIEW_URL=$(jq -r '.deploy_url' deploy_output.json)\n          echo \"NETLIFY_PREVIEW_URL=$NETLIFY_PREVIEW_URL\" >> \"$GITHUB_OUTPUT\"\n\n      - name: Post Netlify Preview Status to PR\n        if: ${{ github.event.workflow_run.event == 'pull_request' }}\n        uses: actions/github-script@v8\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          script: |\n            const previewUrl = '${{ steps.url_preview.outputs.NETLIFY_PREVIEW_URL }}';\n            const commitSha = '${{ github.event.workflow_run.head_sha }}';\n\n            await github.rest.repos.createCommitStatus({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              sha: commitSha,\n              state: 'success',\n              target_url: previewUrl,\n              description: 'click to view Netlify preview deploy',\n              context: 'netlify-deploy / preview'\n            });\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release Rust Crate\n\non:\n  push:\n    tags:\n      - \"v*\"\n  workflow_dispatch:\n    inputs:\n      version:\n        description: The version to build\n\njobs:\n  release:\n    permissions:\n      id-token: write\n\n    runs-on: ubuntu-latest\n    environment: release\n    steps:\n      - uses: actions/checkout@0c366fd6a839edf440554fa01a7085ccba70ac98 # v5.0.1\n        with:\n          # The tag to build or the tag received by the tag event\n          ref: ${{ github.event.inputs.version || github.ref }}\n          persist-credentials: false\n\n      - uses: astral-sh/setup-uv@v7\n        with:\n          save-cache: false\n\n      - uses: rust-lang/crates-io-auth-action@v1\n        id: auth\n\n      - name: Publish to crates.io\n        run: uvx nox -s publish\n        env:\n          CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}\n"
  },
  {
    "path": ".gitignore",
    "content": "target\nCargo.lock\n/doc\n/gh-pages\nbuild/\n*.py[co]\n__pycache__/\n.cache\n.pytest_cache/\ndist/\n.tox/\n.mypy_cache/\n.hypothesis/\n.eggs/\nvenv*\nguide/book/\nguide/src/LICENSE-APACHE\nguide/src/LICENSE-MIT\n*.so\n*.out\n*.egg-info\nextensions/stamps/\npip-wheel-metadata\nvalgrind-python.supp\n*.pyd\nlcov.info\ncoverage.json\nnetlify_build/\n.nox/\n.vscode/\n.lycheecache\n"
  },
  {
    "path": ".netlify/internal_banner.html",
    "content": "<div id='pyo3-internal-banner'>\n    <div style=\"white-space: nowrap;\">\n        ⚠️ Internal Docs ⚠️ Not Public API 👉\n        <a href='https://pyo3.rs/main/doc/pyo3/index.html' style='color:red;text-decoration:underline;'>\n            Official Docs Here\n        </a>\n    </div>\n    <style id=\"pyo3-noscript-style\">\n        body {\n            padding-top: 2em;\n        }\n    </style>\n    <style>\n        #pyo3-internal-banner {\n            position: fixed;\n            display: flex;\n            align-items: center;\n            justify-content:\n                center;\n            z-index: 99999;\n            color: red;\n            left: 0;\n            right: 0;\n            top: 0;\n            height: 2em;\n            border: 3px solid red;\n            width: 100%;\n            overflow-x: hidden;\n            background-color: var(--target-background-color);\n        }\n\n        @media (max-width: 700px) {\n            #pyo3-internal-banner {\n                top: 50px;\n                margin-bottom: 10px;\n            }\n        }\n    </style>\n</div>\n<script>\n    // when javascript is active, splice the banner into a \"sticky\" location\n    // inside the doc body for best appearance\n    banner = document.getElementById(\"pyo3-internal-banner\")\n    banner.style.position = \"sticky\"\n    document.getElementsByTagName(\"main\")[0].prepend(banner)\n    document.getElementById(\"pyo3-noscript-style\").remove()\n</script>\n"
  },
  {
    "path": ".netlify/redirect.sh",
    "content": "# Add redirect for each documented version\nset +x  # these loops get very spammy and fill the deploy log\n\nfor d in netlify_build/v*; do\n    version=\"${d/netlify_build\\/v/}\"\n    echo \"/v$version/doc/* https://docs.rs/pyo3/$version/:splat\" >> netlify_build/_redirects\n    if [ $version != $PYO3_VERSION ]; then\n        # for old versions, mark the files in the latest version as the canonical URL\n        for file in $(find $d -type f); do\n            file_path=\"${file/$d\\//}\"\n            # remove index.html and/or .html suffix to match the page URL on the\n            # final netlfiy site\n            url_path=\"$file_path\"\n            if [[ $file_path == index.html ]]; then\n                url_path=\"\"\n            elif [[ $file_path == *.html ]]; then\n                url_path=\"${file_path%.html}\"\n            fi\n            echo \"/v$version/$url_path\" >> netlify_build/_headers\n            if test -f \"netlify_build/v$PYO3_VERSION/$file_path\"; then\n                echo \"  Link: <https://pyo3.rs/v$PYO3_VERSION/$url_path>; rel=\\\"canonical\\\"\" >> netlify_build/_headers\n            else\n                # this file doesn't exist in the latest guide, don't index it\n                echo \"  X-Robots-Tag: noindex\" >> netlify_build/_headers\n            fi\n        done\n    fi\ndone\n\n# Add latest redirect\necho \"/latest/* /v${PYO3_VERSION}/:splat 302\" >> netlify_build/_redirects\n\n# some backwards compatbiility redirects\necho \"/latest/building_and_distribution/* /latest/building-and-distribution/:splat 302\" >> netlify_build/_redirects\necho \"/latest/building-and-distribution/multiple_python_versions/* /latest/building-and-distribution/multiple-python-versions:splat 302\" >> netlify_build/_redirects\necho \"/latest/function/error_handling/* /latest/function/error-handling/:splat 302\" >> netlify_build/_redirects\necho \"/latest/getting_started/* /latest/getting-started/:splat 302\" >> netlify_build/_redirects\necho \"/latest/python_from_rust/* /latest/python-from-rust/:splat 302\" >> netlify_build/_redirects\necho \"/latest/python_typing_hints/* /latest/python-typing-hints/:splat 302\" >> netlify_build/_redirects\necho \"/latest/trait_bounds/* /latest/trait-bounds/:splat 302\" >> netlify_build/_redirects\n\n## Add landing page redirect\nif [ \"${CONTEXT}\" == \"deploy-preview\" ]; then\n    echo \"/ /main/\" >> netlify_build/_redirects\nelse\n    echo \"/ /v${PYO3_VERSION}/ 302\" >> netlify_build/_redirects\nfi\n\nset -x"
  },
  {
    "path": ".towncrier.template.md",
    "content": "{% for section_text, section in sections.items() %}{%- if section %}{{section_text}}{% endif -%}\n\n{% if section %}\n{% for category in ['packaging', 'added', 'changed', 'removed', 'fixed' ] if category in section %}\n\n### {{ definitions[category]['name'] }}\n\n{% if definitions[category]['showcontent'] %}\n{% for text, pull_requests in section[category].items() %}\n- {{ text }} {{ pull_requests|join(', ') }}\n{% endfor %}\n{% else %}\n- {{ section[category]['']|join(', ') }}\n{% endif %}\n{% endfor %}\n{% else %}\n\nNo significant changes.\n{% endif %}\n\n{% endfor %}\n"
  },
  {
    "path": "Architecture.md",
    "content": "<!-- This file contains a rough overview of the PyO3 codebase. -->\n<!-- Please do not make descriptions too specific, so that we can easily -->\n<!-- keep this file in sync with the codebase. -->\n\n# PyO3: Architecture\n\nThis document roughly describes the high-level architecture of PyO3.\nIf you want to become familiar with the codebase you are in the right place!\n\n## Overview\n\nPyO3 provides a bridge between Rust and Python, based on the [Python/C API].\nThus, PyO3 has low-level bindings of these API as its core.\nOn top of that, we have higher-level bindings to operate Python objects safely.\nAlso, to define Python classes and functions in Rust code, we have `trait PyClass` and a set of\nprotocol traits (e.g., `PyIterProtocol`) for supporting object protocols (i.e., `__dunder__` methods).\nSince implementing `PyClass` requires lots of boilerplate, we have a proc-macro `#[pyclass]`.\n\nTo summarize, there are six main parts to the PyO3 codebase.\n\n1. [Low-level bindings of Python/C API.](#1-low-level-bindings-of-python-capi)\n   - [`pyo3-ffi`] and [`src/ffi`]\n2. [Bindings to Python objects.](#2-bindings-to-python-objects)\n   - [`src/instance.rs`] and [`src/types`]\n3. [`PyClass` and related functionalities.](#3-pyclass-and-related-functionalities)\n   - [`src/pycell.rs`], [`src/pyclass.rs`], and more\n4. [Procedural macros to simplify usage for users.](#4-procedural-macros-to-simplify-usage-for-users)\n   - [`src/impl_`], [`pyo3-macros`] and [`pyo3-macros-backend`]\n5. [`build.rs` and `pyo3-build-config`](#5-buildrs-and-pyo3-build-config)\n   - [`build.rs`](https://github.com/PyO3/pyo3/tree/main/build.rs)\n   - [`pyo3-build-config`]\n\n## 1. Low-level bindings of Python/C API\n\n[`pyo3-ffi`] contains wrappers of the [Python/C API]. This is currently done by hand rather than\nautomated tooling because:\n  - it gives us best control about how to adapt C conventions to Rust, and\n  - there are many Python interpreter versions we support in a single set of files.\n\nWe aim to provide straight-forward Rust wrappers resembling the file structure of [`cpython/Include`](https://github.com/python/cpython/tree/main/Include).\n\nWe are continuously updating the module to match the latest CPython version which PyO3 supports (i.e. as of time of writing Python 3.13). The tracking issue is [#1289](https://github.com/PyO3/pyo3/issues/1289), and contribution is welcome.\n\nIn the [`pyo3-ffi`] crate, there is lots of conditional compilation such as `#[cfg(Py_LIMITED_API)]`,\n`#[cfg(Py_3_7)]`, and `#[cfg(PyPy)]`.\n`Py_LIMITED_API` corresponds to `#define Py_LIMITED_API` macro in Python/C API.\nWith `Py_LIMITED_API`, we can build a Python-version-agnostic binary called an\n[abi3 wheel](https://pyo3.rs/latest/building-and-distribution.html#py_limited_apiabi3).\n`Py_3_7` means that the API is available from Python >= 3.7.\nThere are also `Py_3_8`, `Py_3_9`, and so on.\n`PyPy` means that the API definition is for PyPy.\nThose flags are set in [`build.rs`](#6-buildrs-and-pyo3-build-config).\n\n## 2. Bindings to Python objects\n\n[`src/types`] contains bindings to [built-in types](https://docs.python.org/3/library/stdtypes.html)\nof Python, such as `dict` and `list`.\nFor historical reasons, Python's `object` is called `PyAny` in PyO3 and located in [`src/types/any.rs`].\n\nCurrently, `PyAny` is a straightforward wrapper of `ffi::PyObject`, defined as:\n\n```rust\n#[repr(transparent)]\npub struct PyAny(UnsafeCell<ffi::PyObject>);\n```\n\nConcrete Python objects are implemented by wrapping `PyAny`, e.g.,:\n\n```rust\n#[repr(transparent)]\npub struct PyDict(PyAny);\n```\n\nThese types are not intended to be accessed directly, and instead are used through the `Py<T>` and `Bound<T>` smart pointers.\n\nWe have some macros in [`src/types/mod.rs`] which make it easier to implement APIs for concrete Python types.\n\n## 3. `PyClass` and related functionalities\n\n[`src/pycell.rs`], [`src/pyclass.rs`], and [`src/type_object.rs`] contain types and\ntraits to make `#[pyclass]` work.\nAlso, [`src/pyclass_init.rs`] and [`src/impl_/pyclass.rs`] have related functionalities.\n\nTo realize object-oriented programming in C, all Python objects have `ob_base: PyObject` as their\nfirst field in their structure definition. Thanks to this guarantee, casting `*mut A` to `*mut PyObject`\nis valid if `A` is a Python object.\n\nTo ensure this guarantee, we have a wrapper struct `PyClassObject<T>` in [`src/pycell/impl_.rs`] which is roughly:\n\n```rust\n#[repr(C)]\npub struct PyClassObject<T> {\n    ob_base: crate::ffi::PyObject,\n    inner: T,\n}\n```\n\nThus, when copying a Rust struct to a Python object, we first allocate `PyClassObject` on the Python heap and then\nmove `T` into it.\n\nThe primary way to interact with Python objects implemented in Rust is through the `Bound<'py, T>` smart pointer.\nBy having the `'py` lifetime of the `Python<'py>` token, this ties the lifetime of the `Bound<'py, T>` smart pointer to the lifetime for which the thread is attached to the Python interpreter and allows PyO3 to call Python APIs at maximum efficiency.\n\n`Bound<'py, T>` requires that `T` implements `PyClass`.\nThis trait is somewhat complex and derives many traits, but the most important one is `PyTypeInfo`\nin [`src/type_object.rs`].\n`PyTypeInfo` is also implemented for built-in types.\nIn Python, all objects have their types, and types are also objects of `type`.\nFor example, you can see `type({})` shows `dict` and `type(type({}))` shows `type` in Python REPL.\n`T: PyTypeInfo` implies that `T` has a corresponding type object.\n\n### Protocol methods\n\nPython has some built-in special methods called dunder methods, such as `__iter__`.\nThey are called \"slots\" in the [abstract objects layer](https://docs.python.org/3/c-api/abstract.html) in\nPython/C API.\nWe provide a way to implement those protocols similarly, by recognizing special\nnames in `#[pymethods]`, with a few new ones for slots that can not be\nimplemented in Python, such as GC support.\n\n## 4. Procedural macros to simplify usage for users.\n\n[`pyo3-macros`] provides five proc-macro APIs: `pymodule`, `pyfunction`, `pyclass`,\n`pymethods`, and `#[derive(FromPyObject)]`.\n[`pyo3-macros-backend`] has the actual implementations of these APIs.\n[`src/impl_`] contains `#[doc(hidden)]` functionality used in code generated by these proc-macros,\nsuch as parsing function arguments.\n\n## 5. `build.rs` and `pyo3-build-config`\n\nPyO3 supports a wide range of OSes, interpreters and use cases. The correct environment must be\ndetected at build time in order to set up relevant conditional compilation correctly. This logic\nis captured in the [`pyo3-build-config`] crate, which is a `build-dependency` of `pyo3` and\n`pyo3-macros`, and can also be used by downstream users in the same way.\n\nIn [`pyo3-build-config`]'s `build.rs` the build environment is detected and inlined into the crate\nas a \"config file\". This works in all cases except for cross-compiling, where it is necessary to\ncapture this from the `pyo3` `build.rs` to get some extra environment variables that Cargo doesn't\nset for build dependencies.\n\nThe `pyo3` `build.rs` also runs some safety checks such as ensuring the Python version detected is\nactually supported.\n\nSome of the functionality of `pyo3-build-config`:\n- Find the interpreter for build and detect the Python version.\n  - We have to set some version flags like `#[cfg(Py_3_7)]`.\n  - If the interpreter is PyPy, we set `#[cfg(PyPy)`.\n  - If the `PYO3_CONFIG_FILE` environment variable is set then that file's contents will be used\n    instead of any detected configuration.\n  - If the `PYO3_NO_PYTHON` environment variable is set then the interpreter detection is bypassed\n    entirely and only abi3 extensions can be built.\n- Check if we are building a Python extension.\n  - If we are building an extension (e.g., Python library installable by `pip`),\n    we don't link `libpython` on most platforms (to allow for statically-linked Python interpreters).\n    The `PYO3_BUILD_EXTENSION_MODULE` environment variable suppresses linking.\n- Cross-compiling configuration\n  - If `TARGET` architecture and `HOST` architecture differ, we can find cross compile information\n    from environment variables (`PYO3_CROSS_LIB_DIR`, `PYO3_CROSS_PYTHON_VERSION` and\n    `PYO3_CROSS_PYTHON_IMPLEMENTATION`) or system files.\n    When cross compiling extension modules it is often possible to make it work without any\n    additional user input.\n  - On Windows, `pyo3-ffi` uses Rust's `raw-dylib` linking feature to link against the Python DLL\n    directly without needing import libraries (`.lib` files). The build script emits a `pyo3_dll`\n    cfg with the target DLL name, and the `extern_libpython!` macro expands to the appropriate\n    `#[link(name = \"...\", kind = \"raw-dylib\")]` attribute. This enables cross compiling Python\n    extensions for Windows without having to install any Windows Python libraries.\n\n<!-- External Links -->\n\n[python/c api]: https://docs.python.org/3/c-api/\n\n<!-- Crates -->\n\n[`pyo3-macros`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros\n[`pyo3-macros-backend`]: https://github.com/PyO3/pyo3/tree/main/pyo3-macros-backend\n[`pyo3-build-config`]: https://github.com/PyO3/pyo3/tree/main/pyo3-build-config\n[`pyo3-ffi`]: https://github.com/PyO3/pyo3/tree/main/pyo3-ffi\n\n<!-- Directories -->\n\n[`src/class`]: https://github.com/PyO3/pyo3/tree/main/src/class\n[`src/ffi`]: https://github.com/PyO3/pyo3/tree/main/src/ffi\n[`src/types`]: https://github.com/PyO3/pyo3/tree/main/src/types\n\n<!-- Files -->\n\n[`src/impl_`]: https://github.com/PyO3/pyo3/blob/main/src/impl_\n[`src/instance.rs`]: https://github.com/PyO3/pyo3/tree/main/src/instance.rs\n[`src/pycell.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pycell.rs\n[`src/pyclass.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass.rs\n[`src/pyclass_init.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass_init.rs\n[`src/pyclass_slot.rs`]: https://github.com/PyO3/pyo3/tree/main/src/pyclass_slot.rs\n[`src/type_object.rs`]: https://github.com/PyO3/pyo3/tree/main/src/type_object.rs\n[`src/class/methods.rs`]: https://github.com/PyO3/pyo3/tree/main/src/class/methods.rs\n[`src/class/impl_.rs`]: https://github.com/PyO3/pyo3/tree/main/src/class/impl_.rs\n[`src/types/any.rs`]: https://github.com/PyO3/pyo3/tree/main/src/types/any.rs\n[`src/types/mod.rs`]: https://github.com/PyO3/pyo3/tree/main/src/types/mod.rs\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file. For help with updating to new\nPyO3 versions, please see the [migration guide](https://pyo3.rs/latest/migration.html).\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\nTo see unreleased changes, please see the [CHANGELOG on the main branch guide](https://pyo3.rs/main/changelog.html).\n\n<!-- towncrier release notes start -->\n\n## [0.28.2] - 2026-02-18\n\n### Fixed\n\n- Fix complex enum `__qualname__` not using python name [#5815](https://github.com/PyO3/pyo3/pull/5815)\n- Fix FFI definition `PyType_GetTypeDataSize` (was incorrectly named `PyObject_GetTypeDataSize`). [#5819](https://github.com/PyO3/pyo3/pull/5819)\n- Fix memory corruption when subclassing native types with `abi3` feature on Python 3.12+ (newly enabled in PyO3 0.28.0). [#5823](https://github.com/PyO3/pyo3/pull/5823)\n\n## [0.28.1] - 2026-02-14\n\n### Fixed\n\n- Fix `*args` / `**kwargs` support in` experimental-async` feature (regressed in 0.28.0). [#5771](https://github.com/PyO3/pyo3/pull/5771)\n- Fix `clippy::declare_interior_mutable_const` warning inside `#[pyclass]` generated code on enums. [#5772](https://github.com/PyO3/pyo3/pull/5772)\n- Fix `ambiguous_associated_items` compilation error when deriving `FromPyObject` or using `#[pyclass(from_py_object)]` macro on enums with `Error` variant. [#5784](https://github.com/PyO3/pyo3/pull/5784)\n- Fix `__qualname__` for complex `#[pyclass]` enum variants to include the enum name. [#5796](https://github.com/PyO3/pyo3/pull/5796)\n- Fix missing `std::sync::atomic::Ordering` import for targets without atomic64. [#5808](https://github.com/PyO3/pyo3/pull/5808)\n\n## [0.28.0] - 2026-02-01\n\n### Packaging\n\n- Bump MSRV to Rust 1.83. [#5531](https://github.com/PyO3/pyo3/pull/5531)\n- Bump minimum supported `quote` version to 1.0.37. [#5531](https://github.com/PyO3/pyo3/pull/5531)\n- Bump supported GraalPy version to 25.0. [#5542](https://github.com/PyO3/pyo3/pull/5542)\n- Drop `memoffset` dependency. [#5545](https://github.com/PyO3/pyo3/pull/5545)\n- Support for free-threaded Python is now opt-out rather than opt-in. [#5564](https://github.com/PyO3/pyo3/pull/5564)\n- Bump `target-lexicon` dependency to 0.13.3. [#5571](https://github.com/PyO3/pyo3/pull/5571)\n- Drop `indoc` and `unindent` dependencies. [#5608](https://github.com/PyO3/pyo3/pull/5608)\n\n### Added\n\n- Add `__init__` support in `#[pymethods]`. [#4951](https://github.com/PyO3/pyo3/pull/4951)\n- Expose `PySuper` on PyPy, GraalPy and ABI3 [#4951](https://github.com/PyO3/pyo3/pull/4951)\n- Add `PyString::from_fmt` and `py_format!` macro. [#5199](https://github.com/PyO3/pyo3/pull/5199)\n- Add `#[pyclass(new = \"from_fields\")]` option. [#5421](https://github.com/PyO3/pyo3/pull/5421)\n- Add `pyo3::buffer::PyUntypedBuffer`, a type-erased form of `PyBuffer<T>`. [#5458](https://github.com/PyO3/pyo3/pull/5458)\n- Add `PyBytes::new_with_writer` [#5517](https://github.com/PyO3/pyo3/pull/5517)\n- Add `PyClass::NAME`. [#5579](https://github.com/PyO3/pyo3/pull/5579)\n- Add `pyo3_build_config::add_libpython_rpath_link_args`. [#5624](https://github.com/PyO3/pyo3/pull/5624)\n- Add `PyBackedStr::clone_ref` and `PyBackedBytes::clone_ref` methods. [#5654](https://github.com/PyO3/pyo3/pull/5654)\n- Add `PyCapsule::new_with_pointer` and `PyCapsule::new_with_pointer_and_destructor` for creating capsules with raw pointers. [#5689](https://github.com/PyO3/pyo3/pull/5689)\n- Add `#[deleter]` attribute to implement property deleters in `#[methods]`. [#5699](https://github.com/PyO3/pyo3/pull/5699)\n- Add `IntoPyObject` and `FromPyObject` implementations for `uuid::NonNilUuid`. [#5707](https://github.com/PyO3/pyo3/pull/5707) \n- Add `PyBackedStr::as_str` and `PyBackedStr::as_py_str` methods. [#5723](https://github.com/PyO3/pyo3/pull/5723)\n- Add support for subclassing native types (`PyDict`, exceptions, ...) when building for abi3 on Python 3.12+. [#5733](https://github.com/PyO3/pyo3/pull/5733)\n- Add support for subclassing `PyList` when building for Python 3.12+. [#5734](https://github.com/PyO3/pyo3/pull/5734)\n- FFI definitions:\n  - Add FFI definitions `PyEval_GetFrameBuiltins`, `PyEval_GetFrameGlobals` and `PyEval_GetFrameLocals` on Python 3.13 and up. [#5590](https://github.com/PyO3/pyo3/pull/5590)\n  - Add FFI definitions `PyObject_New`, `PyObject_NewVar`, `PyObject_GC_Resize`, `PyObject_GC_New`, and `PyObject_GC_NewVar`. [#5591](https://github.com/PyO3/pyo3/pull/5591)\n  - Added FFI definitions and an unsafe Rust API wrapping `Py_BEGIN_CRITICAL_SECTION_MUTEX` and `Py_BEGIN_CRITICAL_SECTION_MUTEX2`. [#5642](https://github.com/PyO3/pyo3/pull/5642)\n  - Add FFI definition `PyDict_GetItemStringRef` on Python 3.13 and up. [#5659](https://github.com/PyO3/pyo3/pull/5659)\n  - Add FFI definition `PyIter_NextItem` on Python 3.14 and up, and `compat::PyIter_NextItem` for older versions. [#5661](https://github.com/PyO3/pyo3/pull/5661)\n  - Add FFI definitions `PyThreadState_GetInterpreter` and `PyThreadState_GetID` on Python 3.9+, `PyThreadState_EnterTracing` and `PyThreadState_LeaveTracing` on Python 3.11+, `PyThreadState_GetUnchecked` on Python 3.13+, and `compat::PyThreadState_GetUnchecked`. [#5711](https://github.com/PyO3/pyo3/pull/5711)\n  - Add FFI definitions `PyImport_ImportModuleAttr` and `PyImport_ImportModuleAttrString` on Python 3.14+. [#5737](https://github.com/PyO3/pyo3/pull/5737)\n  - Add FFI definitions for the `PyABIInfo` and `PyModExport` APIs available in Python 3.15. [#5746](https://github.com/PyO3/pyo3/pull/5746)\n- `experimental-inspect`:\n  - Emit base classes. [#5331](https://github.com/PyO3/pyo3/pull/5331)\n  - Emit `@typing.final` on final classes. [#5552](https://github.com/PyO3/pyo3/pull/5552)\n  - Generate nested classes for complex enums. [#5708](https://github.com/PyO3/pyo3/pull/5708)\n  - Emit `async` keyword for async functions. [#5731](https://github.com/PyO3/pyo3/pull/5731)\n\n### Changed\n\n- Call `sys.unraisablehook` instead of `PyErr_Print` if panicking on null FFI pointer in `Bound`, `Borrowed` and `Py` constructors. [#5496](https://github.com/PyO3/pyo3/pull/5496)\n- Use PEP-489 multi-phase initialization for `#[pymodule]`. [#5525](https://github.com/PyO3/pyo3/pull/5525)\n- Deprecate implicit by-value implementation of `FromPyObject` for `#[pyclass]`. [#5550](https://github.com/PyO3/pyo3/pull/5550)\n- Deprecate `PyTypeInfo::NAME` and `PyTypeInfo::MODULE`. [#5579](https://github.com/PyO3/pyo3/pull/5579)\n- Deprecate `Py<T>::from_{owned,borrowed}[or_{err,opt}]` constructors from raw pointer. [#5585](https://github.com/PyO3/pyo3/pull/5585)\n- Deprecate FFI definitions `PyEval_AcquireLock` and `PyEval_ReleaseLock`. [#5590](https://github.com/PyO3/pyo3/pull/5590)\n- Relax `'py: 'a` bound in `Py::extract`. [#5594](https://github.com/PyO3/pyo3/pull/5594)\n- Add a `T: PyTypeCheck` bound to the `IntoPyObject` implementations on `Bound<T>`, `Borrowed<T>` and `Py<T>`. [#5640](https://github.com/PyO3/pyo3/pull/5640)\n- The `with_critical_section` and `with_critical_section2` functions are moved to `pyo3::sync::critical_section`. [#5642](https://github.com/PyO3/pyo3/pull/5642)\n- Use `PyIter_NextItem` in `PyIterator::next` implementation. [#5661](https://github.com/PyO3/pyo3/pull/5661)\n- `IntoPyObject` for simple enums now uses a singleton value, allowing identity (python `is`) comparisons. [#5665](https://github.com/PyO3/pyo3/pull/5665)\n- Allow any `Sequence[int]` in `FromPyObject` on `Cow<[u8]>` and change the error type to `PyErr`. [#5667](https://github.com/PyO3/pyo3/pull/5667)\n- `async` pymethods now borrow `self` only for the duration of awaiting the future, not the entire method call. [#5684](https://github.com/PyO3/pyo3/pull/5684)\n- Change `CastError` formatted message to directly describe the \"is not an instance of\" failure condition. [#5693](https://github.com/PyO3/pyo3/pull/5693)\n- Add `#[inline]` hints to many methods on `PyBackedStr`. [#5723](https://github.com/PyO3/pyo3/pull/5723)\n- Remove redundant internal counters from `BoundSetIterator` and `BoundFrozenSetIterator`. [#5725](https://github.com/PyO3/pyo3/pull/5725)\n- Implement `PyIterator::size_hint` on abi3 builds (previously was only on unlimited API builds). [#5727](https://github.com/PyO3/pyo3/pull/5727)\n- Deprecate FFI definition `PyImport_ImportModuleNoBlock` (deprecated in Python 3.13). [#5737](https://github.com/PyO3/pyo3/pull/5737)\n- `#[new]` can now return arbitrary Python objects. [#5739](https://github.com/PyO3/pyo3/pull/5739)\n- `experimental-inspect`:\n  - Introduce `TypeHint` and make use of it to encode type hint annotations. [#5438](https://github.com/PyO3/pyo3/pull/5438)\n  - Rename `PyType{Info,Check}::TYPE_INFO` into `PyType{Info,Check}::TYPE_HINT`. [#5438](https://github.com/PyO3/pyo3/pull/5438) [#5619](https://github.com/PyO3/pyo3/pull/5619) [#5641](https://github.com/PyO3/pyo3/pull/5641)\n  - Fill annotations on function arguments and return values for all types supported natively by PyO3. [#5634](https://github.com/PyO3/pyo3/pull/5634) [#5637](https://github.com/PyO3/pyo3/pull/5637) [#5639](https://github.com/PyO3/pyo3/pull/5639)\n  - Use `_typeshed.Incomplete` instead of `typing.Any` as default type hint, to make it easier to spot incomplete trait implementations. [#5744](https://github.com/PyO3/pyo3/pull/5744)\n  - Use general Python expression syntax for type hints. [#5671](https://github.com/PyO3/pyo3/pull/5671)\n\n### Removed\n\n- Remove all functionality deprecated in PyO3 0.25 and 0.26. [#5740](https://github.com/PyO3/pyo3/pull/5740)\n- FFI definitions:\n  - Remove FFI definition `PyEval_GetCallStats` (removed from CPython in Python 3.7). [#5590](https://github.com/PyO3/pyo3/pull/5590)\n  - Remove FFI definitions `PyEval_AcquireLock` and `PyEval_ReleaseLock` on Python 3.13 and up. [#5590](https://github.com/PyO3/pyo3/pull/5590)\n  - Remove private FFI definitions `_PyObject_New`, `_PyObject_NewVar`, `_PyObject_GC_Resize`, `_PyObject_GC_New`, and `_PyObject_GC_NewVar`. [#5591](https://github.com/PyO3/pyo3/pull/5591)\n  - Remove private FFI definitions `_PyDict_SetItem_KnownHash`, `_PyDict_Next`, `_PyDict_NewPresized`, `_PyDict_Contains_KnownHash`, and `_PyDict_Contains`. [#5659](https://github.com/PyO3/pyo3/pull/5659)\n  - Remove private FFI definitions `_PyFrameEvalFunction`, `_PyInterpreterState_GetEvalFrameFunc` and `_PyInterpreterState_SetEvalFrameFunc`. [#5711](https://github.com/PyO3/pyo3/pull/5711)\n  - Remove private FFI definitions `_PyImport_IsInitialized`, `_PyImport_SetModule`, `_PyImport_SetModuleString`, `_PyImport_AcquireLock`, `_PyImport_ReleaseLock`, `_PyImport_FindBuiltin`, `_PyImport_FindExtensionObject`, `_PyImport_FixupBuiltin`, and `_PyImport_FixupExtensionObject`. [#5737](https://github.com/PyO3/pyo3/pull/5737)\n\n### Fixed\n\n- Fix `PyModuleMethods::add_submodule()` to use the last segment of the submodule name as the attribute name on the parent module instead of using the full name. [#5375](https://github.com/PyO3/pyo3/pull/5375)\n- Link with libpython for Cygwin extension modules. [#5571](https://github.com/PyO3/pyo3/pull/5571)\n- Link against the limited API DLL for Cygwin when abi3 is used. [#5574](https://github.com/PyO3/pyo3/pull/5574)\n- Handle errors in `PyIterator` when calling `size_hint` [#5604](https://github.com/PyO3/pyo3/pull/5604)\n- Link with libpython for iOS extension modules. [#5605](https://github.com/PyO3/pyo3/pull/5605)\n- Correct `IntoPyObject` output type of `PyBackedStr` to be `PyString`, not `PyAny`. [#5655](https://github.com/PyO3/pyo3/pull/5655)\n- Fix `async` functions to return `None` rather than empty tuple `()`. [#5685](https://github.com/PyO3/pyo3/pull/5685)\n- Fix compile error when using references to `#[pyclass]` types (e.g. `&MyClass`) as arguments to async `#[pyfunction]`s. [#5725](https://github.com/PyO3/pyo3/pull/5725)\n- FFI definitions:\n  - Fix FFI definition `PyMemberDescrObject.d_member` to use `PyMemberDef` for Python 3.11+ (was incorrectly `PyGetSetDef`). [#5647](https://github.com/PyO3/pyo3/pull/5647)\n  - Mark FFI definition `PyThreadState_GetFrame` available with abi3 in 3.10+. [#5711](https://github.com/PyO3/pyo3/pull/5711)\n  - Fix FFI definition `PyImport_GetModule` on PyPy. [#5737](https://github.com/PyO3/pyo3/pull/5737)\n- `experimental-inspect`:\n  - fix `__new__` return type to be the built object type and not `None`. [#5555](https://github.com/PyO3/pyo3/pull/5555)\n  - fix imports of decorators. [#5618](https://github.com/PyO3/pyo3/pull/5618)\n  - fix the return type annotation of `PyResult<()>` (must be `None` and not `tuple`) [#5674](https://github.com/PyO3/pyo3/pull/5674)\n\n## [0.27.2] - 2025-11-30\n\n### Changed\n\n- Disable subclassing `PyDict` on GraalPy (unsupported for now, may crash at runtime). [#5653](https://github.com/PyO3/pyo3/pull/5653)\n\n### Fixed\n\n- Fix crash when compiling on Rust 1.92+ with both debug assertions and optimizations enabled. [#5638](https://github.com/PyO3/pyo3/pull/5638)\n- Fix FFI definition of `PyDictObject` on PyPy. [#5653](https://github.com/PyO3/pyo3/pull/5653)\n\n## [0.27.1] - 2025-10-21\n\n### Fixed\n\n- Fix `clippy:declare_interior_mutable_const` warning from `#[pyfunction]`. [#5538](https://github.com/PyO3/pyo3/pull/5538)\n- Expose `pyo3::types::PySendResult` in public API. [#5539](https://github.com/PyO3/pyo3/pull/5539)\n\n## [0.27.0] - 2025-10-19\n\n### Packaging\n\n- Extend range of supported versions of `hashbrown` optional dependency to include version 0.16. [#5428](https://github.com/PyO3/pyo3/pull/5428)\n- Bump optional `num-bigint` dependency minimum version to 0.4.4. [#5471](https://github.com/PyO3/pyo3/pull/5471)\n- Test against Python 3.14 final release. [#5499](https://github.com/PyO3/pyo3/pull/5499)\n- Drop support for PyPy 3.9 and 3.10. [#5516](https://github.com/PyO3/pyo3/pull/5516)\n- Provide a better error message when building an outdated PyO3 for a too-new Python version. [#5519](https://github.com/PyO3/pyo3/pull/5519)\n\n### Added\n\n- Add `FromPyObjectOwned` as convenient trait bound for `FromPyObject` when the data is not borrowed from Python. [#4390](https://github.com/PyO3/pyo3/pull/4390)\n- Add `Borrowed::extract`, same as `PyAnyMethods::extract`, but does not restrict the lifetime by deref. [#4390](https://github.com/PyO3/pyo3/pull/4390)\n- `experimental-inspect`: basic support for `#[derive(IntoPyObject)]` (no struct fields support yet). [#5365](https://github.com/PyO3/pyo3/pull/5365)\n- `experimental-inspect`: support `#[pyo3(get, set)]` and `#[pyclass(get_all, set_all)]`. [#5370](https://github.com/PyO3/pyo3/pull/5370)\n- Add `PyTypeCheck::classinfo_object` that returns an object that can be used as parameter in `isinstance` or `issubclass`. [#5387](https://github.com/PyO3/pyo3/pull/5387)\n- Implement `PyTypeInfo` on `datetime.*` types even when the limited API is enabled. [#5388](https://github.com/PyO3/pyo3/pull/5388)\n- Implement `PyTypeInfo` on `PyIterator`, `PyMapping` and `PySequence`. [#5402](https://github.com/PyO3/pyo3/pull/5402)\n- Implement `PyTypeInfo` on `PyCode` when using the stable ABI. [#5403](https://github.com/PyO3/pyo3/pull/5403)\n- Implement `PyTypeInfo` on `PyWeakrefReference` when using the stable ABI. [#5404](https://github.com/PyO3/pyo3/pull/5404)\n- Add `pyo3::sync::RwLockExt` trait, analogous to `pyo3::sync::MutexExt` for readwrite locks. [#5435](https://github.com/PyO3/pyo3/pull/5435)\n- Add `PyString::from_bytes`. [#5437](https://github.com/PyO3/pyo3/pull/5437)\n- Implement `AsRef<[u8]>` for `PyBytes`. [#5445](https://github.com/PyO3/pyo3/pull/5445)\n- Add `CastError` and `CastIntoError`. [#5468](https://github.com/PyO3/pyo3/pull/5468)\n- Add `PyCapsuleMethods::pointer_checked` and `PyCapsuleMethods::is_valid_checked`. [#5474](https://github.com/PyO3/pyo3/pull/5474)\n- Add `Borrowed::cast`, `Borrowed::cast_exact` and `Borrowed::cast_unchecked`. [#5475](https://github.com/PyO3/pyo3/pull/5475)\n- Add conversions for `jiff::civil::ISOWeekDate`. [#5478](https://github.com/PyO3/pyo3/pull/5478)\n- Add conversions for `&Cstr`, `Cstring` and `Cow<Cstr>`. [#5482](https://github.com/PyO3/pyo3/pull/5482)\n- add `#[pyclass(skip_from_py_object)]` option, to opt-out of the `FromPyObject: PyClass + Clone` blanket impl. [#5488](https://github.com/PyO3/pyo3/pull/5488)\n- Add `PyErr::add_note`. [#5489](https://github.com/PyO3/pyo3/pull/5489)\n- Add `FromPyObject` impl for `Cow<Path>` & `Cow<OsStr>`. [#5497](https://github.com/PyO3/pyo3/pull/5497)\n- Add `#[pyclass(from_py_object)]` pyclass option, to opt-in to the extraction of pyclasses by value (requires `Clone`). [#5506](https://github.com/PyO3/pyo3/pull/5506)\n\n### Changed\n\n- Rework `FromPyObject` trait for flexibility and performance: [#4390](https://github.com/PyO3/pyo3/pull/4390)\n  - Add a second lifetime to `FromPyObject`, to allow borrowing data from Python objects (e.g. `&str` from Python `str`).\n  - Replace `extract_bound` with `extract`, which takes `Borrowed<'a, 'py, PyAny>`.\n- Optimize `FromPyObject` implementations for `Vec<u8>` and `[u8; N]` from `bytes` and `bytearray`. [#5244](https://github.com/PyO3/pyo3/pull/5244)\n- Deprecate `#[pyfn]` attribute. [#5384](https://github.com/PyO3/pyo3/pull/5384)\n- Fetch type name dynamically on cast errors instead of using `PyTypeCheck::NAME`. [#5387](https://github.com/PyO3/pyo3/pull/5387)\n- Deprecate `PyTypeCheck::NAME` in favour of `PyTypeCheck::classinfo_object` which provides the type information at runtime. [#5387](https://github.com/PyO3/pyo3/pull/5387)\n- `PyClassGuard(Mut)` and `PyRef(Mut)` extraction now returns an opaque Rust error [#5413](https://github.com/PyO3/pyo3/pull/5413)\n- Fetch type name dynamically when exporting types implementing `PyTypeInfo` with `#[pymodule_use]`. [#5414](https://github.com/PyO3/pyo3/pull/5414)\n- Improve `Debug` representation of `PyBuffer<T>`. [#5442](https://github.com/PyO3/pyo3/pull/5442)\n- `experimental-inspect`: change the way introspection data is emitted in the binaries to avoid a pointer indirection and simplify parsing. [#5450](https://github.com/PyO3/pyo3/pull/5450)\n- Optimize `Py<T>::drop` for the case when attached to the Python interpreter. [#5454](https://github.com/PyO3/pyo3/pull/5454)\n- Replace `DowncastError` and `DowncastIntoError` with `CastError` and `CastIntoError`. [#5468](https://github.com/PyO3/pyo3/pull/5468)\n- Enable fast-path for 128-bit integer conversions on `GraalPy`. [#5471](https://github.com/PyO3/pyo3/pull/5471)\n- Deprecate `PyAnyMethods::downcast` functions in favour of `Bound::cast` functions. [#5472](https://github.com/PyO3/pyo3/pull/5472)\n- Make `PyTypeCheck` an `unsafe trait`. [#5473](https://github.com/PyO3/pyo3/pull/5473)\n- Deprecate unchecked `PyCapsuleMethods`: `pointer()`, `reference()`, and `is_valid()`. [#5474](https://github.com/PyO3/pyo3/pull/5474)\n- Reduce lifetime of return value in `PyCapsuleMethods::reference`. [#5474](https://github.com/PyO3/pyo3/pull/5474)\n- `PyCapsuleMethods::name` now returns `CapsuleName` wrapper instead of `&CStr`. [#5474](https://github.com/PyO3/pyo3/pull/5474)\n- Deprecate `import_exception_bound` in favour of `import_exception`. [#5480](https://github.com/PyO3/pyo3/pull/5480)\n- `PyList::get_item_unchecked`, `PyTuple::get_item_unchecked`, and `PyTuple::get_borrowed_item_unchecked` no longer check for null values at the provided index. [#5494](https://github.com/PyO3/pyo3/pull/5494)\n- Allow converting naive datetime into chrono `DateTime<Local>`. [#5507](https://github.com/PyO3/pyo3/pull/5507)\n\n### Removed\n\n- Removed `FromPyObjectBound` trait. [#4390](https://github.com/PyO3/pyo3/pull/4390)\n\n### Fixed\n\n- Fix compilation failure on `wasm32-wasip2`. [#5368](https://github.com/PyO3/pyo3/pull/5368)\n- Fix `OsStr` conversion for non-utf8 strings on Windows. [#5444](https://github.com/PyO3/pyo3/pull/5444)\n- Fix issue with `cargo vendor` caused by gitignored build artifact `emscripten/pybuilddir.txt`. [#5456](https://github.com/PyO3/pyo3/pull/5456)\n- Stop leaking `PyMethodDef` instances inside `#[pyfunction]` macro generated code. [#5459](https://github.com/PyO3/pyo3/pull/5459)\n- Don't export definition of FFI struct `PyObjectObFlagsAndRefcnt` on 32-bit Python 3.14 (doesn't exist). [#5499](https://github.com/PyO3/pyo3/pull/5499)\n- Fix failure to build for `abi3` interpreters on Windows using maturin's built-in sysconfig in combination with the `generate-import-lib` feature. [#5503](https://github.com/PyO3/pyo3/pull/5503)\n- Fix FFI definitions `PyModule_ExecDef` and `PyModule_FromDefAndSpec2` on PyPy. [#5529](https://github.com/PyO3/pyo3/pull/5529)\n\n## [0.26.0] - 2025-08-29\n\n### Packaging\n\n- Bump hashbrown dependency to 0.15. [#5152](https://github.com/PyO3/pyo3/pull/5152)\n- Update MSRV to 1.74. [#5171](https://github.com/PyO3/pyo3/pull/5171)\n- Set the same maximum supported version for alternative interpreters as for CPython. [#5192](https://github.com/PyO3/pyo3/pull/5192)\n- Add optional `bytes` dependency to add conversions for `bytes::Bytes`. [#5252](https://github.com/PyO3/pyo3/pull/5252)\n- Publish new crate `pyo3-introspection` to pair with the `experimental-inspect` feature. [#5300](https://github.com/PyO3/pyo3/pull/5300)\n- The `PYO3_BUILD_EXTENSION_MODULE` now causes the same effect as the `extension-module` feature. Eventually we expect maturin and setuptools-rust to set this environment variable automatically. Users with their own build systems will need to do the same. [#5343](https://github.com/PyO3/pyo3/pull/5343)\n\n### Added\n\n- Add `#[pyo3(warn(message = \"...\", category = ...))]` attribute for automatic warnings generation for `#[pyfunction]` and `#[pymethods]`. [#4364](https://github.com/PyO3/pyo3/pull/4364)\n- Add `PyMutex`, available on Python 3.13 and newer. [#4523](https://github.com/PyO3/pyo3/pull/4523)\n- Add FFI definition `PyMutex_IsLocked`, available on Python 3.14 and newer. [#4523](https://github.com/PyO3/pyo3/pull/4523)\n- Add `PyString::from_encoded_object`. [#5017](https://github.com/PyO3/pyo3/pull/5017)\n- `experimental-inspect`: add basic input type annotations. [#5089](https://github.com/PyO3/pyo3/pull/5089)\n- Add FFI function definitions for `PyFrameObject` from CPython 3.13. [#5154](https://github.com/PyO3/pyo3/pull/5154)\n- `experimental-inspect`: tag modules created using `#[pymodule]` or `#[pymodule_init]` functions as incomplete. [#5207](https://github.com/PyO3/pyo3/pull/5207)\n- `experimental-inspect`: add basic return type support. [#5208](https://github.com/PyO3/pyo3/pull/5208)\n- Add `PyCode::compile` and `PyCodeMethods::run` to create and execute code objects. [#5217](https://github.com/PyO3/pyo3/pull/5217)\n- Add `PyOnceLock` type for thread-safe single-initialization. [#5223](https://github.com/PyO3/pyo3/pull/5223)\n- Add `PyClassGuard(Mut)` pyclass holders. In the future they will replace `PyRef(Mut)`. [#5233](https://github.com/PyO3/pyo3/pull/5233)\n- `experimental-inspect`: allow annotations in `#[pyo3(signature)]` signature attribute. [#5241](https://github.com/PyO3/pyo3/pull/5241)\n- Implement `MutexExt` for parking_lot's/lock_api `ReentrantMutex`. [#5258](https://github.com/PyO3/pyo3/pull/5258)\n- `experimental-inspect`: support class associated constants. [#5272](https://github.com/PyO3/pyo3/pull/5272)\n- Add `Bound::cast` family of functions superseding the `PyAnyMethods::downcast` family. [#5289](https://github.com/PyO3/pyo3/pull/5289)\n- Add FFI definitions `Py_Version` and `Py_IsFinalizing`. [#5317](https://github.com/PyO3/pyo3/pull/5317)\n- `experimental-inspect`: add output type annotation for `#[pyclass]`. [#5320](https://github.com/PyO3/pyo3/pull/5320)\n- `experimental-inspect`: support `#[pyclass(eq, eq_int, ord, hash, str)]`. [#5338](https://github.com/PyO3/pyo3/pull/5338)\n- `experimental-inspect`: add basic support for `#[derive(FromPyObject)]` (no struct fields support yet). [#5339](https://github.com/PyO3/pyo3/pull/5339)\n- Add `Python::try_attach`. [#5342](https://github.com/PyO3/pyo3/pull/5342)\n\n### Changed\n\n- Use `Py_TPFLAGS_DISALLOW_INSTANTIATION` instead of a `__new__` which always fails for a `#[pyclass]` without a `#[new]` on Python 3.10 and up. [#4568](https://github.com/PyO3/pyo3/pull/4568)\n- `PyModule::from_code` now defaults `file_name` to `<string>` if empty. [#4777](https://github.com/PyO3/pyo3/pull/4777)\n- Deprecate `PyString::from_object` in favour of `PyString::from_encoded_object`. [#5017](https://github.com/PyO3/pyo3/pull/5017)\n- When building with `abi3` for a Python version newer than pyo3 supports, automatically fall back to an abi3 build for the latest supported version. [#5144](https://github.com/PyO3/pyo3/pull/5144)\n- Change `is_instance_of` trait bound from `PyTypeInfo` to `PyTypeCheck`. [#5146](https://github.com/PyO3/pyo3/pull/5146)\n- Many PyO3 proc macros now report multiple errors instead of only the first one. [#5159](https://github.com/PyO3/pyo3/pull/5159)\n- Change `MutexExt` return type to be an associated type. [#5201](https://github.com/PyO3/pyo3/pull/5201)\n- Use `PyCallArgs` for `Py::call` and friends so they're equivalent to their `Bound` counterpart. [#5206](https://github.com/PyO3/pyo3/pull/5206)\n- Rename `Python::with_gil` to `Python::attach`. [#5209](https://github.com/PyO3/pyo3/pull/5209)\n- Rename `Python::allow_threads` to `Python::detach` [#5221](https://github.com/PyO3/pyo3/pull/5221)\n- Deprecate `GILOnceCell` type in favour of `PyOnceLock`. [#5223](https://github.com/PyO3/pyo3/pull/5223)\n- Rename `pyo3::prepare_freethreaded_python` to `Python::initialize`. [#5247](https://github.com/PyO3/pyo3/pull/5247)\n- Convert `PyMemoryError` into/from `io::ErrorKind::OutOfMemory`. [#5256](https://github.com/PyO3/pyo3/pull/5256)\n- Deprecate `GILProtected`. [#5285](https://github.com/PyO3/pyo3/pull/5285)\n- Move `#[pyclass]` docstring formatting from import time to compile time. [#5286](https://github.com/PyO3/pyo3/pull/5286)\n- `Python::attach` will now panic if the Python interpreter is in the process of shutting down. [#5317](https://github.com/PyO3/pyo3/pull/5317)\n- Add fast-path to `PyTypeInfo::type_object` for `#[pyclass]` types. [#5324](https://github.com/PyO3/pyo3/pull/5324)\n- Deprecate `PyObject` type alias for `Py<PyAny>`. [#5325](https://github.com/PyO3/pyo3/pull/5325)\n- Rename `Python::with_gil_unchecked` to `Python::attach_unchecked`. [#5340](https://github.com/PyO3/pyo3/pull/5340)\n- Rename `Python::assume_gil_acquired` to `Python::assume_attached`. [#5354](https://github.com/PyO3/pyo3/pull/5354)\n\n### Removed\n\n- Remove FFI definition of internals of `PyFrameObject`. [#5154](https://github.com/PyO3/pyo3/pull/5154)\n- Remove `Eq` and `PartialEq` implementations on `PyGetSetDef` FFI definition. [#5196](https://github.com/PyO3/pyo3/pull/5196)\n- Remove private FFI definitions `_Py_IsCoreInitialized` and `_Py_InitializeMain`. [#5317](https://github.com/PyO3/pyo3/pull/5317)\n\n### Fixed\n\n- Use critical section in `PyByteArray::to_vec` on freethreaded build to replicate GIL-enabled \"soundness\". [#4742](https://github.com/PyO3/pyo3/pull/4742)\n- Fix precision loss when converting `bigdecimal` into Python. [#5198](https://github.com/PyO3/pyo3/pull/5198)\n- Don't treat win7 target as a cross-compilation. [#5210](https://github.com/PyO3/pyo3/pull/5210)\n- WASM targets no longer require exception handling support for Python < 3.14. [#5239](https://github.com/PyO3/pyo3/pull/5239)\n- Fix segfault when dropping `PyBuffer<T>` after the Python interpreter has been finalized. [#5242](https://github.com/PyO3/pyo3/pull/5242)\n- `experimental-inspect`: better automated imports generation. [#5251](https://github.com/PyO3/pyo3/pull/5251)\n- `experimental-inspect`: fix introspection of `__richcmp__`, `__concat__`, `__repeat__`, `__inplace_concat__` and `__inplace_repeat__`. [#5273](https://github.com/PyO3/pyo3/pull/5273)\n- fixed a leaked borrow, when converting a mutable sub class into a frozen base class using `PyRef::into_super` [#5281](https://github.com/PyO3/pyo3/pull/5281)\n- Fix FFI definition `Py_Exit` (never returns, was `()` return value, now `!`). [#5317](https://github.com/PyO3/pyo3/pull/5317)\n- `experimental-inspect`: fix handling of module members gated behind `#[cfg(...)]` attributes. [#5318](https://github.com/PyO3/pyo3/pull/5318)\n\n## [0.25.1] - 2025-06-12\n### Packaging\n\n- Add support for Windows on ARM64. [#5145](https://github.com/PyO3/pyo3/pull/5145)\n- Add `chrono-local` feature for optional conversions for chrono's `Local` timezone & `DateTime<Local>` instances. [#5174](https://github.com/PyO3/pyo3/pull/5174)\n\n### Added\n\n- Add FFI definition `PyBytes_AS_STRING`. [#5121](https://github.com/PyO3/pyo3/pull/5121)\n- Add support for module associated consts introspection. [#5150](https://github.com/PyO3/pyo3/pull/5150)\n\n### Changed\n\n- Enable \"vectorcall\" FFI definitions on GraalPy. [#5121](https://github.com/PyO3/pyo3/pull/5121)\n- Use `Py_Is` function on GraalPy [#5121](https://github.com/PyO3/pyo3/pull/5121)\n\n### Fixed\n\n- Report a better compile error for `async` declarations when not using `experimental-async` feature. [#5156](https://github.com/PyO3/pyo3/pull/5156)\n- Fix implementation of `FromPyObject` for `uuid::Uuid` on big-endian architectures. [#5161](https://github.com/PyO3/pyo3/pull/5161)\n- Fix segmentation faults on 32-bit x86 with Python 3.14. [#5180](https://github.com/PyO3/pyo3/pull/5180)\n\n## [0.25.0] - 2025-05-14\n\n### Packaging\n\n- Support Python 3.14.0b1. [#4811](https://github.com/PyO3/pyo3/pull/4811)\n- Bump supported GraalPy version to 24.2. [#5116](https://github.com/PyO3/pyo3/pull/5116)\n- Add optional `bigdecimal` dependency to add conversions for `bigdecimal::BigDecimal`. [#5011](https://github.com/PyO3/pyo3/pull/5011)\n- Add optional `time` dependency to add conversions for `time` types. [#5057](https://github.com/PyO3/pyo3/pull/5057)\n- Remove `cfg-if` dependency. [#5110](https://github.com/PyO3/pyo3/pull/5110)\n- Add optional `ordered_float` dependency to add conversions for `ordered_float::NotNan` and `ordered_float::OrderedFloat`. [#5114](https://github.com/PyO3/pyo3/pull/5114)\n\n### Added\n\n- Add initial type stub generation to the `experimental-inspect` feature. [#3977](https://github.com/PyO3/pyo3/pull/3977)\n- Add `#[pyclass(generic)]` option to support runtime generic typing. [#4926](https://github.com/PyO3/pyo3/pull/4926)\n- Implement `OnceExt` & `MutexExt` for `parking_lot` & `lock_api`. Use the new extension traits by enabling the `arc_lock`, `lock_api`, or `parking_lot` cargo features. [#5044](https://github.com/PyO3/pyo3/pull/5044)\n- Implement `From`/`Into` for `Borrowed<T>` -> `Py<T>`. [#5054](https://github.com/PyO3/pyo3/pull/5054)\n- Add `PyTzInfo` constructors. [#5055](https://github.com/PyO3/pyo3/pull/5055)\n- Add FFI definition `PY_INVALID_STACK_EFFECT`. [#5064](https://github.com/PyO3/pyo3/pull/5064)\n- Implement `AsRef<Py<PyAny>>` for `Py<T>`, `Bound<T>` and `Borrowed<T>`. [#5071](https://github.com/PyO3/pyo3/pull/5071)\n- Add FFI definition `PyModule_Add` and `compat::PyModule_Add`. [#5085](https://github.com/PyO3/pyo3/pull/5085)\n- Add FFI definitions `Py_HashBuffer`, `Py_HashPointer`, and `PyObject_GenericHash`. [#5086](https://github.com/PyO3/pyo3/pull/5086)\n- Support `#[pymodule_export]` on `const` items in declarative modules. [#5096](https://github.com/PyO3/pyo3/pull/5096)\n- Add `#[pyclass(immutable_type)]` option (on Python 3.14+ with `abi3`, or 3.10+ otherwise) for immutable type objects. [#5101](https://github.com/PyO3/pyo3/pull/5101)\n- Support `#[pyo3(rename_all)]` support on `#[derive(IntoPyObject)]`. [#5112](https://github.com/PyO3/pyo3/pull/5112)\n- Add `PyRange` wrapper. [#5117](https://github.com/PyO3/pyo3/pull/5117)\n\n### Changed\n\n- Enable use of `datetime` types with `abi3` feature enabled. [#4970](https://github.com/PyO3/pyo3/pull/4970)\n- Deprecate `timezone_utc` in favor of `PyTzInfo::utc`. [#5055](https://github.com/PyO3/pyo3/pull/5055)\n- Reduce visibility of some CPython implementation details: [#5064](https://github.com/PyO3/pyo3/pull/5064)\n  - The FFI definition `PyCodeObject` is now an opaque struct on all Python versions.\n  - The FFI definition `PyFutureFeatures` is now only defined up until Python 3.10 (it was present in CPython headers but unused in 3.11 and 3.12).\n- Change `PyAnyMethods::is` to take `other: &Bound<T>`. [#5071](https://github.com/PyO3/pyo3/pull/5071)\n- Change `Py::is` to take `other: &Py<T>`. [#5071](https://github.com/PyO3/pyo3/pull/5071)\n- Change `PyVisit::call` to take `T: Into<Option<&Py<T>>>`. [#5071](https://github.com/PyO3/pyo3/pull/5071)\n- Expose `PyDateTime_DATE_GET_TZINFO` and `PyDateTime_TIME_GET_TZINFO` on PyPy 3.10 and later. [#5079](https://github.com/PyO3/pyo3/pull/5079)\n- Add `#[track_caller]` to `with_gil` and `with_gil_unchecked`. [#5109](https://github.com/PyO3/pyo3/pull/5109)\n- Use `std::thread::park()` instead of `libc::pause()` or `sleep(9999999)`. [#5115](https://github.com/PyO3/pyo3/pull/5115)\n\n### Removed\n\n- Remove all functionality deprecated in PyO3 0.23. [#4982](https://github.com/PyO3/pyo3/pull/4982)\n- Remove deprecated `IntoPy` and `ToPyObject` traits. [#5010](https://github.com/PyO3/pyo3/pull/5010)\n- Remove private types from `pyo3-ffi` (i.e. starting with `_Py`) which are not referenced by public APIs: `_PyLocalMonitors`, `_Py_GlobalMonitors`, `_PyCoCached`, `_PyCoLineInstrumentationData`, `_PyCoMonitoringData`, `_PyCompilerSrcLocation`, `_PyErr_StackItem`. [#5064](https://github.com/PyO3/pyo3/pull/5064)\n- Remove FFI definition `PyCode_GetNumFree` (PyO3 cannot support it due to knowledge of the code object). [#5064](https://github.com/PyO3/pyo3/pull/5064)\n- Remove `AsPyPointer` trait. [#5071](https://github.com/PyO3/pyo3/pull/5071)\n- Remove support for the deprecated string form of `from_py_with`. [#5097](https://github.com/PyO3/pyo3/pull/5097)\n- Remove FFI definitions of private static variables: `_PyMethodWrapper_Type`, `_PyCoroWrapper_Type`, `_PyImport_FrozenBootstrap`, `_PyImport_FrozenStdlib`, `_PyImport_FrozenTest`, `_PyManagedBuffer_Type`, `_PySet_Dummy`, `_PyWeakref_ProxyType`, and `_PyWeakref_CallableProxyType`. [#5105](https://github.com/PyO3/pyo3/pull/5105)\n- Remove FFI definitions `PyASCIIObjectState`, `PyUnicode_IS_ASCII`, `PyUnicode_IS_COMPACT`, and `PyUnicode_IS_COMPACT_ASCII` on Python 3.14 and newer. [#5133](https://github.com/PyO3/pyo3/pull/5133)\n\n### Fixed\n\n- Correctly pick up the shared state for conda-based Python installation when reading information from sysconfigdata. [#5037](https://github.com/PyO3/pyo3/pull/5037)\n- Fix compile failure with `#[derive(IntoPyObject, FromPyObject)]` when using `#[pyo3()]` options recognised by only one of the two derives. [#5070](https://github.com/PyO3/pyo3/pull/5070)\n- Fix various compile errors from missing FFI definitions using certain feature combinations on PyPy and GraalPy. [#5091](https://github.com/PyO3/pyo3/pull/5091)\n- Fallback on `backports.zoneinfo` for python <3.9 when converting timezones into python. [#5120](https://github.com/PyO3/pyo3/pull/5120)\n\n## [0.24.2] - 2025-04-21\n\n### Fixed\n\n- Fix `unused_imports` lint of `#[pyfunction]` and `#[pymethods]` expanded in `macro_rules` context. [#5030](https://github.com/PyO3/pyo3/pull/5030)\n- Fix size of `PyCodeObject::_co_instrumentation_version` ffi struct member on Python 3.13 for systems where `uintptr_t` is not 64 bits. [#5048](https://github.com/PyO3/pyo3/pull/5048)\n- Fix struct-type complex enum variant fields incorrectly exposing raw identifiers as `r#ident` in Python bindings. [#5050](https://github.com/PyO3/pyo3/pull/5050)\n\n## [0.24.1] - 2025-03-31\n\n### Added\n\n- Add `abi3-py313` feature. [#4969](https://github.com/PyO3/pyo3/pull/4969)\n- Add `PyAnyMethods::getattr_opt`. [#4978](https://github.com/PyO3/pyo3/pull/4978)\n- Add `PyInt::new` constructor for all supported number types (i32, u32, i64, u64, isize, usize). [#4984](https://github.com/PyO3/pyo3/pull/4984)\n- Add `pyo3::sync::with_critical_section2`. [#4992](https://github.com/PyO3/pyo3/pull/4992)\n- Implement `PyCallArgs` for `Borrowed<'_, 'py, PyTuple>`, `&Bound<'py, PyTuple>`, and `&Py<PyTuple>`. [#5013](https://github.com/PyO3/pyo3/pull/5013)\n\n### Fixed\n\n- Fix `is_type_of` for native types not using same specialized check as `is_type_of_bound`. [#4981](https://github.com/PyO3/pyo3/pull/4981)\n- Fix `Probe` class naming issue with `#[pymethods]`. [#4988](https://github.com/PyO3/pyo3/pull/4988)\n- Fix compile failure with required `#[pyfunction]` arguments taking `Option<&str>` and `Option<&T>` (for `#[pyclass]` types). [#5002](https://github.com/PyO3/pyo3/pull/5002)\n- Fix `PyString::from_object` causing of bounds reads with `encoding` and `errors` parameters which are not nul-terminated. [#5008](https://github.com/PyO3/pyo3/pull/5008)\n- Fix compile error when additional options follow after `crate` for `#[pyfunction]`. [#5015](https://github.com/PyO3/pyo3/pull/5015)\n\n## [0.24.0] - 2025-03-09\n\n### Packaging\n\n- Add supported CPython/PyPy versions to cargo package metadata. [#4756](https://github.com/PyO3/pyo3/pull/4756)\n- Bump `target-lexicon` dependency to 0.13. [#4822](https://github.com/PyO3/pyo3/pull/4822)\n- Add optional `jiff` dependency to add conversions for `jiff` datetime types. [#4823](https://github.com/PyO3/pyo3/pull/4823)\n- Add optional `uuid` dependency to add conversions for `uuid::Uuid`. [#4864](https://github.com/PyO3/pyo3/pull/4864)\n- Bump minimum supported `inventory` version to 0.3.5. [#4954](https://github.com/PyO3/pyo3/pull/4954)\n\n### Added\n\n- Add `PyIterator::send` method to allow sending values into a python generator. [#4746](https://github.com/PyO3/pyo3/pull/4746)\n- Add `PyCallArgs` trait for passing arguments into the Python calling protocol. This enabled using a faster calling convention for certain types, improving performance. [#4768](https://github.com/PyO3/pyo3/pull/4768)\n- Add `#[pyo3(default = ...']` option for `#[derive(FromPyObject)]` to set a default value for extracted fields of named structs. [#4829](https://github.com/PyO3/pyo3/pull/4829)\n- Add `#[pyo3(into_py_with = ...)]` option for `#[derive(IntoPyObject, IntoPyObjectRef)]`. [#4850](https://github.com/PyO3/pyo3/pull/4850)\n- Add FFI definitions `PyThreadState_GetFrame` and `PyFrame_GetBack`. [#4866](https://github.com/PyO3/pyo3/pull/4866)\n- Optimize `last` for `BoundListIterator`, `BoundTupleIterator` and `BorrowedTupleIterator`. [#4878](https://github.com/PyO3/pyo3/pull/4878)\n- Optimize `Iterator::count()` for `PyDict`, `PyList`, `PyTuple` & `PySet`. [#4878](https://github.com/PyO3/pyo3/pull/4878)\n- Optimize `nth`, `nth_back`, `advance_by` and `advance_back_by` for `BoundTupleIterator` [#4897](https://github.com/PyO3/pyo3/pull/4897)\n- Add support for `types.GenericAlias` as `pyo3::types::PyGenericAlias`. [#4917](https://github.com/PyO3/pyo3/pull/4917)\n- Add `MutextExt` trait to help avoid deadlocks with the GIL while locking a `std::sync::Mutex`. [#4934](https://github.com/PyO3/pyo3/pull/4934)\n- Add `#[pyo3(rename_all = \"...\")]` option for `#[derive(FromPyObject)]`. [#4941](https://github.com/PyO3/pyo3/pull/4941)\n\n### Changed\n\n- Optimize `nth`, `nth_back`, `advance_by` and `advance_back_by` for `BoundListIterator`. [#4810](https://github.com/PyO3/pyo3/pull/4810)\n- Use `DerefToPyAny` in blanket implementations of `From<Py<T>>` and `From<Bound<'py, T>>` for `PyObject`. [#4593](https://github.com/PyO3/pyo3/pull/4593)\n- Map `io::ErrorKind::IsADirectory`/`NotADirectory` to the corresponding Python exception on Rust 1.83+. [#4747](https://github.com/PyO3/pyo3/pull/4747)\n- `PyAnyMethods::call` and friends now require `PyCallArgs` for their positional arguments. [#4768](https://github.com/PyO3/pyo3/pull/4768)\n- Expose FFI definitions for `PyObject_Vectorcall(Method)` on the stable abi on 3.12+. [#4853](https://github.com/PyO3/pyo3/pull/4853)\n- `#[pyo3(from_py_with = ...)]` now take a path rather than a string literal [#4860](https://github.com/PyO3/pyo3/pull/4860)\n- Format Python traceback in impl Debug for PyErr. [#4900](https://github.com/PyO3/pyo3/pull/4900)\n- Convert `PathBuf` & `Path` into Python `pathlib.Path` instead of `PyString`. [#4925](https://github.com/PyO3/pyo3/pull/4925)\n- Relax parsing of exotic Python versions. [#4949](https://github.com/PyO3/pyo3/pull/4949)\n- PyO3 threads now hang instead of `pthread_exit` trying to acquire the GIL when the interpreter is shutting down. This mimics the [Python 3.14](https://github.com/python/cpython/issues/87135) behavior and avoids undefined behavior and crashes. [#4874](https://github.com/PyO3/pyo3/pull/4874)\n\n### Removed\n\n- Remove implementations of `Deref` for `PyAny` and other \"native\" types. [#4593](https://github.com/PyO3/pyo3/pull/4593)\n- Remove implicit default of trailing optional arguments (see #2935) [#4729](https://github.com/PyO3/pyo3/pull/4729)\n- Remove the deprecated implicit eq fallback for simple enums. [#4730](https://github.com/PyO3/pyo3/pull/4730)\n\n### Fixed\n\n- Correct FFI definition of `PyIter_Send` to return a `PySendResult`. [#4746](https://github.com/PyO3/pyo3/pull/4746)\n- Fix a thread safety issue in the runtime borrow checker used by mutable pyclass instances on the free-threaded build. [#4948](https://github.com/PyO3/pyo3/pull/4948)\n\n\n## [0.23.5] - 2025-02-22\n\n### Packaging\n\n- Add support for PyPy3.11 [#4760](https://github.com/PyO3/pyo3/pull/4760)\n\n### Fixed\n\n- Fix thread-unsafe implementation of freelist pyclasses on the free-threaded build. [#4902](https://github.com/PyO3/pyo3/pull/4902)\n- Re-enable a workaround for situations where CPython incorrectly does not add `__builtins__` to `__globals__` in code executed by `Python::py_run` (was removed in PyO3 0.23.0). [#4921](https://github.com/PyO3/pyo3/pull/4921)\n\n## [0.23.4] - 2025-01-10\n\n### Added\n\n- Add `PyList::locked_for_each`, which uses a critical section to lock the list on the free-threaded build. [#4789](https://github.com/PyO3/pyo3/pull/4789)\n- Add `pyo3_build_config::add_python_framework_link_args` build script API to set rpath when using macOS system Python. [#4833](https://github.com/PyO3/pyo3/pull/4833)\n\n### Changed\n\n- Use `datetime.fold` to distinguish ambiguous datetimes when converting to and from `chrono::DateTime<Tz>` (rather than erroring). [#4791](https://github.com/PyO3/pyo3/pull/4791)\n- Optimize PyList iteration on the free-threaded build. [#4789](https://github.com/PyO3/pyo3/pull/4789)\n\n### Fixed\n\n- Fix unnecessary internal `py.allow_threads` GIL-switch when attempting to access contents of a `PyErr` which originated from Python (could lead to unintended deadlocks). [#4766](https://github.com/PyO3/pyo3/pull/4766)\n- Fix thread-unsafe access of dict internals in `BoundDictIterator` on the free-threaded build. [#4788](https://github.com/PyO3/pyo3/pull/4788)\n* Fix unnecessary critical sections in `BoundDictIterator` on the free-threaded build. [#4788](https://github.com/PyO3/pyo3/pull/4788)\n- Fix time-of-check to time-of-use issues with list iteration on the free-threaded build. [#4789](https://github.com/PyO3/pyo3/pull/4789)\n- Fix `chrono::DateTime<Tz>` to-Python conversion when `Tz` is `chrono_tz::Tz`. [#4790](https://github.com/PyO3/pyo3/pull/4790)\n- Fix `#[pyclass]` not being able to be named `Probe`. [#4794](https://github.com/PyO3/pyo3/pull/4794)\n- Fix not treating cross-compilation from x64 to aarch64 on Windows as a cross-compile. [#4800](https://github.com/PyO3/pyo3/pull/4800)\n- Fix missing struct fields on GraalPy when subclassing builtin classes. [#4802](https://github.com/PyO3/pyo3/pull/4802)\n- Fix generating import lib for PyPy when `abi3` feature is enabled. [#4806](https://github.com/PyO3/pyo3/pull/4806)\n- Fix generating import lib for python3.13t when `abi3` feature is enabled. [#4808](https://github.com/PyO3/pyo3/pull/4808)\n- Fix compile failure for raw identifiers like `r#box` in `derive(FromPyObject)`. [#4814](https://github.com/PyO3/pyo3/pull/4814)\n- Fix compile failure for `#[pyclass]` enum variants with more than 12 fields. [#4832](https://github.com/PyO3/pyo3/pull/4832)\n\n\n## [0.23.3] - 2024-12-03\n\n### Packaging\n\n- Bump optional `python3-dll-a` dependency to 0.2.11. [#4749](https://github.com/PyO3/pyo3/pull/4749)\n\n### Fixed\n\n- Fix unresolved symbol link failures on Windows when compiling for Python 3.13t with `abi3` features enabled. [#4733](https://github.com/PyO3/pyo3/pull/4733)\n- Fix unresolved symbol link failures on Windows when compiling for Python 3.13t using the `generate-import-lib` feature. [#4749](https://github.com/PyO3/pyo3/pull/4749)\n- Fix compile-time regression in PyO3 0.23.0 where changing `PYO3_CONFIG_FILE` would not reconfigure PyO3 for the new interpreter. [#4758](https://github.com/PyO3/pyo3/pull/4758)\n\n## [0.23.2] - 2024-11-25\n\n### Added\n\n- Add `IntoPyObjectExt` trait. [#4708](https://github.com/PyO3/pyo3/pull/4708)\n\n### Fixed\n\n- Fix compile failures when building for free-threaded Python when the `abi3` or `abi3-pyxx` features are enabled. [#4719](https://github.com/PyO3/pyo3/pull/4719)\n- Fix `ambiguous_associated_items` lint error in `#[pyclass]` and `#[derive(IntoPyObject)]` macros. [#4725](https://github.com/PyO3/pyo3/pull/4725)\n\n\n## [0.23.1] - 2024-11-16\n\nRe-release of 0.23.0 with fixes to docs.rs build.\n\n## [0.23.0] - 2024-11-15\n\n### Packaging\n\n- Drop support for PyPy 3.7 and 3.8. [#4582](https://github.com/PyO3/pyo3/pull/4582)\n- Extend range of supported versions of `hashbrown` optional dependency to include version 0.15. [#4604](https://github.com/PyO3/pyo3/pull/4604)\n- Bump minimum version of `eyre` optional dependency to 0.6.8. [#4617](https://github.com/PyO3/pyo3/pull/4617)\n- Bump minimum version of `hashbrown` optional dependency to 0.14.5. [#4617](https://github.com/PyO3/pyo3/pull/4617)\n- Bump minimum version of `indexmap` optional dependency to 2.5.0. [#4617](https://github.com/PyO3/pyo3/pull/4617)\n- Bump minimum version of `num-complex` optional dependency to 0.4.6. [#4617](https://github.com/PyO3/pyo3/pull/4617)\n- Bump minimum version of `chrono-tz` optional dependency to 0.10. [#4617](https://github.com/PyO3/pyo3/pull/4617)\n- Support free-threaded Python 3.13t. [#4588](https://github.com/PyO3/pyo3/pull/4588)\n\n### Added\n\n- Add `IntoPyObject` (fallible) conversion trait to convert from Rust to Python values. [#4060](https://github.com/PyO3/pyo3/pull/4060)\n- Add `#[pyclass(str=\"<format string>\")]` option to generate `__str__` based on a `Display` implementation or format string. [#4233](https://github.com/PyO3/pyo3/pull/4233)\n- Implement `PartialEq` for `Bound<'py, PyInt>` with `u8`, `u16`, `u32`, `u64`, `u128`, `usize`, `i8`, `i16`, `i32`, `i64`, `i128` and `isize`. [#4317](https://github.com/PyO3/pyo3/pull/4317)\n- Implement `PartialEq<f64>` and `PartialEq<f32>` for `Bound<'py, PyFloat>`. [#4348](https://github.com/PyO3/pyo3/pull/4348)\n- Add `as_super` and `into_super` methods for `Bound<T: PyClass>`. [#4351](https://github.com/PyO3/pyo3/pull/4351)\n- Add FFI definitions `PyCFunctionFast` and `PyCFunctionFastWithKeywords` [#4415](https://github.com/PyO3/pyo3/pull/4415)\n- Add FFI definitions for `PyMutex` on Python 3.13 and newer. [#4421](https://github.com/PyO3/pyo3/pull/4421)\n- Add `PyDict::locked_for_each` to iterate efficiently on freethreaded Python. [#4439](https://github.com/PyO3/pyo3/pull/4439)\n- Add FFI definitions `PyObject_GetOptionalAttr`, `PyObject_GetOptionalAttrString`, `PyObject_HasAttrWithError`, `PyObject_HasAttrStringWithError`, `Py_CONSTANT_*` constants, `Py_GetConstant`, `Py_GetConstantBorrowed`, and `PyType_GetModuleByDef` on Python 3.13 and newer. [#4447](https://github.com/PyO3/pyo3/pull/4447)\n- Add FFI definitions for the Python critical section API available on Python 3.13 and newer. [#4477](https://github.com/PyO3/pyo3/pull/4477)\n- Add derive macro for `IntoPyObject`. [#4495](https://github.com/PyO3/pyo3/pull/4495)\n- Add `Borrowed::as_ptr`. [#4520](https://github.com/PyO3/pyo3/pull/4520)\n- Add FFI definition for `PyImport_AddModuleRef`. [#4529](https://github.com/PyO3/pyo3/pull/4529)\n- Add `PyAnyMethods::try_iter`. [#4553](https://github.com/PyO3/pyo3/pull/4553)\n- Add `pyo3::sync::with_critical_section`, a wrapper around the Python Critical Section API added in Python 3.13. [#4587](https://github.com/PyO3/pyo3/pull/4587)\n- Add `#[pymodule(gil_used = false)]` option to declare that a module supports the free-threaded build. [#4588](https://github.com/PyO3/pyo3/pull/4588)\n- Add `PyModule::gil_used` method to declare that a module supports the free-threaded build. [#4588](https://github.com/PyO3/pyo3/pull/4588)\n- Add FFI definition `PyDateTime_CAPSULE_NAME`. [#4634](https://github.com/PyO3/pyo3/pull/4634)\n- Add `PyMappingProxy` type to represent the `mappingproxy` Python class. [#4644](https://github.com/PyO3/pyo3/pull/4644)\n- Add FFI definitions `PyList_Extend` and `PyList_Clear`. [#4667](https://github.com/PyO3/pyo3/pull/4667)\n- Add derive macro for `IntoPyObjectRef`. [#4674](https://github.com/PyO3/pyo3/pull/4674)\n- Add `pyo3::sync::OnceExt` and `pyo3::sync::OnceLockExt` traits. [#4676](https://github.com/PyO3/pyo3/pull/4676)\n\n### Changed\n\n- Prefer `IntoPyObject` over `IntoPy<Py<PyAny>>>` for `#[pyfunction]` and `#[pymethods]` return types. [#4060](https://github.com/PyO3/pyo3/pull/4060)\n- Report multiple errors from `#[pyclass]` and `#[pyo3(..)]` attributes. [#4243](https://github.com/PyO3/pyo3/pull/4243)\n- Nested declarative `#[pymodule]` are automatically treated as submodules (no `PyInit_` entrypoint is created). [#4308](https://github.com/PyO3/pyo3/pull/4308)\n- Deprecate `PyAnyMethods::is_ellipsis` (`Py::is_ellipsis` was deprecated in PyO3 0.20). [#4322](https://github.com/PyO3/pyo3/pull/4322)\n- Deprecate `PyLong` in favor of `PyInt`. [#4347](https://github.com/PyO3/pyo3/pull/4347)\n- Rename `IntoPyDict::into_py_dict_bound` to `IntoPyDict::into_py_dict`. [#4388](https://github.com/PyO3/pyo3/pull/4388)\n- `PyModule::from_code` now expects `&CStr` as arguments instead of `&str`. [#4404](https://github.com/PyO3/pyo3/pull/4404)\n- Use \"fastcall\" Python calling convention for `#[pyfunction]`s when compiling on abi3 for Python 3.10 and up. [#4415](https://github.com/PyO3/pyo3/pull/4415)\n- Remove `Copy` and `Clone` from `PyObject` struct FFI definition. [#4434](https://github.com/PyO3/pyo3/pull/4434)\n- `Python::eval` and `Python::run` now take a `&CStr` instead of `&str`. [#4435](https://github.com/PyO3/pyo3/pull/4435)\n- Deprecate `IPowModulo`, `PyClassAttributeDef`, `PyGetterDef`, `PyMethodDef`, `PyMethodDefType`, and `PySetterDef` from PyO3's public API. [#4441](https://github.com/PyO3/pyo3/pull/4441)\n- `IntoPyObject` impls for `Vec<u8>`, `&[u8]`, `[u8; N]`, `Cow<[u8]>` and `SmallVec<[u8; N]>` now convert into Python `bytes` rather than a `list` of integers. [#4442](https://github.com/PyO3/pyo3/pull/4442)\n- Emit a compile-time error when attempting to subclass a class that doesn't allow subclassing. [#4453](https://github.com/PyO3/pyo3/pull/4453)\n- `IntoPyDict::into_py_dict` is now fallible due to `IntoPyObject` migration. [#4493](https://github.com/PyO3/pyo3/pull/4493)\n- The `abi3` feature will now override config files provided via `PYO3_BUILD_CONFIG`. [#4497](https://github.com/PyO3/pyo3/pull/4497)\n- Disable the `GILProtected` struct on free-threaded Python. [#4504](https://github.com/PyO3/pyo3/pull/4504)\n- Updated FFI definitions for functions and struct fields that have been deprecated or removed from CPython. [#4534](https://github.com/PyO3/pyo3/pull/4534)\n- Disable `PyListMethods::get_item_unchecked` on free-threaded Python. [#4539](https://github.com/PyO3/pyo3/pull/4539)\n- Add `GILOnceCell::import`. [#4542](https://github.com/PyO3/pyo3/pull/4542)\n- Deprecate `PyAnyMethods::iter` in favour of `PyAnyMethods::try_iter`. [#4553](https://github.com/PyO3/pyo3/pull/4553)\n- The `#[pyclass]` macro now requires a types to be `Sync`. (Except for `#[pyclass(unsendable)]` types). [#4566](https://github.com/PyO3/pyo3/pull/4566)\n- `PyList::new` and `PyTuple::new` are now fallible due to `IntoPyObject` migration. [#4580](https://github.com/PyO3/pyo3/pull/4580)\n- `PyErr::matches` is now fallible due to `IntoPyObject` migration. [#4595](https://github.com/PyO3/pyo3/pull/4595)\n- Deprecate `ToPyObject` in favour of `IntoPyObject` [#4595](https://github.com/PyO3/pyo3/pull/4595)\n- Deprecate `PyWeakrefMethods::get_option`. [#4597](https://github.com/PyO3/pyo3/pull/4597)\n- Seal `PyWeakrefMethods` trait. [#4598](https://github.com/PyO3/pyo3/pull/4598)\n- Remove `PyNativeTypeInitializer` and `PyObjectInit` from the PyO3 public API. [#4611](https://github.com/PyO3/pyo3/pull/4611)\n- Deprecate `IntoPy` in favor of `IntoPyObject` [#4618](https://github.com/PyO3/pyo3/pull/4618)\n- Eagerly normalize exceptions in `PyErr::take()` and `PyErr::fetch()` on Python 3.11 and older. [#4655](https://github.com/PyO3/pyo3/pull/4655)\n- Move `IntoPy::type_output` to `IntoPyObject::type_output`. [#4657](https://github.com/PyO3/pyo3/pull/4657)\n- Change return type of `PyMapping::keys`, `PyMapping::values` and `PyMapping::items` to `Bound<'py, PyList>` instead of `Bound<'py, PySequence>`. [#4661](https://github.com/PyO3/pyo3/pull/4661)\n- Complex enums now allow field types that either implement `IntoPyObject` by reference or by value together with `Clone`. This makes `Py<T>` available as field type. [#4694](https://github.com/PyO3/pyo3/pull/4694)\n\n\n### Removed\n\n- Remove all functionality deprecated in PyO3 0.20. [#4322](https://github.com/PyO3/pyo3/pull/4322)\n- Remove all functionality deprecated in PyO3 0.21. [#4323](https://github.com/PyO3/pyo3/pull/4323)\n- Deprecate `PyUnicode` in favour of `PyString`. [#4370](https://github.com/PyO3/pyo3/pull/4370)\n- Remove deprecated `gil-refs` feature. [#4378](https://github.com/PyO3/pyo3/pull/4378)\n- Remove private FFI definitions `_Py_IMMORTAL_REFCNT`, `_Py_IsImmortal`, `_Py_TPFLAGS_STATIC_BUILTIN`, `_Py_Dealloc`, `_Py_IncRef`, `_Py_DecRef`. [#4447](https://github.com/PyO3/pyo3/pull/4447)\n- Remove private FFI definitions `_Py_c_sum`, `_Py_c_diff`, `_Py_c_neg`, `_Py_c_prod`, `_Py_c_quot`, `_Py_c_pow`, `_Py_c_abs`. [#4521](https://github.com/PyO3/pyo3/pull/4521)\n- Remove `_borrowed` methods of `PyWeakRef` and `PyWeakRefProxy`. [#4528](https://github.com/PyO3/pyo3/pull/4528)\n- Removed private FFI definition `_PyErr_ChainExceptions`. [#4534](https://github.com/PyO3/pyo3/pull/4534)\n\n### Fixed\n\n- Fix invalid library search path `lib_dir` when cross-compiling. [#4389](https://github.com/PyO3/pyo3/pull/4389)\n- Fix FFI definition `Py_Is` for PyPy on 3.10 to call the function defined by PyPy. [#4447](https://github.com/PyO3/pyo3/pull/4447)\n- Fix compile failure when using `#[cfg]` attributes for simple enum variants. [#4509](https://github.com/PyO3/pyo3/pull/4509)\n- Fix compiler warning for `non_snake_case` method names inside `#[pymethods]` generated code. [#4567](https://github.com/PyO3/pyo3/pull/4567)\n- Fix compile error with `#[derive(FromPyObject)]` generic struct with trait bounds. [#4645](https://github.com/PyO3/pyo3/pull/4645)\n- Fix compile error for `#[classmethod]` and `#[staticmethod]` on magic methods. [#4654](https://github.com/PyO3/pyo3/pull/4654)\n- Fix compile warning for `unsafe_op_in_unsafe_fn` in generated macro code. [#4674](https://github.com/PyO3/pyo3/pull/4674)\n- Fix incorrect deprecation warning for `#[pyclass] enum`s with custom `__eq__` implementation. [#4692](https://github.com/PyO3/pyo3/pull/4692)\n- Fix `non_upper_case_globals` lint firing for generated `__match_args__` on complex enums. [#4705](https://github.com/PyO3/pyo3/pull/4705)\n\n## [0.22.5] - 2024-10-15\n\n### Fixed\n\n- Fix regression in 0.22.4 of naming collision in `__clear__` slot and `clear` method generated code. [#4619](https://github.com/PyO3/pyo3/pull/4619)\n\n\n## [0.22.4] - 2024-10-12\n\n### Added\n\n- Add FFI definition `PyWeakref_GetRef` and `compat::PyWeakref_GetRef`. [#4528](https://github.com/PyO3/pyo3/pull/4528)\n\n### Changed\n\n- Deprecate `_borrowed` methods on `PyWeakRef` and `PyWeakrefProxy` (just use the owning forms). [#4590](https://github.com/PyO3/pyo3/pull/4590)\n\n### Fixed\n\n- Revert removal of private FFI function `_PyLong_NumBits` on Python 3.13 and later. [#4450](https://github.com/PyO3/pyo3/pull/4450)\n- Fix `__traverse__` functions for base classes not being called by subclasses created with `#[pyclass(extends = ...)]`. [#4563](https://github.com/PyO3/pyo3/pull/4563)\n- Fix regression in 0.22.3 failing compiles under `#![forbid(unsafe_code)]`. [#4574](https://github.com/PyO3/pyo3/pull/4574)\n- Fix `create_exception` macro triggering lint and compile errors due to interaction with `gil-refs` feature. [#4589](https://github.com/PyO3/pyo3/pull/4589)\n- Workaround possible use-after-free in `_borrowed` methods on `PyWeakRef` and `PyWeakrefProxy` by leaking their contents. [#4590](https://github.com/PyO3/pyo3/pull/4590)\n- Fix crash calling `PyType_GetSlot` on static types before Python 3.10. [#4599](https://github.com/PyO3/pyo3/pull/4599)\n\n\n## [0.22.3] - 2024-09-15\n\n### Added\n\n- Add `pyo3::ffi::compat` namespace with compatibility shims for C API functions added in recent versions of Python.\n- Add FFI definition `PyDict_GetItemRef` on Python 3.13 and newer, and `compat::PyDict_GetItemRef` for all versions. [#4355](https://github.com/PyO3/pyo3/pull/4355)\n- Add FFI definition `PyList_GetItemRef` on Python 3.13 and newer, and `pyo3_ffi::compat::PyList_GetItemRef` for all versions. [#4410](https://github.com/PyO3/pyo3/pull/4410)\n- Add FFI definitions `compat::Py_NewRef` and `compat::Py_XNewRef`. [#4445](https://github.com/PyO3/pyo3/pull/4445)\n- Add FFI definitions `compat::PyObject_CallNoArgs` and `compat::PyObject_CallMethodNoArgs`. [#4461](https://github.com/PyO3/pyo3/pull/4461)\n- Add `GilOnceCell<Py<T>>::clone_ref`. [#4511](https://github.com/PyO3/pyo3/pull/4511)\n\n### Changed\n\n- Improve error messages for `#[pyfunction]` defined inside `#[pymethods]`. [#4349](https://github.com/PyO3/pyo3/pull/4349)\n- Improve performance of calls to Python by using the vectorcall calling convention where possible. [#4456](https://github.com/PyO3/pyo3/pull/4456)\n- Mention the type name in the exception message when trying to instantiate a class with no constructor defined. [#4481](https://github.com/PyO3/pyo3/pull/4481)\n\n### Removed\n\n- Remove private FFI definition `_Py_PackageContext`. [#4420](https://github.com/PyO3/pyo3/pull/4420)\n\n### Fixed\n\n- Fix compile failure in declarative `#[pymodule]` under presence of `#![no_implicit_prelude]`. [#4328](https://github.com/PyO3/pyo3/pull/4328)\n- Fix use of borrowed reference in `PyDict::get_item` (unsafe in free-threaded Python). [#4355](https://github.com/PyO3/pyo3/pull/4355)\n- Fix `#[pyclass(eq)]` macro hygiene issues for structs and enums. [#4359](https://github.com/PyO3/pyo3/pull/4359)\n- Fix hygiene/span issues of `#[pyfunction]` and `#[pymethods]` generated code which affected expansion in `macro_rules` context. [#4382](https://github.com/PyO3/pyo3/pull/4382)\n- Fix `unsafe_code` lint error in `#[pyclass]` generated code. [#4396](https://github.com/PyO3/pyo3/pull/4396)\n- Fix async functions returning a tuple only returning the first element to Python. [#4407](https://github.com/PyO3/pyo3/pull/4407)\n- Fix use of borrowed reference in `PyList::get_item` (unsafe in free-threaded Python). [#4410](https://github.com/PyO3/pyo3/pull/4410)\n- Correct FFI definition `PyArg_ParseTupleAndKeywords` to take `*const *const c_char` instead of `*mut *mut c_char` on Python 3.13 and up. [#4420](https://github.com/PyO3/pyo3/pull/4420)\n- Fix a soundness bug with `PyClassInitializer`: panic if adding subclass to existing instance via `PyClassInitializer::from(Py<BaseClass>).add_subclass(SubClass)`. [#4454](https://github.com/PyO3/pyo3/pull/4454)\n- Fix illegal reference counting op inside implementation of `__traverse__` handlers. [#4479](https://github.com/PyO3/pyo3/pull/4479)\n\n## [0.22.2] - 2024-07-17\n\n### Packaging\n\n- Require opt-in to freethreaded Python using the `UNSAFE_PYO3_BUILD_FREE_THREADED=1` environment variable (it is not yet supported by PyO3). [#4327](https://github.com/PyO3/pyo3/pull/4327)\n\n### Changed\n\n- Use FFI function calls for reference counting on all abi3 versions. [#4324](https://github.com/PyO3/pyo3/pull/4324)\n- `#[pymodule(...)]` now directly accepts all relevant `#[pyo3(...)]` options. [#4330](https://github.com/PyO3/pyo3/pull/4330)\n\n### Fixed\n\n- Fix compile failure in declarative `#[pymodule]` under presence of `#![no_implicit_prelude]`. [#4328](https://github.com/PyO3/pyo3/pull/4328)\n- Fix compile failure due to c-string literals on Rust < 1.79. [#4353](https://github.com/PyO3/pyo3/pull/4353)\n\n## [0.22.1] - 2024-07-06\n\n### Added\n\n- Add `#[pyo3(submodule)]` option for declarative `#[pymodule]`s. [#4301](https://github.com/PyO3/pyo3/pull/4301)\n- Implement `PartialEq<bool>` for `Bound<'py, PyBool>`. [#4305](https://github.com/PyO3/pyo3/pull/4305)\n\n### Fixed\n\n- Return `NotImplemented` instead of raising `TypeError` from generated equality method when comparing different types. [#4287](https://github.com/PyO3/pyo3/pull/4287)\n- Handle full-path `#[pyo3::prelude::pymodule]` and similar for `#[pyclass]` and `#[pyfunction]` in declarative modules. [#4288](https://github.com/PyO3/pyo3/pull/4288)\n- Fix 128-bit int regression on big-endian platforms with Python <3.13. [#4291](https://github.com/PyO3/pyo3/pull/4291)\n- Stop generating code that will never be covered with declarative modules. [#4297](https://github.com/PyO3/pyo3/pull/4297)\n- Fix invalid deprecation warning for trailing optional on `#[setter]` function. [#4304](https://github.com/PyO3/pyo3/pull/4304)\n\n## [0.22.0] - 2024-06-24\n\n### Packaging\n\n- Update `heck` dependency to 0.5. [#3966](https://github.com/PyO3/pyo3/pull/3966)\n- Extend range of supported versions of `chrono-tz` optional dependency to include version 0.10. [#4061](https://github.com/PyO3/pyo3/pull/4061)\n- Update MSRV to 1.63. [#4129](https://github.com/PyO3/pyo3/pull/4129)\n- Add optional `num-rational` feature to add conversions with Python's `fractions.Fraction`. [#4148](https://github.com/PyO3/pyo3/pull/4148)\n- Support Python 3.13. [#4184](https://github.com/PyO3/pyo3/pull/4184)\n\n### Added\n\n- Add `PyWeakref`, `PyWeakrefReference` and `PyWeakrefProxy`. [#3835](https://github.com/PyO3/pyo3/pull/3835)\n- Support `#[pyclass]` on enums that have tuple variants. [#4072](https://github.com/PyO3/pyo3/pull/4072)\n- Add support for scientific notation in `Decimal` conversion. [#4079](https://github.com/PyO3/pyo3/pull/4079)\n- Add `pyo3_disable_reference_pool` conditional compilation flag to avoid the overhead of the global reference pool at the cost of known limitations as explained in the performance section of the guide. [#4095](https://github.com/PyO3/pyo3/pull/4095)\n- Add `#[pyo3(constructor = (...))]` to customize the generated constructors for complex enum variants. [#4158](https://github.com/PyO3/pyo3/pull/4158)\n- Add `PyType::module`, which always matches Python `__module__`. [#4196](https://github.com/PyO3/pyo3/pull/4196)\n- Add `PyType::fully_qualified_name` which matches the \"fully qualified name\" defined in [PEP 737](https://peps.python.org/pep-0737). [#4196](https://github.com/PyO3/pyo3/pull/4196)\n- Add `PyTypeMethods::mro` and `PyTypeMethods::bases`. [#4197](https://github.com/PyO3/pyo3/pull/4197)\n- Add `#[pyclass(ord)]` to implement ordering based on `PartialOrd`. [#4202](https://github.com/PyO3/pyo3/pull/4202)\n- Implement `ToPyObject` and `IntoPy<PyObject>` for `PyBackedStr` and `PyBackedBytes`. [#4205](https://github.com/PyO3/pyo3/pull/4205)\n- Add `#[pyclass(hash)]` option to implement `__hash__` in terms of the `Hash` implementation [#4206](https://github.com/PyO3/pyo3/pull/4206)\n- Add `#[pyclass(eq)]` option to generate `__eq__` based on `PartialEq`, and `#[pyclass(eq_int)]` for simple enums to implement equality based on their discriminants. [#4210](https://github.com/PyO3/pyo3/pull/4210)\n- Implement `From<Bound<'py, T>>` for `PyClassInitializer<T>`. [#4214](https://github.com/PyO3/pyo3/pull/4214)\n- Add `as_super` methods to `PyRef` and `PyRefMut` for accessing the base class by reference. [#4219](https://github.com/PyO3/pyo3/pull/4219)\n- Implement `PartialEq<str>` for `Bound<'py, PyString>`. [#4245](https://github.com/PyO3/pyo3/pull/4245)\n- Implement `PyModuleMethods::filename` on PyPy. [#4249](https://github.com/PyO3/pyo3/pull/4249)\n- Implement `PartialEq<[u8]>` for `Bound<'py, PyBytes>`. [#4250](https://github.com/PyO3/pyo3/pull/4250)\n- Add `pyo3_ffi::c_str` macro to create `&'static CStr` on Rust versions which don't have 1.77's `c\"\"` literals. [#4255](https://github.com/PyO3/pyo3/pull/4255)\n- Support `bool` conversion with `numpy` 2.0's `numpy.bool` type [#4258](https://github.com/PyO3/pyo3/pull/4258)\n- Add `PyAnyMethods::{bitnot, matmul, floor_div, rem, divmod}`. [#4264](https://github.com/PyO3/pyo3/pull/4264)\n\n### Changed\n\n- Change the type of `PySliceIndices::slicelength` and the `length` parameter of `PySlice::indices()`. [#3761](https://github.com/PyO3/pyo3/pull/3761)\n- Deprecate implicit default for trailing optional arguments [#4078](https://github.com/PyO3/pyo3/pull/4078)\n- `Clone`ing pointers into the Python heap has been moved behind the `py-clone` feature, as it must panic without the GIL being held as a soundness fix. [#4095](https://github.com/PyO3/pyo3/pull/4095)\n- Add `#[track_caller]` to all `Py<T>`, `Bound<'py, T>` and `Borrowed<'a, 'py, T>` methods which can panic. [#4098](https://github.com/PyO3/pyo3/pull/4098)\n- Change `PyAnyMethods::dir` to be fallible and return `PyResult<Bound<'py, PyList>>` (and similar for `PyAny::dir`). [#4100](https://github.com/PyO3/pyo3/pull/4100)\n- The global reference pool (to track pending reference count decrements) is now initialized lazily to avoid the overhead of taking a mutex upon function entry when the functionality is not actually used. [#4178](https://github.com/PyO3/pyo3/pull/4178)\n- Emit error messages when using `weakref` or `dict` when compiling for `abi3` for Python older than 3.9. [#4194](https://github.com/PyO3/pyo3/pull/4194)\n- Change `PyType::name` to always match Python `__name__`. [#4196](https://github.com/PyO3/pyo3/pull/4196)\n- Remove CPython internal ffi call for complex number including: add, sub, mul, div, neg, abs, pow. Added PyAnyMethods::{abs, pos, neg} [#4201](https://github.com/PyO3/pyo3/pull/4201)\n- Deprecate implicit integer comparison for simple enums in favor of `#[pyclass(eq_int)]`. [#4210](https://github.com/PyO3/pyo3/pull/4210)\n- Set the `module=` attribute of declarative modules' child `#[pymodule]`s and `#[pyclass]`es. [#4213](https://github.com/PyO3/pyo3/pull/4213)\n- Set the `module` option for complex enum variants from the value set on the complex enum `module`. [#4228](https://github.com/PyO3/pyo3/pull/4228)\n- Respect the Python \"limited API\" when building for the `abi3` feature on PyPy or GraalPy. [#4237](https://github.com/PyO3/pyo3/pull/4237)\n- Optimize code generated by `#[pyo3(get)]` on `#[pyclass]` fields. [#4254](https://github.com/PyO3/pyo3/pull/4254)\n- `PyCFunction::new`, `PyCFunction::new_with_keywords` and `PyCFunction::new_closure` now take `&'static CStr` name and doc arguments (previously was `&'static str`). [#4255](https://github.com/PyO3/pyo3/pull/4255)\n- The `experimental-declarative-modules` feature is now stabilized and available by default. [#4257](https://github.com/PyO3/pyo3/pull/4257)\n\n### Fixed\n\n- Fix panic when `PYO3_CROSS_LIB_DIR` is set to a missing path. [#4043](https://github.com/PyO3/pyo3/pull/4043)\n- Fix a compile error when exporting an exception created with `create_exception!` living in a different Rust module using the `declarative-module` feature. [#4086](https://github.com/PyO3/pyo3/pull/4086)\n- Fix FFI definitions of `PY_VECTORCALL_ARGUMENTS_OFFSET` and `PyVectorcall_NARGS` to fix a false-positive assertion. [#4104](https://github.com/PyO3/pyo3/pull/4104)\n- Disable `PyUnicode_DATA` on PyPy: not exposed by PyPy. [#4116](https://github.com/PyO3/pyo3/pull/4116)\n- Correctly handle `#[pyo3(from_py_with = ...)]` attribute on dunder (`__magic__`) method arguments instead of silently ignoring it. [#4117](https://github.com/PyO3/pyo3/pull/4117)\n- Fix a compile error when declaring a standalone function or class method with a Python name that is a Rust keyword. [#4226](https://github.com/PyO3/pyo3/pull/4226)\n- Fix declarative modules discarding doc comments on the `mod` node. [#4236](https://github.com/PyO3/pyo3/pull/4236)\n- Fix `__dict__` attribute missing for `#[pyclass(dict)]` instances when building for `abi3` on Python 3.9. [#4251](https://github.com/PyO3/pyo3/pull/4251)\n\n## [0.21.2] - 2024-04-16\n\n### Changed\n\n- Deprecate the `PySet::empty()` gil-ref constructor. [#4082](https://github.com/PyO3/pyo3/pull/4082)\n\n### Fixed\n\n- Fix compile error for `async fn` in `#[pymethods]` with a `&self` receiver and more than one additional argument. [#4035](https://github.com/PyO3/pyo3/pull/4035)\n- Improve error message for wrong receiver type in `__traverse__`. [#4045](https://github.com/PyO3/pyo3/pull/4045)\n- Fix compile error when exporting a `#[pyclass]` living in a different Rust module using the `experimental-declarative-modules` feature. [#4054](https://github.com/PyO3/pyo3/pull/4054)\n- Fix `missing_docs` lint triggering on documented `#[pymodule]` functions. [#4067](https://github.com/PyO3/pyo3/pull/4067)\n- Fix undefined symbol errors for extension modules on AIX (by linking `libpython`). [#4073](https://github.com/PyO3/pyo3/pull/4073)\n\n## [0.21.1] - 2024-04-01\n\n### Added\n\n- Implement `Send` and `Sync` for `PyBackedStr` and `PyBackedBytes`. [#4007](https://github.com/PyO3/pyo3/pull/4007)\n- Implement `Clone`, `Debug`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash` implementation for `PyBackedBytes` and `PyBackedStr`, and `Display` for `PyBackedStr`. [#4020](https://github.com/PyO3/pyo3/pull/4020)\n- Add `import_exception_bound!` macro to import exception types without generating GIL Ref functionality for them. [#4027](https://github.com/PyO3/pyo3/pull/4027)\n\n### Changed\n\n- Emit deprecation warning for uses of GIL Refs as `#[setter]` function arguments. [#3998](https://github.com/PyO3/pyo3/pull/3998)\n- Add `#[inline]` hints on many `Bound` and `Borrowed` methods. [#4024](https://github.com/PyO3/pyo3/pull/4024)\n\n### Fixed\n\n- Handle `#[pyo3(from_py_with = \"\")]` in `#[setter]` methods [#3995](https://github.com/PyO3/pyo3/pull/3995)\n- Allow extraction of `&Bound` in `#[setter]` methods. [#3998](https://github.com/PyO3/pyo3/pull/3998)\n- Fix some uncovered code blocks emitted by `#[pymodule]`, `#[pyfunction]` and `#[pyclass]` macros. [#4009](https://github.com/PyO3/pyo3/pull/4009)\n- Fix typo in the panic message when a class referenced in `pyo3::import_exception!` does not exist. [#4012](https://github.com/PyO3/pyo3/pull/4012)\n- Fix compile error when using an async `#[pymethod]` with a receiver and additional arguments. [#4015](https://github.com/PyO3/pyo3/pull/4015)\n\n\n## [0.21.0] - 2024-03-25\n\n### Added\n\n- Add support for GraalPy (24.0 and up). [#3247](https://github.com/PyO3/pyo3/pull/3247)\n- Add `PyMemoryView` type. [#3514](https://github.com/PyO3/pyo3/pull/3514)\n- Allow `async fn` in for `#[pyfunction]` and `#[pymethods]`, with the `experimental-async` feature. [#3540](https://github.com/PyO3/pyo3/pull/3540) [#3588](https://github.com/PyO3/pyo3/pull/3588) [#3599](https://github.com/PyO3/pyo3/pull/3599) [#3931](https://github.com/PyO3/pyo3/pull/3931)\n- Implement `PyTypeInfo` for `PyEllipsis`, `PyNone` and `PyNotImplemented`. [#3577](https://github.com/PyO3/pyo3/pull/3577)\n- Support `#[pyclass]` on enums that have non-unit variants. [#3582](https://github.com/PyO3/pyo3/pull/3582)\n- Support `chrono` feature with `abi3` feature. [#3664](https://github.com/PyO3/pyo3/pull/3664)\n- `FromPyObject`, `IntoPy<PyObject>` and `ToPyObject` are implemented on `std::duration::Duration` [#3670](https://github.com/PyO3/pyo3/pull/3670)\n- Add `PyString::to_cow`. Add `Py<PyString>::to_str`, `Py<PyString>::to_cow`, and `Py<PyString>::to_string_lossy`, as ways to access Python string data safely beyond the GIL lifetime. [#3677](https://github.com/PyO3/pyo3/pull/3677)\n- Add `Bound<T>` and `Borrowed<T>` smart pointers as a new API for accessing Python objects. [#3686](https://github.com/PyO3/pyo3/pull/3686)\n- Add `PyNativeType::as_borrowed` to convert \"GIL refs\" to the new `Bound` smart pointer. [#3692](https://github.com/PyO3/pyo3/pull/3692)\n- Add `FromPyObject::extract_bound` method, to migrate `FromPyObject` implementations to the Bound API. [#3706](https://github.com/PyO3/pyo3/pull/3706)\n- Add `gil-refs` feature to allow continued use of the deprecated GIL Refs APIs. [#3707](https://github.com/PyO3/pyo3/pull/3707)\n- Add methods to `PyAnyMethods` for binary operators (`add`, `sub`, etc.) [#3712](https://github.com/PyO3/pyo3/pull/3712)\n- Add `chrono-tz` feature allowing conversion between `chrono_tz::Tz` and `zoneinfo.ZoneInfo` [#3730](https://github.com/PyO3/pyo3/pull/3730)\n- Add FFI definition `PyType_GetModuleByDef`. [#3734](https://github.com/PyO3/pyo3/pull/3734)\n- Conversion between `std::time::SystemTime` and `datetime.datetime` [#3736](https://github.com/PyO3/pyo3/pull/3736)\n- Add `Py::as_any` and `Py::into_any`. [#3785](https://github.com/PyO3/pyo3/pull/3785)\n- Add `PyStringMethods::encode_utf8`. [#3801](https://github.com/PyO3/pyo3/pull/3801)\n- Add `PyBackedStr` and `PyBackedBytes`, as alternatives to `&str` and `&bytes` where a Python object owns the data. [#3802](https://github.com/PyO3/pyo3/pull/3802) [#3991](https://github.com/PyO3/pyo3/pull/3991)\n- Allow `#[pymodule]` macro on Rust `mod` blocks, with the `experimental-declarative-modules` feature. [#3815](https://github.com/PyO3/pyo3/pull/3815)\n- Implement `ExactSizeIterator` for `set` and `frozenset` iterators on `abi3` feature. [#3849](https://github.com/PyO3/pyo3/pull/3849)\n- Add `Py::drop_ref` to explicitly drop a `Py`` and immediately decrease the Python reference count if the GIL is already held. [#3871](https://github.com/PyO3/pyo3/pull/3871)\n- Allow `#[pymodule]` macro on single argument functions that take `&Bound<'_, PyModule>`. [#3905](https://github.com/PyO3/pyo3/pull/3905)\n- Implement `FromPyObject` for `Cow<str>`. [#3928](https://github.com/PyO3/pyo3/pull/3928)\n- Implement `Default` for `GILOnceCell`. [#3971](https://github.com/PyO3/pyo3/pull/3971)\n- Add `PyDictMethods::into_mapping`, `PyListMethods::into_sequence` and `PyTupleMethods::into_sequence`. [#3982](https://github.com/PyO3/pyo3/pull/3982)\n\n### Changed\n\n- `PyDict::from_sequence` now takes a single argument of type `&PyAny` (previously took two arguments `Python` and `PyObject`). [#3532](https://github.com/PyO3/pyo3/pull/3532)\n- Deprecate `Py::is_ellipsis` and `PyAny::is_ellipsis` in favour of `any.is(py.Ellipsis())`. [#3577](https://github.com/PyO3/pyo3/pull/3577)\n- Split some `PyTypeInfo` functionality into new traits `HasPyGilRef` and `PyTypeCheck`. [#3600](https://github.com/PyO3/pyo3/pull/3600)\n- Deprecate `PyTryFrom` and `PyTryInto` traits in favor of `any.downcast()` via the `PyTypeCheck` and `PyTypeInfo` traits. [#3601](https://github.com/PyO3/pyo3/pull/3601)\n- Allow async methods to accept `&self`/`&mut self` [#3609](https://github.com/PyO3/pyo3/pull/3609)\n- `FromPyObject` for set types now also accept `frozenset` objects as input. [#3632](https://github.com/PyO3/pyo3/pull/3632)\n- `FromPyObject` for `bool` now also accepts NumPy's `bool_` as input. [#3638](https://github.com/PyO3/pyo3/pull/3638)\n- Add `AsRefSource` associated type to `PyNativeType`. [#3653](https://github.com/PyO3/pyo3/pull/3653)\n- Rename `.is_true` to `.is_truthy` on `PyAny` and `Py<PyAny>` to clarify that the test is not based on identity with or equality to the True singleton. [#3657](https://github.com/PyO3/pyo3/pull/3657)\n- `PyType::name` is now `PyType::qualname` whereas `PyType::name` efficiently accesses the full name which includes the module name. [#3660](https://github.com/PyO3/pyo3/pull/3660)\n- The `Iter(A)NextOutput` types are now deprecated and `__(a)next__` can directly return anything which can be converted into Python objects, i.e. awaitables do not need to be wrapped into `IterANextOutput` or `Option` any more. `Option` can still be used as well and returning `None` will trigger the fast path for `__next__`, stopping iteration without having to raise a `StopIteration` exception. [#3661](https://github.com/PyO3/pyo3/pull/3661)\n- Implement `FromPyObject` on `chrono::DateTime<Tz>` for all `Tz`, not just `FixedOffset` and `Utc`. [#3663](https://github.com/PyO3/pyo3/pull/3663)\n- Add lifetime parameter to `PyTzInfoAccess` trait. For the deprecated gil-ref API, the trait is now implemented for `&'py PyTime` and `&'py PyDateTime` instead of `PyTime` and `PyDate`. [#3679](https://github.com/PyO3/pyo3/pull/3679)\n- Calls to `__traverse__` become no-ops for unsendable pyclasses if on the wrong thread, thereby avoiding hard aborts at the cost of potential leakage. [#3689](https://github.com/PyO3/pyo3/pull/3689)\n- Include `PyNativeType` in `pyo3::prelude`. [#3692](https://github.com/PyO3/pyo3/pull/3692)\n- Improve performance of `extract::<i64>` (and other integer types) by avoiding call to `__index__()` converting the value to an integer for 3.10+. Gives performance improvement of around 30% for successful extraction. [#3742](https://github.com/PyO3/pyo3/pull/3742)\n- Relax bound of `FromPyObject` for `Py<T>` to just `T: PyTypeCheck`. [#3776](https://github.com/PyO3/pyo3/pull/3776)\n- `PySet` and `PyFrozenSet` iterators now always iterate the equivalent of `iter(set)`. (A \"fast path\" with no noticeable performance benefit was removed.) [#3849](https://github.com/PyO3/pyo3/pull/3849)\n- Move implementations of `FromPyObject` for `&str`, `Cow<str>`, `&[u8]` and `Cow<[u8]>` onto a temporary trait `FromPyObjectBound` when `gil-refs` feature is deactivated. [#3928](https://github.com/PyO3/pyo3/pull/3928)\n- Deprecate `GILPool`, `Python::with_pool`, and `Python::new_pool`. [#3947](https://github.com/PyO3/pyo3/pull/3947)\n\n### Removed\n\n- Remove all functionality deprecated in PyO3 0.19. [#3603](https://github.com/PyO3/pyo3/pull/3603)\n\n### Fixed\n\n- Match PyPy 7.3.14 in removing PyPy-only symbol `Py_MAX_NDIMS` in favour of `PyBUF_MAX_NDIM`. [#3757](https://github.com/PyO3/pyo3/pull/3757)\n- Fix segmentation fault using `datetime` types when an invalid `datetime` module is on sys.path. [#3818](https://github.com/PyO3/pyo3/pull/3818)\n- Fix `non_local_definitions` lint warning triggered by many PyO3 macros. [#3901](https://github.com/PyO3/pyo3/pull/3901)\n- Disable `PyCode` and `PyCode_Type` on PyPy: `PyCode_Type` is not exposed by PyPy. [#3934](https://github.com/PyO3/pyo3/pull/3934)\n\n## [0.21.0-beta.0] - 2024-03-10\n\nPrerelease of PyO3 0.21. See [the GitHub diff](https://github.com/pyo3/pyo3/compare/v0.21.0-beta.0...v0.21.0) for what changed between 0.21.0-beta.0 and the final release.\n\n## [0.20.3] - 2024-02-23\n\n### Packaging\n\n- Add `portable-atomic` dependency. [#3619](https://github.com/PyO3/pyo3/pull/3619)\n- Check maximum version of Python at build time and for versions not yet supported require opt-in to the `abi3` stable ABI by the environment variable `PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1`. [#3821](https://github.com/PyO3/pyo3/pull/3821)\n\n### Fixed\n\n- Use `portable-atomic` to support platforms without 64-bit atomics. [#3619](https://github.com/PyO3/pyo3/pull/3619)\n- Fix compilation failure with `either` feature enabled without `experimental-inspect` enabled. [#3834](https://github.com/PyO3/pyo3/pull/3834)\n\n## [0.20.2] - 2024-01-04\n\n### Packaging\n\n- Pin `pyo3` and `pyo3-ffi` dependencies on `pyo3-build-config` to require the same patch version, i.e. `pyo3` 0.20.2 requires _exactly_ `pyo3-build-config` 0.20.2. [#3721](https://github.com/PyO3/pyo3/pull/3721)\n\n### Fixed\n\n- Fix compile failure when building `pyo3` 0.20.0 with latest `pyo3-build-config` 0.20.X. [#3724](https://github.com/PyO3/pyo3/pull/3724)\n- Fix docs.rs build. [#3722](https://github.com/PyO3/pyo3/pull/3722)\n\n## [0.20.1] - 2023-12-30\n\n### Added\n\n- Add optional `either` feature to add conversions for `either::Either<L, R>` sum type. [#3456](https://github.com/PyO3/pyo3/pull/3456)\n- Add optional `smallvec` feature to add conversions for `smallvec::SmallVec`. [#3507](https://github.com/PyO3/pyo3/pull/3507)\n- Add `take` and `into_inner` methods to `GILOnceCell` [#3556](https://github.com/PyO3/pyo3/pull/3556)\n- `#[classmethod]` methods can now also receive `Py<PyType>` as their first argument. [#3587](https://github.com/PyO3/pyo3/pull/3587)\n- `#[pyfunction(pass_module)]` can now also receive `Py<PyModule>` as their first argument. [#3587](https://github.com/PyO3/pyo3/pull/3587)\n- Add `traverse` method to `GILProtected`. [#3616](https://github.com/PyO3/pyo3/pull/3616)\n- Added `abi3-py312` feature [#3687](https://github.com/PyO3/pyo3/pull/3687)\n\n### Fixed\n\n- Fix minimum version specification for optional `chrono` dependency. [#3512](https://github.com/PyO3/pyo3/pull/3512)\n- Silenced new `clippy::unnecessary_fallible_conversions` warning when using a `Py<Self>` `self` receiver. [#3564](https://github.com/PyO3/pyo3/pull/3564)\n\n\n## [0.20.0] - 2023-10-11\n\n### Packaging\n\n- Dual-license PyO3 under either the Apache 2.0 OR the MIT license. This makes the project GPLv2 compatible. [#3108](https://github.com/PyO3/pyo3/pull/3108)\n- Update MSRV to Rust 1.56. [#3208](https://github.com/PyO3/pyo3/pull/3208)\n- Bump `indoc` dependency to 2.0 and `unindent` dependency to 0.2. [#3237](https://github.com/PyO3/pyo3/pull/3237)\n- Bump `syn` dependency to 2.0. [#3239](https://github.com/PyO3/pyo3/pull/3239)\n- Drop support for debug builds of Python 3.7. [#3387](https://github.com/PyO3/pyo3/pull/3387)\n- Bump `chrono` optional dependency to require 0.4.25 or newer. [#3427](https://github.com/PyO3/pyo3/pull/3427)\n- Support Python 3.12. [#3488](https://github.com/PyO3/pyo3/pull/3488)\n\n### Added\n\n- Support `__lt__`, `__le__`, `__eq__`, `__ne__`, `__gt__` and `__ge__` in `#[pymethods]`. [#3203](https://github.com/PyO3/pyo3/pull/3203)\n- Add FFI definition `Py_GETENV`. [#3336](https://github.com/PyO3/pyo3/pull/3336)\n- Add `as_ptr` and `into_ptr` inherent methods for `Py`, `PyAny`, `PyRef`, and `PyRefMut`. [#3359](https://github.com/PyO3/pyo3/pull/3359)\n- Implement `DoubleEndedIterator` for `PyTupleIterator` and `PyListIterator`. [#3366](https://github.com/PyO3/pyo3/pull/3366)\n- Add `#[pyclass(rename_all = \"...\")]` option: this allows renaming all getters and setters of a struct, or all variants of an enum. Available renaming rules are: `\"camelCase\"`, `\"kebab-case\"`, `\"lowercase\"`, `\"PascalCase\"`, `\"SCREAMING-KEBAB-CASE\"`, `\"SCREAMING_SNAKE_CASE\"`, `\"snake_case\"`, `\"UPPERCASE\"`. [#3384](https://github.com/PyO3/pyo3/pull/3384)\n- Add FFI definitions `PyObject_GC_IsTracked` and `PyObject_GC_IsFinalized` on Python 3.9 and up (PyPy 3.10 and up). [#3403](https://github.com/PyO3/pyo3/pull/3403)\n- Add types for `None`, `Ellipsis`, and `NotImplemented`. [#3408](https://github.com/PyO3/pyo3/pull/3408)\n- Add FFI definitions for the `Py_mod_multiple_interpreters` constant and its possible values. [#3494](https://github.com/PyO3/pyo3/pull/3494)\n- Add FFI definitions for `PyInterpreterConfig` struct, its constants and `Py_NewInterpreterFromConfig`. [#3502](https://github.com/PyO3/pyo3/pull/3502)\n\n### Changed\n\n- Change `PySet::discard` to return `PyResult<bool>` (previously returned nothing). [#3281](https://github.com/PyO3/pyo3/pull/3281)\n- Optimize implementation of `IntoPy` for Rust tuples to Python tuples. [#3321](https://github.com/PyO3/pyo3/pull/3321)\n- Change `PyDict::get_item` to no longer suppress arbitrary exceptions (the return type is now `PyResult<Option<&PyAny>>` instead of `Option<&PyAny>`), and deprecate `PyDict::get_item_with_error`. [#3330](https://github.com/PyO3/pyo3/pull/3330)\n- Deprecate FFI definitions which are deprecated in Python 3.12. [#3336](https://github.com/PyO3/pyo3/pull/3336)\n- `AsPyPointer` is now an `unsafe trait`. [#3358](https://github.com/PyO3/pyo3/pull/3358)\n- Accept all `os.PathLike` values in implementation of `FromPyObject` for `PathBuf`. [#3374](https://github.com/PyO3/pyo3/pull/3374)\n- Add `__builtins__` to globals in `py.run()` and `py.eval()` if they're missing. [#3378](https://github.com/PyO3/pyo3/pull/3378)\n- Optimize implementation of `FromPyObject` for `BigInt` and `BigUint`. [#3379](https://github.com/PyO3/pyo3/pull/3379)\n- `PyIterator::from_object` and `PyByteArray::from` now take a single argument of type `&PyAny` (previously took two arguments `Python` and `AsPyPointer`). [#3389](https://github.com/PyO3/pyo3/pull/3389)\n- Replace `AsPyPointer` with `AsRef<PyAny>` as a bound in the blanket implementation of `From<&T> for PyObject`. [#3391](https://github.com/PyO3/pyo3/pull/3391)\n- Replace blanket `impl IntoPy<PyObject> for &T where T: AsPyPointer` with implementations of `impl IntoPy<PyObject>` for `&PyAny`, `&T where T: AsRef<PyAny>`, and `&Py<T>`. [#3393](https://github.com/PyO3/pyo3/pull/3393)\n- Preserve `std::io::Error` kind in implementation of `From<std::io::IntoInnerError>` for `PyErr` [#3396](https://github.com/PyO3/pyo3/pull/3396)\n- Try to select a relevant `ErrorKind` in implementation of `From<PyErr>` for `OSError` subclass. [#3397](https://github.com/PyO3/pyo3/pull/3397)\n- Retrieve the original `PyErr` in implementation of `From<std::io::Error>` for `PyErr` if the `std::io::Error` has been built using a Python exception (previously would create a new exception wrapping the `std::io::Error`). [#3402](https://github.com/PyO3/pyo3/pull/3402)\n- `#[pymodule]` will now return the same module object on repeated import by the same Python interpreter, on Python 3.9 and up. [#3446](https://github.com/PyO3/pyo3/pull/3446)\n- Truncate leap-seconds and warn when converting `chrono` types to Python `datetime` types (`datetime` cannot represent leap-seconds). [#3458](https://github.com/PyO3/pyo3/pull/3458)\n- `Err` returned from `#[pyfunction]` will now have a non-None `__context__` if called from inside a `catch` block. [#3455](https://github.com/PyO3/pyo3/pull/3455)\n- Deprecate undocumented `#[__new__]` form of `#[new]` attribute. [#3505](https://github.com/PyO3/pyo3/pull/3505)\n\n### Removed\n\n- Remove all functionality deprecated in PyO3 0.18, including `#[args]` attribute for `#[pymethods]`. [#3232](https://github.com/PyO3/pyo3/pull/3232)\n- Remove `IntoPyPointer` trait in favour of `into_ptr` inherent methods. [#3385](https://github.com/PyO3/pyo3/pull/3385)\n\n### Fixed\n\n- Handle exceptions properly in `PySet::discard`. [#3281](https://github.com/PyO3/pyo3/pull/3281)\n- The `PyTupleIterator` type returned by `PyTuple::iter` is now public and hence can be named by downstream crates. [#3366](https://github.com/PyO3/pyo3/pull/3366)\n- Linking of `PyOS_FSPath` on PyPy. [#3374](https://github.com/PyO3/pyo3/pull/3374)\n- Fix memory leak in `PyTypeBuilder::build`. [#3401](https://github.com/PyO3/pyo3/pull/3401)\n- Disable removed FFI definitions `_Py_GetAllocatedBlocks`, `_PyObject_GC_Malloc`, and `_PyObject_GC_Calloc` on Python 3.11 and up. [#3403](https://github.com/PyO3/pyo3/pull/3403)\n- Fix `ResourceWarning` and crashes related to GC when running with debug builds of CPython. [#3404](https://github.com/PyO3/pyo3/pull/3404)\n- Some-wrapping of `Option<T>` default arguments will no longer re-wrap `Some(T)` or expressions evaluating to `None`. [#3461](https://github.com/PyO3/pyo3/pull/3461)\n- Fix `IterNextOutput::Return` not returning a value on PyPy. [#3471](https://github.com/PyO3/pyo3/pull/3471)\n- Emit compile errors instead of ignoring macro invocations inside `#[pymethods]` blocks. [#3491](https://github.com/PyO3/pyo3/pull/3491)\n- Emit error on invalid arguments to `#[new]`, `#[classmethod]`, `#[staticmethod]`, and `#[classattr]`. [#3484](https://github.com/PyO3/pyo3/pull/3484)\n- Disable `PyMarshal_WriteObjectToString` from `PyMarshal_ReadObjectFromString` with the `abi3` feature. [#3490](https://github.com/PyO3/pyo3/pull/3490)\n- Fix FFI definitions for `_PyFrameEvalFunction` on Python 3.11 and up (it now receives a `_PyInterpreterFrame` opaque struct). [#3500](https://github.com/PyO3/pyo3/pull/3500)\n\n\n## [0.19.2] - 2023-08-01\n\n### Added\n\n- Add FFI definitions `PyState_AddModule`, `PyState_RemoveModule` and `PyState_FindModule` for PyPy 3.9 and up. [#3295](https://github.com/PyO3/pyo3/pull/3295)\n- Add FFI definitions `_PyObject_CallFunction_SizeT` and `_PyObject_CallMethod_SizeT`. [#3297](https://github.com/PyO3/pyo3/pull/3297)\n- Add a \"performance\" section to the guide collecting performance-related tricks and problems. [#3304](https://github.com/PyO3/pyo3/pull/3304)\n- Add `PyErr::Display` for all Python versions, and FFI symbol `PyErr_DisplayException` for Python 3.12. [#3334](https://github.com/PyO3/pyo3/pull/3334)\n- Add FFI definition `PyType_GetDict()` for Python 3.12. [#3339](https://github.com/PyO3/pyo3/pull/3339)\n- Add `PyAny::downcast_exact`. [#3346](https://github.com/PyO3/pyo3/pull/3346)\n- Add `PySlice::full()` to construct a full slice (`::`). [#3353](https://github.com/PyO3/pyo3/pull/3353)\n\n### Changed\n\n- Update `PyErr` for 3.12 betas to avoid deprecated ffi methods. [#3306](https://github.com/PyO3/pyo3/pull/3306)\n- Update FFI definitions of `object.h` for Python 3.12.0b4. [#3335](https://github.com/PyO3/pyo3/pull/3335)\n- Update `pyo3::ffi` struct definitions to be compatible with 3.12.0b4. [#3342](https://github.com/PyO3/pyo3/pull/3342)\n- Optimize conversion of `float` to `f64` (and `PyFloat::value`) on non-abi3 builds. [#3345](https://github.com/PyO3/pyo3/pull/3345)\n\n### Fixed\n\n- Fix timezone conversion bug for FixedOffset datetimes that were being incorrectly converted to and from UTC. [#3269](https://github.com/PyO3/pyo3/pull/3269)\n- Fix `SystemError` raised in `PyUnicodeDecodeError_Create` on PyPy 3.10. [#3297](https://github.com/PyO3/pyo3/pull/3297)\n- Correct FFI definition `Py_EnterRecursiveCall` to return `c_int` (was incorrectly returning `()`). [#3300](https://github.com/PyO3/pyo3/pull/3300)\n- Fix case where `PyErr::matches` and `PyErr::is_instance` returned results inconsistent with `PyErr::get_type`. [#3313](https://github.com/PyO3/pyo3/pull/3313)\n- Fix loss of panic message in `PanicException` when unwinding after the exception was \"normalized\". [#3326](https://github.com/PyO3/pyo3/pull/3326)\n- Fix `PyErr::from_value` and `PyErr::into_value` losing traceback on conversion. [#3328](https://github.com/PyO3/pyo3/pull/3328)\n- Fix reference counting of immortal objects on Python 3.12.0b4. [#3335](https://github.com/PyO3/pyo3/pull/3335)\n\n\n## [0.19.1] - 2023-07-03\n\n### Packaging\n\n- Extend range of supported versions of `hashbrown` optional dependency to include version 0.14 [#3258](https://github.com/PyO3/pyo3/pull/3258)\n- Extend range of supported versions of `indexmap` optional dependency to include version 2. [#3277](https://github.com/PyO3/pyo3/pull/3277)\n- Support PyPy 3.10. [#3289](https://github.com/PyO3/pyo3/pull/3289)\n\n### Added\n\n- Add `pyo3::types::PyFrozenSetBuilder` to allow building a `PyFrozenSet` item by item. [#3156](https://github.com/PyO3/pyo3/pull/3156)\n- Add support for converting to and from Python's `ipaddress.IPv4Address`/`ipaddress.IPv6Address` and `std::net::IpAddr`. [#3197](https://github.com/PyO3/pyo3/pull/3197)\n- Add support for `num-bigint` feature in combination with `abi3`. [#3198](https://github.com/PyO3/pyo3/pull/3198)\n- Add `PyErr_GetRaisedException()`, `PyErr_SetRaisedException()` to FFI definitions for Python 3.12 and later. [#3248](https://github.com/PyO3/pyo3/pull/3248)\n- Add `Python::with_pool` which is a safer but more limited alternative to `Python::new_pool`. [#3263](https://github.com/PyO3/pyo3/pull/3263)\n- Add `PyDict::get_item_with_error` on PyPy. [#3270](https://github.com/PyO3/pyo3/pull/3270)\n- Allow `#[new]` methods may to return `Py<Self>` in order to return existing instances. [#3287](https://github.com/PyO3/pyo3/pull/3287)\n\n### Fixed\n\n- Fix conversion of classes implementing `__complex__` to `Complex` when using `abi3` or PyPy. [#3185](https://github.com/PyO3/pyo3/pull/3185)\n- Stop suppressing unrelated exceptions in `PyAny::hasattr`. [#3271](https://github.com/PyO3/pyo3/pull/3271)\n- Fix memory leak when creating `PySet` or `PyFrozenSet` or returning types converted into these internally, e.g. `HashSet` or `BTreeSet`. [#3286](https://github.com/PyO3/pyo3/pull/3286)\n\n\n## [0.19.0] - 2023-05-31\n\n### Packaging\n\n- Correct dependency on syn to version 1.0.85 instead of the incorrect version 1.0.56. [#3152](https://github.com/PyO3/pyo3/pull/3152)\n\n### Added\n\n- Accept `text_signature` option (and automatically generate signature) for `#[new]` in `#[pymethods]`. [#2980](https://github.com/PyO3/pyo3/pull/2980)\n- Add support for converting to and from Python's `decimal.Decimal` and `rust_decimal::Decimal`. [#3016](https://github.com/PyO3/pyo3/pull/3016)\n- Add `#[pyo3(from_item_all)]` when deriving `FromPyObject` to specify `get_item` as getter for all fields. [#3120](https://github.com/PyO3/pyo3/pull/3120)\n- Add `pyo3::exceptions::PyBaseExceptionGroup` for Python 3.11, and corresponding FFI definition `PyExc_BaseExceptionGroup`. [#3141](https://github.com/PyO3/pyo3/pull/3141)\n- Accept `#[new]` with `#[classmethod]` to create a constructor which receives a (subtype's) class/`PyType` as its first argument. [#3157](https://github.com/PyO3/pyo3/pull/3157)\n- Add `PyClass::get` and `Py::get` for GIL-independent access to classes with `#[pyclass(frozen)]`. [#3158](https://github.com/PyO3/pyo3/pull/3158)\n- Add `PyAny::is_exact_instance` and `PyAny::is_exact_instance_of`. [#3161](https://github.com/PyO3/pyo3/pull/3161)\n\n### Changed\n\n- `PyAny::is_instance_of::<T>(obj)` is now equivalent to `T::is_type_of(obj)`, and now returns `bool` instead of `PyResult<bool>`. [#2881](https://github.com/PyO3/pyo3/pull/2881)\n- Deprecate `text_signature` option on `#[pyclass]` structs. [#2980](https://github.com/PyO3/pyo3/pull/2980)\n- No longer wrap `anyhow::Error`/`eyre::Report` containing a basic `PyErr` without a chain in a `PyRuntimeError`. [#3004](https://github.com/PyO3/pyo3/pull/3004)\n- - Change `#[getter]` and `#[setter]` to use a common call \"trampoline\" to slightly reduce generated code size and compile times. [#3029](https://github.com/PyO3/pyo3/pull/3029)\n- Improve default values for str, numbers and bool in automatically-generated `text_signature`. [#3050](https://github.com/PyO3/pyo3/pull/3050)\n- Improve default value for `None` in automatically-generated `text_signature`. [#3066](https://github.com/PyO3/pyo3/pull/3066)\n- Rename `PySequence::list` and `PySequence::tuple` to `PySequence::to_list` and `PySequence::to_tuple`. (The old names continue to exist as deprecated forms.) [#3111](https://github.com/PyO3/pyo3/pull/3111)\n- Extend the lifetime of the GIL token returned by `PyRef::py` and `PyRefMut::py` to match the underlying borrow. [#3131](https://github.com/PyO3/pyo3/pull/3131)\n- Safe access to the GIL, for example via `Python::with_gil`, is now locked inside of implementations of the `__traverse__` slot. [#3168](https://github.com/PyO3/pyo3/pull/3168)\n\n### Removed\n\n- Remove all functionality deprecated in PyO3 0.17, most prominently `Python::acquire_gil` is replaced by `Python::with_gil`. [#2981](https://github.com/PyO3/pyo3/pull/2981)\n\n### Fixed\n\n- Correct FFI definitions `PyGetSetDef`, `PyMemberDef`, `PyStructSequence_Field` and `PyStructSequence_Desc` to have `*const c_char` members for `name` and `doc` (not `*mut c_char`). [#3036](https://github.com/PyO3/pyo3/pull/3036)\n- Fix panic on `fmt::Display`, instead return `\"<unprintable object>\"` string and report error via `sys.unraisablehook()` [#3062](https://github.com/PyO3/pyo3/pull/3062)\n- Fix a compile error of \"temporary value dropped while borrowed\" when `#[pyfunction]`s take references into `#[pyclass]`es [#3142](https://github.com/PyO3/pyo3/pull/3142)\n- Fix crashes caused by PyO3 applying deferred reference count updates when entering a `__traverse__` implementation. [#3168](https://github.com/PyO3/pyo3/pull/3168)\n- Forbid running the `Drop` implementations of unsendable classes on other threads. [#3176](https://github.com/PyO3/pyo3/pull/3176)\n- Fix a compile error when `#[pymethods]` items come from somewhere else (for example, as a macro argument) and a custom receiver like `Py<Self>` is used. [#3178](https://github.com/PyO3/pyo3/pull/3178)\n\n\n## [0.18.3] - 2023-04-13\n\n### Added\n\n- Add `GILProtected<T>` to mediate concurrent access to a value using Python's global interpreter lock (GIL). [#2975](https://github.com/PyO3/pyo3/pull/2975)\n- Support `PyASCIIObject` / `PyUnicode` and associated methods on big-endian architectures. [#3015](https://github.com/PyO3/pyo3/pull/3015)\n- Add FFI definition `_PyDict_Contains_KnownHash()` for CPython 3.10 and up. [#3088](https://github.com/PyO3/pyo3/pull/3088)\n\n### Fixed\n\n- Fix compile error for `#[pymethods]` and `#[pyfunction]` called \"output\". [#3022](https://github.com/PyO3/pyo3/pull/3022)\n- Fix compile error in generated code for magic methods implemented as a `#[staticmethod]`. [#3055](https://github.com/PyO3/pyo3/pull/3055)\n- Fix `is_instance` for `PyDateTime` (would incorrectly check for a `PyDate`). [#3071](https://github.com/PyO3/pyo3/pull/3071)\n- Fix upstream deprecation of `PyUnicode_InternImmortal` since Python 3.10. [#3071](https://github.com/PyO3/pyo3/pull/3087)\n\n\n## [0.18.2] - 2023-03-24\n\n### Packaging\n\n- Disable default features of `chrono` to avoid depending on `time` v0.1.x. [#2939](https://github.com/PyO3/pyo3/pull/2939)\n\n### Added\n\n- Implement `IntoPy<PyObject>`, `ToPyObject` and `FromPyObject` for `Cow<[u8]>` to efficiently handle both `bytes` and `bytearray` objects. [#2899](https://github.com/PyO3/pyo3/pull/2899)\n- Implement `IntoPy<PyObject>`, `ToPyObject` and `FromPyObject` for `Cell<T>`. [#3014](https://github.com/PyO3/pyo3/pull/3014)\n- Add `PyList::to_tuple()`, as a convenient and efficient conversion from lists to tuples. [#3042](https://github.com/PyO3/pyo3/pull/3042)\n- Add `PyTuple::to_list()`, as a convenient and efficient conversion from tuples to lists. [#3044](https://github.com/PyO3/pyo3/pull/3044)\n\n### Changed\n\n- Optimize `PySequence` conversion for `list` and `tuple` inputs. [#2944](https://github.com/PyO3/pyo3/pull/2944)\n- Improve exception raised when creating `#[pyclass]` type object fails during module import. [#2947](https://github.com/PyO3/pyo3/pull/2947)\n- Optimize `PyMapping` conversion for `dict` inputs. [#2954](https://github.com/PyO3/pyo3/pull/2954)\n- Allow `create_exception!` to take a `dotted.module` to place the exception in a submodule. [#2979](https://github.com/PyO3/pyo3/pull/2979)\n\n### Fixed\n\n- Fix a reference counting race condition affecting `PyObject`s cloned in `allow_threads` blocks. [#2952](https://github.com/PyO3/pyo3/pull/2952)\n- Fix `clippy::redundant_closure` lint on default arguments in `#[pyo3(signature = (...))]` annotations. [#2990](https://github.com/PyO3/pyo3/pull/2990)\n- Fix `non_snake_case` lint on generated code in `#[pyfunction]` macro. [#2993](https://github.com/PyO3/pyo3/pull/2993)\n- Fix some FFI definitions for the upcoming PyPy 3.10 release. [#3031](https://github.com/PyO3/pyo3/pull/3031)\n\n\n## [0.18.1] - 2023-02-07\n\n### Added\n\n- Add `PyErr::write_unraisable()`. [#2889](https://github.com/PyO3/pyo3/pull/2889)\n- Add `Python::Ellipsis()` and `PyAny::is_ellipsis()` methods. [#2911](https://github.com/PyO3/pyo3/pull/2911)\n- Add `PyDict::update()` and `PyDict::update_if_missing()` methods. [#2912](https://github.com/PyO3/pyo3/pull/2912)\n\n### Changed\n\n- FFI definition `PyIter_Check` on CPython 3.7 is now implemented as `hasattr(type(obj), \"__next__\")`, which works correctly on all platforms and adds support for `abi3`. [#2914](https://github.com/PyO3/pyo3/pull/2914)\n- Warn about unknown config keys in `PYO3_CONFIG_FILE` instead of denying. [#2926](https://github.com/PyO3/pyo3/pull/2926)\n\n### Fixed\n\n- Send errors returned by `__releasebuffer__` to `sys.unraisablehook` rather than causing `SystemError`. [#2886](https://github.com/PyO3/pyo3/pull/2886)\n- Fix downcast to `PyIterator` succeeding for Python classes which did not implement `__next__`. [#2914](https://github.com/PyO3/pyo3/pull/2914)\n- Fix segfault in `__traverse__` when visiting `None` fields of `Option<T: AsPyPointer>`. [#2921](https://github.com/PyO3/pyo3/pull/2921)\n- Fix `#[pymethods(crate = \"...\")]` option being ignored. [#2923](https://github.com/PyO3/pyo3/pull/2923)\n- Link against `pythonXY_d.dll` for debug Python builds on Windows. [#2937](https://github.com/PyO3/pyo3/pull/2937)\n\n\n## [0.18.0] - 2023-01-17\n\n### Packaging\n\n- Relax `indexmap` optional depecency to allow `>= 1.6, < 2`. [#2849](https://github.com/PyO3/pyo3/pull/2849)\n- Relax `hashbrown` optional dependency to allow `>= 0.9, < 0.14`. [#2875](https://github.com/PyO3/pyo3/pull/2875)\n- Update `memoffset` dependency to 0.8. [#2875](https://github.com/PyO3/pyo3/pull/2875)\n\n### Added\n\n- Add `GILOnceCell::get_or_try_init` for fallible `GILOnceCell` initialization. [#2398](https://github.com/PyO3/pyo3/pull/2398)\n- Add experimental feature `experimental-inspect` with `type_input()` and `type_output()` helpers to get the Python type of any Python-compatible object. [#2490](https://github.com/PyO3/pyo3/pull/2490) [#2882](https://github.com/PyO3/pyo3/pull/2882)\n- The `#[pyclass]` macro can now take `get_all` and `set_all` to create getters and setters for every field. [#2692](https://github.com/PyO3/pyo3/pull/2692)\n- Add `#[pyo3(signature = (...))]` option for `#[pyfunction]` and `#[pymethods]`. [#2702](https://github.com/PyO3/pyo3/pull/2702)\n- `pyo3-build-config`: rebuild when `PYO3_ENVIRONMENT_SIGNATURE` environment variable value changes. [#2727](https://github.com/PyO3/pyo3/pull/2727)\n- Add conversions between non-zero int types in `std::num` and Python `int`. [#2730](https://github.com/PyO3/pyo3/pull/2730)\n- Add `Py::downcast()` as a companion to `PyAny::downcast()`, as well as `downcast_unchecked()` for both types. [#2734](https://github.com/PyO3/pyo3/pull/2734)\n- Add types for all built-in `Warning` classes as well as `PyErr::warn_explicit`. [#2742](https://github.com/PyO3/pyo3/pull/2742)\n- Add `abi3-py311` feature. [#2776](https://github.com/PyO3/pyo3/pull/2776)\n- Add FFI definition `_PyErr_ChainExceptions()` for CPython. [#2788](https://github.com/PyO3/pyo3/pull/2788)\n- Add FFI definitions `PyVectorcall_NARGS` and `PY_VECTORCALL_ARGUMENTS_OFFSET` for PyPy 3.8 and up. [#2811](https://github.com/PyO3/pyo3/pull/2811)\n- Add `PyList::get_item_unchecked` for PyPy. [#2827](https://github.com/PyO3/pyo3/pull/2827)\n\n### Changed\n\n- PyO3's macros now emit a much nicer error message if function return values don't implement the required trait(s). [#2664](https://github.com/PyO3/pyo3/pull/2664)\n- Use a TypeError, rather than a ValueError, when refusing to treat a str as a Vec. [#2685](https://github.com/PyO3/pyo3/pull/2685)\n- Change `PyCFunction::new_closure` to take `name` and `doc` arguments. [#2686](https://github.com/PyO3/pyo3/pull/2686)\n- `PyType::is_subclass`, `PyErr::is_instance` and `PyAny::is_instance` now take `&PyAny` instead of `&PyType` arguments, so that they work with objects that pretend to be types using `__subclasscheck__` and `__instancecheck__`. [#2695](https://github.com/PyO3/pyo3/pull/2695)\n- Deprecate `#[args]` attribute and passing \"args\" specification directly to `#[pyfunction]` in favor of the new `#[pyo3(signature = (...))]` option. [#2702](https://github.com/PyO3/pyo3/pull/2702)\n- Deprecate required arguments after `Option<T>` arguments to `#[pyfunction]` and `#[pymethods]` without also using `#[pyo3(signature)]` to specify whether the arguments should be required or have defaults. [#2703](https://github.com/PyO3/pyo3/pull/2703)\n- Change `#[pyfunction]` and `#[pymethods]` to use a common call \"trampoline\" to slightly reduce generated code size and compile times. [#2705](https://github.com/PyO3/pyo3/pull/2705)\n- `PyAny::cast_as()` and `Py::cast_as()` are now deprecated in favor of `PyAny::downcast()` and the new `Py::downcast()`. [#2734](https://github.com/PyO3/pyo3/pull/2734)\n- Relax lifetime bounds on `PyAny::downcast()`. [#2734](https://github.com/PyO3/pyo3/pull/2734)\n- Automatically generate `__text_signature__` for all Python functions created using `#[pyfunction]` and `#[pymethods]`. [#2784](https://github.com/PyO3/pyo3/pull/2784)\n- Accept any iterator in `PySet::new` and `PyFrozenSet::new`. [#2795](https://github.com/PyO3/pyo3/pull/2795)\n- Mixing `#[cfg(...)]` and `#[pyo3(...)]` attributes on `#[pyclass]` struct fields will now work. [#2796](https://github.com/PyO3/pyo3/pull/2796)\n- Re-enable `PyFunction` on when building for abi3 or PyPy. [#2838](https://github.com/PyO3/pyo3/pull/2838)\n- Improve `derive(FromPyObject)` to use `intern!` when applicable for `#[pyo3(item)]`. [#2879](https://github.com/PyO3/pyo3/pull/2879)\n\n### Removed\n\n- Remove the deprecated `pyproto` feature, `#[pyproto]` macro, and all accompanying APIs. [#2587](https://github.com/PyO3/pyo3/pull/2587)\n- Remove all functionality deprecated in PyO3 0.16. [#2843](https://github.com/PyO3/pyo3/pull/2843)\n\n### Fixed\n\n- Disable `PyModule::filename` on PyPy. [#2715](https://github.com/PyO3/pyo3/pull/2715)\n- `PyCodeObject` is now once again defined with fields on Python 3.7. [#2726](https://github.com/PyO3/pyo3/pull/2726)\n- Raise a `TypeError` if `#[new]` pymethods with no arguments receive arguments when called from Python. [#2749](https://github.com/PyO3/pyo3/pull/2749)\n- Use the `NOARGS` argument calling convention for methods that have a single `py: Python` argument (as a performance optimization). [#2760](https://github.com/PyO3/pyo3/pull/2760)\n- Fix truncation of `isize` values to `c_long` in `PySlice::new`. [#2769](https://github.com/PyO3/pyo3/pull/2769)\n- Fix soundness issue with FFI definition `PyUnicodeDecodeError_Create` on PyPy leading to indeterminate behavior (typically a `TypeError`). [#2772](https://github.com/PyO3/pyo3/pull/2772)\n- Allow functions taking `**kwargs` to accept keyword arguments which share a name with a positional-only argument (as permitted by PEP 570). [#2800](https://github.com/PyO3/pyo3/pull/2800)\n- Fix unresolved symbol for `PyObject_Vectorcall` on PyPy 3.9 and up. [#2811](https://github.com/PyO3/pyo3/pull/2811)\n- Fix memory leak in `PyCFunction::new_closure`. [#2842](https://github.com/PyO3/pyo3/pull/2842)\n\n\n## [0.17.3] - 2022-11-01\n\n### Packaging\n\n- Support Python 3.11. (Previous versions of PyO3 0.17 have been tested against Python 3.11 release candidates and are expected to be compatible, this is the first version tested against Python 3.11.0.) [#2708](https://github.com/PyO3/pyo3/pull/2708)\n\n### Added\n\n- Implemented `ExactSizeIterator` for `PyListIterator`, `PyDictIterator`, `PySetIterator` and `PyFrozenSetIterator`. [#2676](https://github.com/PyO3/pyo3/pull/2676)\n\n### Fixed\n\n- Fix regression of `impl FromPyObject for [T; N]` no longer accepting types passing `PySequence_Check`, e.g. NumPy arrays, since version 0.17.0. This the same fix that was applied `impl FromPyObject for Vec<T>` in version 0.17.1 extended to fixed-size arrays. [#2675](https://github.com/PyO3/pyo3/pull/2675)\n- Fix UB in `FunctionDescription::extract_arguments_fastcall` due to creating slices from a null pointer. [#2687](https://github.com/PyO3/pyo3/pull/2687)\n\n\n## [0.17.2] - 2022-10-04\n\n### Packaging\n\n- Added optional `chrono` feature to convert `chrono` types into types in the `datetime` module. [#2612](https://github.com/PyO3/pyo3/pull/2612)\n\n### Added\n\n- Add support for `num-bigint` feature on `PyPy`. [#2626](https://github.com/PyO3/pyo3/pull/2626)\n\n### Fixed\n\n- Correctly implement `__richcmp__` for enums, fixing `__ne__` returning always returning `True`. [#2622](https://github.com/PyO3/pyo3/pull/2622)\n- Fix compile error since 0.17.0 with `Option<&SomePyClass>` argument with a default. [#2630](https://github.com/PyO3/pyo3/pull/2630)\n- Fix regression of `impl FromPyObject for Vec<T>` no longer accepting types passing `PySequence_Check`, e.g. NumPy arrays, since 0.17.0. [#2631](https://github.com/PyO3/pyo3/pull/2631)\n\n## [0.17.1] - 2022-08-28\n\n### Fixed\n\n- Fix visibility of `PyDictItems`, `PyDictKeys`, and `PyDictValues` types added in PyO3 0.17.0.\n- Fix compile failure when using `#[pyo3(from_py_with = \"...\")]` attribute on an argument of type `Option<T>`. [#2592](https://github.com/PyO3/pyo3/pull/2592)\n- Fix clippy `redundant-closure` lint on `**kwargs` arguments for `#[pyfunction]` and `#[pymethods]`. [#2595](https://github.com/PyO3/pyo3/pull/2595)\n\n## [0.17.0] - 2022-08-23\n\n### Packaging\n\n- Update inventory dependency to `0.3` (the `multiple-pymethods` feature now requires Rust 1.62 for correctness). [#2492](https://github.com/PyO3/pyo3/pull/2492)\n\n### Added\n\n- Add `timezone_utc`. [#1588](https://github.com/PyO3/pyo3/pull/1588)\n- Implement `ToPyObject` for `[T; N]`. [#2313](https://github.com/PyO3/pyo3/pull/2313)\n- Add `PyDictKeys`, `PyDictValues` and `PyDictItems` Rust types. [#2358](https://github.com/PyO3/pyo3/pull/2358)\n- Add `append_to_inittab`. [#2377](https://github.com/PyO3/pyo3/pull/2377)\n- Add FFI definition `PyFrame_GetCode`. [#2406](https://github.com/PyO3/pyo3/pull/2406)\n- Add `PyCode` and `PyFrame` high level objects. [#2408](https://github.com/PyO3/pyo3/pull/2408)\n- Add FFI definitions `Py_fstring_input`, `sendfunc`, and `_PyErr_StackItem`. [#2423](https://github.com/PyO3/pyo3/pull/2423)\n- Add `PyDateTime::new_with_fold`, `PyTime::new_with_fold`, `PyTime::get_fold`, and `PyDateTime::get_fold` for PyPy. [#2428](https://github.com/PyO3/pyo3/pull/2428)\n- Add `#[pyclass(frozen)]`. [#2448](https://github.com/PyO3/pyo3/pull/2448)\n- Accept `#[pyo3(name)]` on enum variants. [#2457](https://github.com/PyO3/pyo3/pull/2457)\n- Add `CompareOp::matches` to implement `__richcmp__` as the result of a Rust `std::cmp::Ordering` comparison. [#2460](https://github.com/PyO3/pyo3/pull/2460)\n- Add `PySuper` type. [#2486](https://github.com/PyO3/pyo3/pull/2486)\n- Support PyPy on Windows with the `generate-import-lib` feature. [#2506](https://github.com/PyO3/pyo3/pull/2506)\n- Add FFI definitions `Py_EnterRecursiveCall` and `Py_LeaveRecursiveCall`. [#2511](https://github.com/PyO3/pyo3/pull/2511)\n- Add `PyDict::get_item_with_error`. [#2536](https://github.com/PyO3/pyo3/pull/2536)\n- Add `#[pyclass(sequence)]` option. [#2567](https://github.com/PyO3/pyo3/pull/2567)\n\n### Changed\n\n- Change datetime constructors taking a `tzinfo` to take `Option<&PyTzInfo>` instead of `Option<&PyObject>`: `PyDateTime::new`, `PyDateTime::new_with_fold`, `PyTime::new`, and `PyTime::new_with_fold`. [#1588](https://github.com/PyO3/pyo3/pull/1588)\n- Move `PyTypeObject::type_object` method to the `PyTypeInfo` trait, and deprecate the `PyTypeObject` trait. [#2287](https://github.com/PyO3/pyo3/pull/2287)\n- Methods of `Py` and `PyAny` now accept `impl IntoPy<Py<PyString>>` rather than just `&str` to allow use of the `intern!` macro. [#2312](https://github.com/PyO3/pyo3/pull/2312)\n- Change the deprecated `pyproto` feature to be opt-in instead of opt-out. [#2322](https://github.com/PyO3/pyo3/pull/2322)\n- Emit better error messages when `#[pyfunction]` return types do not implement `IntoPy`. [#2326](https://github.com/PyO3/pyo3/pull/2326)\n- Require `T: IntoPy` for `impl<T, const N: usize> IntoPy<PyObject> for [T; N]` instead of `T: ToPyObject`. [#2326](https://github.com/PyO3/pyo3/pull/2326)\n- Deprecate the `ToBorrowedObject` trait. [#2333](https://github.com/PyO3/pyo3/pull/2333)\n- Iterators over `PySet` and `PyDict` will now panic if the underlying collection is mutated during the iteration. [#2380](https://github.com/PyO3/pyo3/pull/2380)\n- Iterators over `PySet` and `PyDict` will now panic if the underlying collection is mutated during the iteration. [#2380](https://github.com/PyO3/pyo3/pull/2380)\n- Allow `#[classattr]` methods to be fallible. [#2385](https://github.com/PyO3/pyo3/pull/2385)\n- Prevent multiple `#[pymethods]` with the same name for a single `#[pyclass]`. [#2399](https://github.com/PyO3/pyo3/pull/2399)\n- Fixup `lib_name` when using `PYO3_CONFIG_FILE`. [#2404](https://github.com/PyO3/pyo3/pull/2404)\n- Add a message to the `ValueError` raised by the `#[derive(FromPyObject)]` implementation for a tuple struct. [#2414](https://github.com/PyO3/pyo3/pull/2414)\n- Allow `#[classattr]` methods to take `Python` argument. [#2456](https://github.com/PyO3/pyo3/pull/2456)\n- Rework `PyCapsule` type to resolve soundness issues: [#2485](https://github.com/PyO3/pyo3/pull/2485)\n  - `PyCapsule::new` and `PyCapsule::new_with_destructor` now take `name: Option<CString>` instead of `&CStr`.\n  - The destructor `F` in `PyCapsule::new_with_destructor` must now be `Send`.\n  - `PyCapsule::get_context` deprecated in favor of `PyCapsule::context` which doesn't take a `py: Python<'_>` argument.\n  - `PyCapsule::set_context` no longer takes a `py: Python<'_>` argument.\n  - `PyCapsule::name` now returns `PyResult<Option<&CStr>>` instead of `&CStr`.\n- `FromPyObject::extract` for `Vec<T>` no longer accepts Python `str` inputs. [#2500](https://github.com/PyO3/pyo3/pull/2500)\n- Ensure each `#[pymodule]` is only initialized once. [#2523](https://github.com/PyO3/pyo3/pull/2523)\n- `pyo3_build_config::add_extension_module_link_args` now also emits linker arguments for `wasm32-unknown-emscripten`. [#2538](https://github.com/PyO3/pyo3/pull/2538)\n- Type checks for `PySequence` and `PyMapping` now require inputs to inherit from (or register with) `collections.abc.Sequence` and `collections.abc.Mapping` respectively. [#2477](https://github.com/PyO3/pyo3/pull/2477)\n- Disable `PyFunction` on when building for abi3 or PyPy. [#2542](https://github.com/PyO3/pyo3/pull/2542)\n- Deprecate `Python::acquire_gil`. [#2549](https://github.com/PyO3/pyo3/pull/2549)\n\n### Removed\n\n- Remove all functionality deprecated in PyO3 0.15. [#2283](https://github.com/PyO3/pyo3/pull/2283)\n- Make the `Dict`, `WeakRef` and `BaseNativeType` members of the `PyClass` private implementation details. [#2572](https://github.com/PyO3/pyo3/pull/2572)\n\n### Fixed\n\n- Enable incorrectly disabled FFI definition `PyThreadState_DeleteCurrent`. [#2357](https://github.com/PyO3/pyo3/pull/2357)\n- Fix `wrap_pymodule` interactions with name resolution rules: it no longer \"sees through\" glob imports of `use submodule::*` when `submodule::submodule` is a `#[pymodule]`. [#2363](https://github.com/PyO3/pyo3/pull/2363)\n- Correct FFI definition `PyEval_EvalCodeEx` to take `*const *mut PyObject` array arguments instead of `*mut *mut PyObject`. [#2368](https://github.com/PyO3/pyo3/pull/2368)\n- Fix \"raw-ident\" structs (e.g. `#[pyclass] struct r#RawName`) incorrectly having `r#` at the start of the class name created in Python. [#2395](https://github.com/PyO3/pyo3/pull/2395)\n- Correct FFI definition `Py_tracefunc` to be `unsafe extern \"C\" fn` (was previously safe). [#2407](https://github.com/PyO3/pyo3/pull/2407)\n- Fix compile failure with `#[pyo3(from_py_with = \"...\")]` annotations on a field in a `#[derive(FromPyObject)]` struct. [#2414](https://github.com/PyO3/pyo3/pull/2414)\n- Fix FFI definitions `_PyDateTime_BaseTime` and `_PyDateTime_BaseDateTime` lacking leading underscores in their names. [#2421](https://github.com/PyO3/pyo3/pull/2421)\n- Remove FFI definition `PyArena` on Python 3.10 and up. [#2421](https://github.com/PyO3/pyo3/pull/2421)\n- Fix FFI definition `PyCompilerFlags` missing member `cf_feature_version` on Python 3.8 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423)\n- Fix FFI definition `PyAsyncMethods` missing member `am_send` on Python 3.10 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423)\n- Fix FFI definition `PyGenObject` having multiple incorrect members on various Python versions. [#2423](https://github.com/PyO3/pyo3/pull/2423)\n- Fix FFI definition `PySyntaxErrorObject` missing members `end_lineno` and `end_offset` on Python 3.10 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423)\n- Fix FFI definition `PyHeapTypeObject` missing member `ht_module` on Python 3.9 and up. [#2423](https://github.com/PyO3/pyo3/pull/2423)\n- Fix FFI definition `PyFrameObject` having multiple incorrect members on various Python versions. [#2424](https://github.com/PyO3/pyo3/pull/2424) [#2434](https://github.com/PyO3/pyo3/pull/2434)\n- Fix FFI definition `PyTypeObject` missing deprecated field `tp_print` on Python 3.8. [#2428](https://github.com/PyO3/pyo3/pull/2428)\n- Fix FFI definitions `PyDateTime_CAPI`. `PyDateTime_Date`, `PyASCIIObject`, `PyBaseExceptionObject`, `PyListObject`, and `PyTypeObject` on PyPy. [#2428](https://github.com/PyO3/pyo3/pull/2428)\n- Fix FFI definition `_inittab` field `initfunc` typo'd as `initfun`. [#2431](https://github.com/PyO3/pyo3/pull/2431)\n- Fix FFI definitions `_PyDateTime_BaseTime` and `_PyDateTime_BaseDateTime` incorrectly having `fold` member. [#2432](https://github.com/PyO3/pyo3/pull/2432)\n- Fix FFI definitions `PyTypeObject`. `PyHeapTypeObject`, and `PyCFunctionObject` having incorrect members on PyPy 3.9. [#2433](https://github.com/PyO3/pyo3/pull/2433)\n- Fix FFI definition `PyGetSetDef` to have `*const c_char` for `doc` member (not `*mut c_char`). [#2439](https://github.com/PyO3/pyo3/pull/2439)\n- Fix `#[pyo3(from_py_with = \"...\")]` being ignored for 1-element tuple structs and transparent structs. [#2440](https://github.com/PyO3/pyo3/pull/2440)\n- Use `memoffset` to avoid UB when computing `PyCell` layout. [#2450](https://github.com/PyO3/pyo3/pull/2450)\n- Fix incorrect enum names being returned by the generated `repr` for enums renamed by `#[pyclass(name = \"...\")]` [#2457](https://github.com/PyO3/pyo3/pull/2457)\n- Fix `PyObject_CallNoArgs` incorrectly being available when building for abi3 on Python 3.9. [#2476](https://github.com/PyO3/pyo3/pull/2476)\n- Fix several clippy warnings generated by `#[pyfunction]` arguments. [#2503](https://github.com/PyO3/pyo3/pull/2503)\n\n## [0.16.6] - 2022-08-23\n\n### Changed\n\n- Fix soundness issues with `PyCapsule` type with select workarounds. Users are encourage to upgrade to PyO3 0.17 at their earliest convenience which contains API breakages which fix the issues in a long-term fashion. [#2522](https://github.com/PyO3/pyo3/pull/2522)\n  - `PyCapsule::new` and `PyCapsule::new_with_destructor` now take ownership of a copy of the `name` to resolve a possible use-after-free.\n  - `PyCapsule::name` now returns an empty `CStr` instead of dereferencing a null pointer if the capsule has no name.\n  - The destructor `F` in `PyCapsule::new_with_destructor` will never be called if the capsule is deleted from a thread other than the one which the capsule was created in (a warning will be emitted).\n- Panics during drop of panic payload caught by PyO3 will now abort. [#2544](https://github.com/PyO3/pyo3/pull/2544)\n\n## [0.16.5] - 2022-05-15\n\n### Added\n\n- Add an experimental `generate-import-lib` feature to support auto-generating non-abi3 python import libraries for Windows targets. [#2364](https://github.com/PyO3/pyo3/pull/2364)\n- Add FFI definition `Py_ExitStatusException`. [#2374](https://github.com/PyO3/pyo3/pull/2374)\n\n### Changed\n\n- Deprecate experimental `generate-abi3-import-lib` feature in favor of the new `generate-import-lib` feature. [#2364](https://github.com/PyO3/pyo3/pull/2364)\n\n### Fixed\n\n- Added missing `warn_default_encoding` field to `PyConfig` on 3.10+. The previously missing field could result in incorrect behavior or crashes. [#2370](https://github.com/PyO3/pyo3/pull/2370)\n- Fixed order of `pathconfig_warnings` and `program_name` fields of `PyConfig` on 3.10+. Previously, the order of the fields was swapped and this could lead to incorrect behavior or crashes. [#2370](https://github.com/PyO3/pyo3/pull/2370)\n\n## [0.16.4] - 2022-04-14\n\n### Added\n\n- Add `PyTzInfoAccess` trait for safe access to time zone information. [#2263](https://github.com/PyO3/pyo3/pull/2263)\n- Add an experimental `generate-abi3-import-lib` feature to auto-generate `python3.dll` import libraries for Windows. [#2282](https://github.com/PyO3/pyo3/pull/2282)\n- Add FFI definitions for `PyDateTime_BaseTime` and `PyDateTime_BaseDateTime`. [#2294](https://github.com/PyO3/pyo3/pull/2294)\n\n### Changed\n\n- Improved performance of failing calls to `FromPyObject::extract` which is common when functions accept multiple distinct types. [#2279](https://github.com/PyO3/pyo3/pull/2279)\n- Default to \"m\" ABI tag when choosing `libpython` link name for CPython 3.7 on Unix. [#2288](https://github.com/PyO3/pyo3/pull/2288)\n- Allow to compile \"abi3\" extensions without a working build host Python interpreter. [#2293](https://github.com/PyO3/pyo3/pull/2293)\n\n### Fixed\n\n- Crates depending on PyO3 can collect code coverage via LLVM instrumentation using stable Rust. [#2286](https://github.com/PyO3/pyo3/pull/2286)\n- Fix segfault when calling FFI methods `PyDateTime_DATE_GET_TZINFO` or `PyDateTime_TIME_GET_TZINFO` on `datetime` or `time` without a tzinfo. [#2289](https://github.com/PyO3/pyo3/pull/2289)\n- Fix directory names starting with the letter `n` breaking serialization of the interpreter configuration on Windows since PyO3 0.16.3. [#2299](https://github.com/PyO3/pyo3/pull/2299)\n\n## [0.16.3] - 2022-04-05\n\n### Packaging\n\n- Extend `parking_lot` dependency supported versions to include 0.12. [#2239](https://github.com/PyO3/pyo3/pull/2239)\n\n### Added\n\n- Add methods to `pyo3_build_config::InterpreterConfig` to run Python scripts using the configured executable. [#2092](https://github.com/PyO3/pyo3/pull/2092)\n- Add `as_bytes` method to `Py<PyBytes>`. [#2235](https://github.com/PyO3/pyo3/pull/2235)\n- Add FFI definitions for `PyType_FromModuleAndSpec`, `PyType_GetModule`, `PyType_GetModuleState` and `PyModule_AddType`. [#2250](https://github.com/PyO3/pyo3/pull/2250)\n- Add `pyo3_build_config::cross_compiling_from_to` as a helper to detect when PyO3 is cross-compiling. [#2253](https://github.com/PyO3/pyo3/pull/2253)\n- Add `#[pyclass(mapping)]` option to leave sequence slots empty in container implementations. [#2265](https://github.com/PyO3/pyo3/pull/2265)\n- Add `PyString::intern` to enable usage of the Python's built-in string interning. [#2268](https://github.com/PyO3/pyo3/pull/2268)\n- Add `intern!` macro which can be used to amortize the cost of creating Python strings by storing them inside a `GILOnceCell`. [#2269](https://github.com/PyO3/pyo3/pull/2269)\n- Add `PYO3_CROSS_PYTHON_IMPLEMENTATION` environment variable for selecting the default cross Python implementation. [#2272](https://github.com/PyO3/pyo3/pull/2272)\n\n### Changed\n\n- Allow `#[pyo3(crate = \"...\", text_signature = \"...\")]` options to be used directly in `#[pyclass(crate = \"...\", text_signature = \"...\")]`. [#2234](https://github.com/PyO3/pyo3/pull/2234)\n- Make `PYO3_CROSS_LIB_DIR` environment variable optional when cross compiling. [#2241](https://github.com/PyO3/pyo3/pull/2241)\n- Mark `METH_FASTCALL` calling convention as limited API on Python 3.10. [#2250](https://github.com/PyO3/pyo3/pull/2250)\n- Deprecate `pyo3_build_config::cross_compiling` in favor of `pyo3_build_config::cross_compiling_from_to`. [#2253](https://github.com/PyO3/pyo3/pull/2253)\n\n### Fixed\n\n- Fix `abi3-py310` feature: use Python 3.10 ABI when available instead of silently falling back to the 3.9 ABI. [#2242](https://github.com/PyO3/pyo3/pull/2242)\n- Use shared linking mode when cross compiling against a [Framework bundle](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html) for macOS. [#2233](https://github.com/PyO3/pyo3/pull/2233)\n- Fix panic during compilation when `PYO3_CROSS_LIB_DIR` is set for some host/target combinations. [#2232](https://github.com/PyO3/pyo3/pull/2232)\n- Correct dependency version for `syn` to require minimal patch version 1.0.56. [#2240](https://github.com/PyO3/pyo3/pull/2240)\n\n## [0.16.2] - 2022-03-15\n\n### Packaging\n\n- Warn when modules are imported on PyPy 3.7 versions older than PyPy 7.3.8, as they are known to have binary compatibility issues. [#2217](https://github.com/PyO3/pyo3/pull/2217)\n- Ensure build script of `pyo3-ffi` runs before that of `pyo3` to fix cross compilation. [#2224](https://github.com/PyO3/pyo3/pull/2224)\n\n## [0.16.1] - 2022-03-05\n\n### Packaging\n\n- Extend `hashbrown` optional dependency supported versions to include 0.12. [#2197](https://github.com/PyO3/pyo3/pull/2197)\n\n### Fixed\n\n- Fix incorrect platform detection for Windows in `pyo3-build-config`. [#2198](https://github.com/PyO3/pyo3/pull/2198)\n- Fix regression from 0.16 preventing cross compiling to aarch64 macOS. [#2201](https://github.com/PyO3/pyo3/pull/2201)\n\n## [0.16.0] - 2022-02-27\n\n### Packaging\n\n- Update MSRV to Rust 1.48. [#2004](https://github.com/PyO3/pyo3/pull/2004)\n- Update `indoc` optional dependency to 1.0. [#2004](https://github.com/PyO3/pyo3/pull/2004)\n- Drop support for Python 3.6, remove `abi3-py36` feature. [#2006](https://github.com/PyO3/pyo3/pull/2006)\n- `pyo3-build-config` no longer enables the `resolve-config` feature by default. [#2008](https://github.com/PyO3/pyo3/pull/2008)\n- Update `inventory` optional dependency to 0.2. [#2019](https://github.com/PyO3/pyo3/pull/2019)\n- Drop `paste` dependency. [#2081](https://github.com/PyO3/pyo3/pull/2081)\n- The bindings found in `pyo3::ffi` are now a re-export of a separate `pyo3-ffi` crate. [#2126](https://github.com/PyO3/pyo3/pull/2126)\n- Support PyPy 3.9. [#2143](https://github.com/PyO3/pyo3/pull/2143)\n\n### Added\n\n- Add `PyCapsule` type exposing the [Capsule API](https://docs.python.org/3/c-api/capsule.html#capsules). [#1980](https://github.com/PyO3/pyo3/pull/1980)\n- Add `pyo3_build_config::Sysconfigdata` and supporting APIs. [#1996](https://github.com/PyO3/pyo3/pull/1996)\n- Add `Py::setattr` method. [#2009](https://github.com/PyO3/pyo3/pull/2009)\n- Add `#[pyo3(crate = \"some::path\")]` option to all attribute macros (except the deprecated `#[pyproto]`). [#2022](https://github.com/PyO3/pyo3/pull/2022)\n- Enable `create_exception!` macro to take an optional docstring. [#2027](https://github.com/PyO3/pyo3/pull/2027)\n- Enable `#[pyclass]` for fieldless (aka C-like) enums. [#2034](https://github.com/PyO3/pyo3/pull/2034)\n- Add buffer magic methods `__getbuffer__` and `__releasebuffer__` to `#[pymethods]`. [#2067](https://github.com/PyO3/pyo3/pull/2067)\n- Add support for paths in `wrap_pyfunction` and `wrap_pymodule`. [#2081](https://github.com/PyO3/pyo3/pull/2081)\n- Enable `wrap_pyfunction!` to wrap a `#[pyfunction]` implemented in a different Rust module or crate. [#2091](https://github.com/PyO3/pyo3/pull/2091)\n- Add `PyAny::contains` method (`in` operator for `PyAny`). [#2115](https://github.com/PyO3/pyo3/pull/2115)\n- Add `PyMapping::contains` method (`in` operator for `PyMapping`). [#2133](https://github.com/PyO3/pyo3/pull/2133)\n- Add garbage collection magic magic methods `__traverse__` and `__clear__` to `#[pymethods]`. [#2159](https://github.com/PyO3/pyo3/pull/2159)\n- Add support for `from_py_with` on struct tuples and enums to override the default from-Python conversion. [#2181](https://github.com/PyO3/pyo3/pull/2181)\n- Add `eq`, `ne`, `lt`, `le`, `gt`, `ge` methods to `PyAny` that wrap `rich_compare`. [#2175](https://github.com/PyO3/pyo3/pull/2175)\n- Add `Py::is` and `PyAny::is` methods to check for object identity. [#2183](https://github.com/PyO3/pyo3/pull/2183)\n- Add support for the `__getattribute__` magic method. [#2187](https://github.com/PyO3/pyo3/pull/2187)\n\n### Changed\n\n- `PyType::is_subclass`, `PyErr::is_instance` and `PyAny::is_instance` now operate run-time type object instead of a type known at compile-time. The old behavior is still available as `PyType::is_subclass_of`, `PyErr::is_instance_of` and `PyAny::is_instance_of`.  [#1985](https://github.com/PyO3/pyo3/pull/1985)\n- Rename some methods on `PyErr` (the old names are just marked deprecated for now): [#2026](https://github.com/PyO3/pyo3/pull/2026)\n  - `pytype` -> `get_type`\n  - `pvalue` -> `value` (and deprecate equivalent `instance`)\n  - `ptraceback` -> `traceback`\n  - `from_instance` -> `from_value`\n  - `into_instance` -> `into_value`\n- `PyErr::new_type` now takes an optional docstring and now returns `PyResult<Py<PyType>>` rather than a `ffi::PyTypeObject` pointer. [#2027](https://github.com/PyO3/pyo3/pull/2027)\n- Deprecate `PyType::is_instance`; it is inconsistent with other `is_instance` methods in PyO3. Instead of `typ.is_instance(obj)`, use `obj.is_instance(typ)`. [#2031](https://github.com/PyO3/pyo3/pull/2031)\n- `__getitem__`, `__setitem__` and `__delitem__` in `#[pymethods]` now implement both a Python mapping and sequence by default. [#2065](https://github.com/PyO3/pyo3/pull/2065)\n- Improve performance and error messages for `#[derive(FromPyObject)]` for enums. [#2068](https://github.com/PyO3/pyo3/pull/2068)\n- Reduce generated LLVM code size (to improve compile times) for:\n  - internal `handle_panic` helper [#2074](https://github.com/PyO3/pyo3/pull/2074) [#2158](https://github.com/PyO3/pyo3/pull/2158)\n  - `#[pyfunction]` and `#[pymethods]` argument extraction [#2075](https://github.com/PyO3/pyo3/pull/2075) [#2085](https://github.com/PyO3/pyo3/pull/2085)\n  - `#[pyclass]` type object creation [#2076](https://github.com/PyO3/pyo3/pull/2076) [#2081](https://github.com/PyO3/pyo3/pull/2081) [#2157](https://github.com/PyO3/pyo3/pull/2157)\n- Respect Rust privacy rules for items wrapped with `wrap_pyfunction` and `wrap_pymodule`. [#2081](https://github.com/PyO3/pyo3/pull/2081)\n- Add modulo argument to `__ipow__` magic method. [#2083](https://github.com/PyO3/pyo3/pull/2083)\n- Fix FFI definition for `_PyCFunctionFast`. [#2126](https://github.com/PyO3/pyo3/pull/2126)\n- `PyDateTimeAPI` and `PyDateTime_TimeZone_UTC` are now unsafe functions instead of statics. [#2126](https://github.com/PyO3/pyo3/pull/2126)\n- `PyDateTimeAPI` does not implicitly call `PyDateTime_IMPORT` anymore to reflect the original Python API more closely. Before the first call to `PyDateTime_IMPORT` a null pointer is returned. Therefore before calling any of the following FFI functions `PyDateTime_IMPORT` must be called to avoid undefined behavior: [#2126](https://github.com/PyO3/pyo3/pull/2126)\n  - `PyDateTime_TimeZone_UTC`\n  - `PyDate_Check`\n  - `PyDate_CheckExact`\n  - `PyDateTime_Check`\n  - `PyDateTime_CheckExact`\n  - `PyTime_Check`\n  - `PyTime_CheckExact`\n  - `PyDelta_Check`\n  - `PyDelta_CheckExact`\n  - `PyTZInfo_Check`\n  - `PyTZInfo_CheckExact`\n  - `PyDateTime_FromTimestamp`\n  - `PyDate_FromTimestamp`\n- Deprecate the `gc` option for `pyclass` (e.g. `#[pyclass(gc)]`). Just implement a `__traverse__` `#[pymethod]`. [#2159](https://github.com/PyO3/pyo3/pull/2159)\n- The `ml_meth` field of `PyMethodDef` is now represented by the `PyMethodDefPointer` union. [2166](https://github.com/PyO3/pyo3/pull/2166)\n- Deprecate the `#[pyproto]` traits. [#2173](https://github.com/PyO3/pyo3/pull/2173)\n\n### Removed\n\n- Remove all functionality deprecated in PyO3 0.14. [#2007](https://github.com/PyO3/pyo3/pull/2007)\n- Remove `Default` impl for `PyMethodDef`. [#2166](https://github.com/PyO3/pyo3/pull/2166)\n- Remove `PartialEq` impl for `Py` and `PyAny` (use the new `is` instead). [#2183](https://github.com/PyO3/pyo3/pull/2183)\n\n### Fixed\n\n- Fix undefined symbol for `PyObject_HasAttr` on PyPy. [#2025](https://github.com/PyO3/pyo3/pull/2025)\n- Fix memory leak in `PyErr::into_value`. [#2026](https://github.com/PyO3/pyo3/pull/2026)\n- Fix clippy warning `needless-option-as-deref` in code generated by `#[pyfunction]` and `#[pymethods]`. [#2040](https://github.com/PyO3/pyo3/pull/2040)\n- Fix undefined behavior in `PySlice::indices`. [#2061](https://github.com/PyO3/pyo3/pull/2061)\n- Fix the `wrap_pymodule!` macro using the wrong name for a `#[pymodule]` with a `#[pyo3(name = \"..\")]` attribute. [#2081](https://github.com/PyO3/pyo3/pull/2081)\n- Fix magic methods in `#[pymethods]` accepting implementations with the wrong number of arguments. [#2083](https://github.com/PyO3/pyo3/pull/2083)\n- Fix panic in `#[pyfunction]` generated code when a required argument following an `Option` was not provided.  [#2093](https://github.com/PyO3/pyo3/pull/2093)\n- Fixed undefined behavior caused by incorrect `ExactSizeIterator` implementations. [#2124](https://github.com/PyO3/pyo3/pull/2124)\n- Fix missing FFI definition `PyCMethod_New` on Python 3.9 and up. [#2143](https://github.com/PyO3/pyo3/pull/2143)\n- Add missing FFI definitions `_PyLong_NumBits` and `_PyLong_AsByteArray` on PyPy. [#2146](https://github.com/PyO3/pyo3/pull/2146)\n- Fix memory leak in implementation of `AsPyPointer` for `Option<T>`. [#2160](https://github.com/PyO3/pyo3/pull/2160)\n- Fix FFI definition of `_PyLong_NumBits` to return `size_t` instead of `c_int`. [#2161](https://github.com/PyO3/pyo3/pull/2161)\n- Fix `TypeError` thrown when argument parsing failed missing the originating causes. [2177](https://github.com/PyO3/pyo3/pull/2178)\n\n## [0.15.2] - 2022-04-14\n\n### Packaging\n\n- Backport of PyPy 3.9 support from PyO3 0.16. [#2262](https://github.com/PyO3/pyo3/pull/2262)\n\n## [0.15.1] - 2021-11-19\n\n### Added\n\n- Add implementations for `Py::as_ref` and `Py::into_ref` for `Py<PySequence>`, `Py<PyIterator>` and `Py<PyMapping>`. [#1682](https://github.com/PyO3/pyo3/pull/1682)\n- Add `PyTraceback` type to represent and format Python tracebacks. [#1977](https://github.com/PyO3/pyo3/pull/1977)\n\n### Changed\n\n- `#[classattr]` constants with a known magic method name (which is lowercase) no longer trigger lint warnings expecting constants to be uppercase. [#1969](https://github.com/PyO3/pyo3/pull/1969)\n\n### Fixed\n\n- Fix creating `#[classattr]` by functions with the name of a known magic method. [#1969](https://github.com/PyO3/pyo3/pull/1969)\n- Fix use of `catch_unwind` in `allow_threads` which can cause fatal crashes. [#1989](https://github.com/PyO3/pyo3/pull/1989)\n- Fix build failure on PyPy when abi3 features are activated. [#1991](https://github.com/PyO3/pyo3/pull/1991)\n- Fix mingw platform detection. [#1993](https://github.com/PyO3/pyo3/pull/1993)\n- Fix panic in `__get__` implementation when accessing descriptor on type object. [#1997](https://github.com/PyO3/pyo3/pull/1997)\n\n## [0.15.0] - 2021-11-03\n\n### Packaging\n\n- `pyo3`'s `Cargo.toml` now advertises `links = \"python\"` to inform Cargo that it links against *libpython*. [#1819](https://github.com/PyO3/pyo3/pull/1819)\n- Added optional `anyhow` feature to convert `anyhow::Error` into `PyErr`. [#1822](https://github.com/PyO3/pyo3/pull/1822)\n- Support Python 3.10. [#1889](https://github.com/PyO3/pyo3/pull/1889)\n- Added optional `eyre` feature to convert `eyre::Report` into `PyErr`. [#1893](https://github.com/PyO3/pyo3/pull/1893)\n- Support PyPy 3.8. [#1948](https://github.com/PyO3/pyo3/pull/1948)\n\n### Added\n\n- Add `PyList::get_item_unchecked` and `PyTuple::get_item_unchecked` to get items without bounds checks. [#1733](https://github.com/PyO3/pyo3/pull/1733)\n- Support `#[doc = include_str!(...)]` attributes on Rust 1.54 and up. [#1746](https://github.com/PyO3/pyo3/issues/1746)\n- Add `PyAny::py` as a convenience for `PyNativeType::py`. [#1751](https://github.com/PyO3/pyo3/pull/1751)\n- Add implementation of `std::ops::Index<usize>` for `PyList`, `PyTuple` and `PySequence`. [#1825](https://github.com/PyO3/pyo3/pull/1825)\n- Add range indexing implementations of `std::ops::Index` for `PyList`, `PyTuple` and `PySequence`. [#1829](https://github.com/PyO3/pyo3/pull/1829)\n- Add `PyMapping` type to represent the Python mapping protocol. [#1844](https://github.com/PyO3/pyo3/pull/1844)\n- Add commonly-used sequence methods to `PyList` and `PyTuple`. [#1849](https://github.com/PyO3/pyo3/pull/1849)\n- Add `as_sequence` methods to `PyList` and `PyTuple`. [#1860](https://github.com/PyO3/pyo3/pull/1860)\n- Add support for magic methods in `#[pymethods]`, intended as a replacement for `#[pyproto]`. [#1864](https://github.com/PyO3/pyo3/pull/1864)\n- Add `abi3-py310` feature. [#1889](https://github.com/PyO3/pyo3/pull/1889)\n- Add `PyCFunction::new_closure` to create a Python function from a Rust closure. [#1901](https://github.com/PyO3/pyo3/pull/1901)\n- Add support for positional-only arguments in `#[pyfunction]`. [#1925](https://github.com/PyO3/pyo3/pull/1925)\n- Add `PyErr::take` to attempt to fetch a Python exception if present. [#1957](https://github.com/PyO3/pyo3/pull/1957)\n\n### Changed\n\n- `PyList`, `PyTuple` and `PySequence`'s APIs now accepts only `usize` indices instead of `isize`.\n  [#1733](https://github.com/PyO3/pyo3/pull/1733), [#1802](https://github.com/PyO3/pyo3/pull/1802),\n  [#1803](https://github.com/PyO3/pyo3/pull/1803)\n- `PyList::get_item` and `PyTuple::get_item` now return `PyResult<&PyAny>` instead of panicking. [#1733](https://github.com/PyO3/pyo3/pull/1733)\n- `PySequence::in_place_repeat` and `PySequence::in_place_concat` now return `PyResult<&PySequence>` instead of `PyResult<()>`, which is needed in case of immutable sequences such as tuples. [#1803](https://github.com/PyO3/pyo3/pull/1803)\n- `PySequence::get_slice` now returns `PyResult<&PySequence>` instead of `PyResult<&PyAny>`. [#1829](https://github.com/PyO3/pyo3/pull/1829)\n- Deprecate `PyTuple::split_from`. [#1804](https://github.com/PyO3/pyo3/pull/1804)\n- Deprecate `PyTuple::slice`, new method `PyTuple::get_slice` added with `usize` indices. [#1828](https://github.com/PyO3/pyo3/pull/1828)\n- Deprecate FFI definitions `PyParser_SimpleParseStringFlags`, `PyParser_SimpleParseStringFlagsFilename`, `PyParser_SimpleParseFileFlags` when building for Python 3.9. [#1830](https://github.com/PyO3/pyo3/pull/1830)\n- Mark FFI definitions removed in Python 3.10 `PyParser_ASTFromString`, `PyParser_ASTFromStringObject`, `PyParser_ASTFromFile`, `PyParser_ASTFromFileObject`, `PyParser_SimpleParseStringFlags`, `PyParser_SimpleParseStringFlagsFilename`, `PyParser_SimpleParseFileFlags`, `PyParser_SimpleParseString`, `PyParser_SimpleParseFile`, `Py_SymtableString`, and `Py_SymtableStringObject`. [#1830](https://github.com/PyO3/pyo3/pull/1830)\n- `#[pymethods]` now handles magic methods similarly to `#[pyproto]`. In the future, `#[pyproto]` may be deprecated. [#1864](https://github.com/PyO3/pyo3/pull/1864)\n- Deprecate FFI definitions `PySys_AddWarnOption`, `PySys_AddWarnOptionUnicode` and `PySys_HasWarnOptions`. [#1887](https://github.com/PyO3/pyo3/pull/1887)\n- Deprecate `#[call]` attribute in favor of using `fn __call__`. [#1929](https://github.com/PyO3/pyo3/pull/1929)\n- Fix missing FFI definition `_PyImport_FindExtensionObject` on Python 3.10. [#1942](https://github.com/PyO3/pyo3/pull/1942)\n- Change `PyErr::fetch` to panic in debug mode if no exception is present. [#1957](https://github.com/PyO3/pyo3/pull/1957)\n\n### Fixed\n\n- Fix building with a conda environment on Windows. [#1873](https://github.com/PyO3/pyo3/pull/1873)\n- Fix panic on Python 3.6 when calling `Python::with_gil` with Python initialized but threading not initialized. [#1874](https://github.com/PyO3/pyo3/pull/1874)\n- Fix incorrect linking to version-specific DLL instead of `python3.dll` when cross-compiling to Windows with `abi3`. [#1880](https://github.com/PyO3/pyo3/pull/1880)\n- Fix FFI definition for `PyTuple_ClearFreeList` incorrectly being present for Python 3.9 and up. [#1887](https://github.com/PyO3/pyo3/pull/1887)\n- Fix panic in generated `#[derive(FromPyObject)]` for enums. [#1888](https://github.com/PyO3/pyo3/pull/1888)\n- Fix cross-compiling to Python 3.7 builds with the \"m\" abi flag. [#1908](https://github.com/PyO3/pyo3/pull/1908)\n- Fix `__mod__` magic method fallback to `__rmod__`. [#1934](https://github.com/PyO3/pyo3/pull/1934).\n- Fix missing FFI definition `_PyImport_FindExtensionObject` on Python 3.10. [#1942](https://github.com/PyO3/pyo3/pull/1942)\n\n## [0.14.5] - 2021-09-05\n\n### Added\n\n- Make `pyo3_build_config::InterpreterConfig` and subfields public. [#1848](https://github.com/PyO3/pyo3/pull/1848)\n- Add `resolve-config` feature to the `pyo3-build-config` to control whether its build script does anything. [#1856](https://github.com/PyO3/pyo3/pull/1856)\n\n### Fixed\n\n- Fix 0.14.4 compile regression on `s390x-unknown-linux-gnu` target. [#1850](https://github.com/PyO3/pyo3/pull/1850)\n\n## [0.14.4] - 2021-08-29\n\n### Changed\n\n- Mark `PyString::data` as `unsafe` and disable it and some supporting PyUnicode FFI APIs (which depend on a C bitfield) on big-endian targets. [#1834](https://github.com/PyO3/pyo3/pull/1834)\n\n## [0.14.3] - 2021-08-22\n\n### Added\n\n- Add `PyString::data` to access the raw bytes stored in a Python string. [#1794](https://github.com/PyO3/pyo3/pull/1794)\n\n### Fixed\n\n- Raise `AttributeError` to avoid panic when calling `del` on a `#[setter]` defined class property. [#1779](https://github.com/PyO3/pyo3/pull/1779)\n- Restrict FFI definitions `PyGILState_Check` and `Py_tracefunc` to the unlimited API. [#1787](https://github.com/PyO3/pyo3/pull/1787)\n- Add missing `_type` field to `PyStatus` struct definition. [#1791](https://github.com/PyO3/pyo3/pull/1791)\n- Reduce lower bound `num-complex` optional dependency to support interop with `rust-numpy` and `ndarray` when building with the MSRV of 1.41 [#1799](https://github.com/PyO3/pyo3/pull/1799)\n- Fix memory leak in `Python::run_code`. [#1806](https://github.com/PyO3/pyo3/pull/1806)\n- Fix memory leak in `PyModule::from_code`. [#1810](https://github.com/PyO3/pyo3/pull/1810)\n- Remove use of `pyo3::` in `pyo3::types::datetime` which broke builds using `-Z avoid-dev-deps` [#1811](https://github.com/PyO3/pyo3/pull/1811)\n\n## [0.14.2] - 2021-08-09\n\n### Added\n\n- Add `indexmap` feature to add `ToPyObject`, `IntoPy` and `FromPyObject` implementations for `indexmap::IndexMap`. [#1728](https://github.com/PyO3/pyo3/pull/1728)\n- Add `pyo3_build_config::add_extension_module_link_args` to use in build scripts to set linker arguments (for macOS). [#1755](https://github.com/PyO3/pyo3/pull/1755)\n- Add `Python::with_gil_unchecked` unsafe variation of `Python::with_gil` to allow obtaining a `Python` in scenarios where `Python::with_gil` would fail. [#1769](https://github.com/PyO3/pyo3/pull/1769)\n\n### Changed\n\n- `PyErr::new` no longer acquires the Python GIL internally. [#1724](https://github.com/PyO3/pyo3/pull/1724)\n- Reverted PyO3 0.14.0's use of `cargo:rustc-cdylib-link-arg` in its build script, as Cargo unintentionally allowed crates to pass linker args to downstream crates in this way. Projects supporting macOS may need to restore `.cargo/config.toml` files. [#1755](https://github.com/PyO3/pyo3/pull/1755)\n\n### Fixed\n\n- Fix regression in 0.14.0 rejecting usage of `#[doc(hidden)]` on structs and functions annotated with PyO3 macros. [#1722](https://github.com/PyO3/pyo3/pull/1722)\n- Fix regression in 0.14.0 leading to incorrect code coverage being computed for `#[pyfunction]`s. [#1726](https://github.com/PyO3/pyo3/pull/1726)\n- Fix incorrect FFI definition of `Py_Buffer` on PyPy. [#1737](https://github.com/PyO3/pyo3/pull/1737)\n- Fix incorrect calculation of `dictoffset` on 32-bit Windows. [#1475](https://github.com/PyO3/pyo3/pull/1475)\n- Fix regression in 0.13.2 leading to linking to incorrect Python library on Windows \"gnu\" targets. [#1759](https://github.com/PyO3/pyo3/pull/1759)\n- Fix compiler warning: deny trailing semicolons in expression macro. [#1762](https://github.com/PyO3/pyo3/pull/1762)\n- Fix incorrect FFI definition of `Py_DecodeLocale`. The 2nd argument is now `*mut Py_ssize_t` instead of `Py_ssize_t`. [#1766](https://github.com/PyO3/pyo3/pull/1766)\n\n## [0.14.1] - 2021-07-04\n\n### Added\n\n- Implement `IntoPy<PyObject>` for `&PathBuf` and `&OsString`. [#1712](https://github.com/PyO3/pyo3/pull/1712)\n\n### Fixed\n\n- Fix crashes on PyPy due to incorrect definitions of `PyList_SET_ITEM`. [#1713](https://github.com/PyO3/pyo3/pull/1713)\n\n## [0.14.0] - 2021-07-03\n\n### Packaging\n\n- Update `num-bigint` optional dependency to 0.4. [#1481](https://github.com/PyO3/pyo3/pull/1481)\n- Update `num-complex` optional dependency to 0.4. [#1482](https://github.com/PyO3/pyo3/pull/1482)\n- Extend `hashbrown` optional dependency supported versions to include 0.11. [#1496](https://github.com/PyO3/pyo3/pull/1496)\n- Support PyPy 3.7. [#1538](https://github.com/PyO3/pyo3/pull/1538)\n\n### Added\n\n- Extend conversions for `[T; N]` to all `N` using const generics (on Rust 1.51 and up). [#1128](https://github.com/PyO3/pyo3/pull/1128)\n- Add conversions between `OsStr`/ `OsString` and Python strings. [#1379](https://github.com/PyO3/pyo3/pull/1379)\n- Add conversions between `Path`/ `PathBuf` and Python strings (and `pathlib.Path` objects). [#1379](https://github.com/PyO3/pyo3/pull/1379) [#1654](https://github.com/PyO3/pyo3/pull/1654)\n- Add a new set of `#[pyo3(...)]` attributes to control various PyO3 macro functionality:\n  - `#[pyo3(from_py_with = \"...\")]` function arguments and struct fields to override the default from-Python conversion. [#1411](https://github.com/PyO3/pyo3/pull/1411)\n  - `#[pyo3(name = \"...\")]` for setting Python names. [#1567](https://github.com/PyO3/pyo3/pull/1567)\n  - `#[pyo3(text_signature = \"...\")]` for setting text signature. [#1658](https://github.com/PyO3/pyo3/pull/1658)\n- Add FFI definition `PyCFunction_CheckExact` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425)\n- Add FFI definition `Py_IS_TYPE`. [#1429](https://github.com/PyO3/pyo3/pull/1429)\n- Add FFI definition `_Py_InitializeMain`. [#1473](https://github.com/PyO3/pyo3/pull/1473)\n- Add FFI definitions from `cpython/import.h`.[#1475](https://github.com/PyO3/pyo3/pull/1475)\n- Add tuple and unit struct support for `#[pyclass]` macro. [#1504](https://github.com/PyO3/pyo3/pull/1504)\n- Add FFI definition `PyDateTime_TimeZone_UTC`. [#1572](https://github.com/PyO3/pyo3/pull/1572)\n- Add support for `#[pyclass(extends=Exception)]`. [#1591](https://github.com/PyO3/pyo3/pull/1591)\n- Add `PyErr::cause` and `PyErr::set_cause`. [#1679](https://github.com/PyO3/pyo3/pull/1679)\n- Add FFI definitions from `cpython/pystate.h`. [#1687](https://github.com/PyO3/pyo3/pull/1687/)\n- Add `wrap_pyfunction!` macro to `pyo3::prelude`. [#1695](https://github.com/PyO3/pyo3/pull/1695)\n\n### Changed\n\n- Allow only one `#[pymethods]` block per `#[pyclass]` by default, to remove the dependency on `inventory`. Add a `multiple-pymethods` feature to opt-in the original behavior and dependency on `inventory`. [#1457](https://github.com/PyO3/pyo3/pull/1457)\n- Change `PyTimeAccess::get_fold` to return a `bool` instead of a `u8`. [#1397](https://github.com/PyO3/pyo3/pull/1397)\n- Deprecate FFI definition `PyCFunction_Call` for Python 3.9 and up. [#1425](https://github.com/PyO3/pyo3/pull/1425)\n- Deprecate FFI definition `PyModule_GetFilename`. [#1425](https://github.com/PyO3/pyo3/pull/1425)\n- The `auto-initialize` feature is no longer enabled by default. [#1443](https://github.com/PyO3/pyo3/pull/1443)\n- Change `PyCFunction::new` and `PyCFunction::new_with_keywords` to take `&'static str` arguments rather than implicitly copying (and leaking) them. [#1450](https://github.com/PyO3/pyo3/pull/1450)\n- Deprecate `PyModule::call`, `PyModule::call0`, `PyModule::call1` and `PyModule::get`. [#1492](https://github.com/PyO3/pyo3/pull/1492)\n- Add length information to `PyBufferError`s raised from `PyBuffer::copy_to_slice` and `PyBuffer::copy_from_slice`. [#1534](https://github.com/PyO3/pyo3/pull/1534)\n- Automatically set `-undefined` and `dynamic_lookup` linker arguments on macOS with the `extension-module` feature. [#1539](https://github.com/PyO3/pyo3/pull/1539)\n- Deprecate `#[pyproto]` methods which are easier to implement as `#[pymethods]`: [#1560](https://github.com/PyO3/pyo3/pull/1560)\n  - `PyBasicProtocol::__bytes__` and `PyBasicProtocol::__format__`\n  - `PyContextProtocol::__enter__` and `PyContextProtocol::__exit__`\n  - `PyDescrProtocol::__delete__` and `PyDescrProtocol::__set_name__`\n  - `PyMappingProtocol::__reversed__`\n  - `PyNumberProtocol::__complex__` and `PyNumberProtocol::__round__`\n  - `PyAsyncProtocol::__aenter__` and `PyAsyncProtocol::__aexit__`\n- Deprecate several attributes in favor of the new `#[pyo3(...)]` options:\n  - `#[name = \"...\"]`, replaced by `#[pyo3(name = \"...\")]` [#1567](https://github.com/PyO3/pyo3/pull/1567)\n  - `#[pyfn(m, \"name\")]`, replaced by `#[pyfn(m)] #[pyo3(name = \"...\")]`. [#1610](https://github.com/PyO3/pyo3/pull/1610)\n  - `#[pymodule(name)]`, replaced by `#[pymodule] #[pyo3(name = \"...\")]` [#1650](https://github.com/PyO3/pyo3/pull/1650)\n  - `#[text_signature = \"...\"]`, replaced by `#[pyo3(text_signature = \"...\")]`. [#1658](https://github.com/PyO3/pyo3/pull/1658)\n- Reduce LLVM line counts to improve compilation times. [#1604](https://github.com/PyO3/pyo3/pull/1604)\n- No longer call `PyEval_InitThreads` in `#[pymodule]` init code. [#1630](https://github.com/PyO3/pyo3/pull/1630)\n- Use `METH_FASTCALL` argument passing convention, when possible, to improve `#[pyfunction]` and method performance.\n  [#1619](https://github.com/PyO3/pyo3/pull/1619), [#1660](https://github.com/PyO3/pyo3/pull/1660)\n- Filter sysconfigdata candidates by architecture when cross-compiling. [#1626](https://github.com/PyO3/pyo3/pull/1626)\n\n### Removed\n\n- Remove deprecated exception names `BaseException` etc. [#1426](https://github.com/PyO3/pyo3/pull/1426)\n- Remove deprecated methods `Python::is_instance`, `Python::is_subclass`, `Python::release`, `Python::xdecref`, and `Py::from_owned_ptr_or_panic`. [#1426](https://github.com/PyO3/pyo3/pull/1426)\n- Remove many FFI definitions which never existed in the Python C-API:\n  - (previously deprecated) `PyGetSetDef_INIT`, `PyGetSetDef_DICT`, `PyCoro_Check`, `PyCoroWrapper_Check`, and `PyAsyncGen_Check` [#1426](https://github.com/PyO3/pyo3/pull/1426)\n  - `PyMethodDef_INIT` [#1426](https://github.com/PyO3/pyo3/pull/1426)\n  - `PyTypeObject_INIT` [#1429](https://github.com/PyO3/pyo3/pull/1429)\n  - `PyObject_Check`, `PySuper_Check`, and `FreeFunc` [#1438](https://github.com/PyO3/pyo3/pull/1438)\n  - `PyModuleDef_INIT` [#1630](https://github.com/PyO3/pyo3/pull/1630)\n- Remove pyclass implementation details from `PyTypeInfo`:\n  - `Type`, `DESCRIPTION`, and `FLAGS` [#1456](https://github.com/PyO3/pyo3/pull/1456)\n  - `BaseType`, `BaseLayout`, `Layout`, `Initializer` [#1596](https://github.com/PyO3/pyo3/pull/1596)\n- Remove `PYO3_CROSS_INCLUDE_DIR` environment variable and the associated C header parsing functionality. [#1521](https://github.com/PyO3/pyo3/pull/1521)\n- Remove `raw_pycfunction!` macro. [#1619](https://github.com/PyO3/pyo3/pull/1619)\n- Remove `PyClassAlloc` trait. [#1657](https://github.com/PyO3/pyo3/pull/1657)\n- Remove `PyList::get_parked_item`. [#1664](https://github.com/PyO3/pyo3/pull/1664)\n\n### Fixed\n\n- Remove FFI definition `PyCFunction_ClearFreeList` for Python 3.9 and later. [#1425](https://github.com/PyO3/pyo3/pull/1425)\n- `PYO3_CROSS_LIB_DIR` environment variable no long required when compiling for x86-64 Python from macOS arm64 and reverse. [#1428](https://github.com/PyO3/pyo3/pull/1428)\n- Fix FFI definition `_PyEval_RequestCodeExtraIndex`, which took an argument of the wrong type. [#1429](https://github.com/PyO3/pyo3/pull/1429)\n- Fix FFI definition `PyIndex_Check` missing with the `abi3` feature. [#1436](https://github.com/PyO3/pyo3/pull/1436)\n- Fix incorrect `TypeError` raised when keyword-only argument passed along with a positional argument in `*args`. [#1440](https://github.com/PyO3/pyo3/pull/1440)\n- Fix inability to use a named lifetime for `&PyTuple` of `*args` in `#[pyfunction]`. [#1440](https://github.com/PyO3/pyo3/pull/1440)\n- Fix use of Python argument for `#[pymethods]` inside macro expansions. [#1505](https://github.com/PyO3/pyo3/pull/1505)\n- No longer include `__doc__` in `__all__` generated for `#[pymodule]`. [#1509](https://github.com/PyO3/pyo3/pull/1509)\n- Always use cross-compiling configuration if any of the `PYO3_CROSS` family of environment variables are set. [#1514](https://github.com/PyO3/pyo3/pull/1514)\n- Support `EnvironmentError`, `IOError`, and `WindowsError` on PyPy. [#1533](https://github.com/PyO3/pyo3/pull/1533)\n- Fix unnecessary rebuilds when cycling between `cargo check` and `cargo clippy` in a Python virtualenv. [#1557](https://github.com/PyO3/pyo3/pull/1557)\n- Fix segfault when dereferencing `ffi::PyDateTimeAPI` without the GIL. [#1563](https://github.com/PyO3/pyo3/pull/1563)\n- Fix memory leak in `FromPyObject` implementations for `u128` and `i128`. [#1638](https://github.com/PyO3/pyo3/pull/1638)\n- Fix `#[pyclass(extends=PyDict)]` leaking the dict contents on drop. [#1657](https://github.com/PyO3/pyo3/pull/1657)\n- Fix segfault when calling `PyList::get_item` with negative indices. [#1668](https://github.com/PyO3/pyo3/pull/1668)\n- Fix FFI definitions of `PyEval_SetProfile`/`PyEval_SetTrace` to take `Option<Py_tracefunc>` parameters. [#1692](https://github.com/PyO3/pyo3/pull/1692)\n- Fix `ToPyObject` impl for `HashSet` to accept non-default hashers. [#1702](https://github.com/PyO3/pyo3/pull/1702)\n\n## [0.13.2] - 2021-02-12\n\n### Packaging\n\n- Lower minimum supported Rust version to 1.41. [#1421](https://github.com/PyO3/pyo3/pull/1421)\n\n### Added\n\n- Add unsafe API `with_embedded_python_interpreter` to initialize a Python interpreter, execute a closure, and finalize the interpreter. [#1355](https://github.com/PyO3/pyo3/pull/1355)\n- Add `serde` feature which provides implementations of `Serialize` and `Deserialize` for `Py<T>`. [#1366](https://github.com/PyO3/pyo3/pull/1366)\n- Add FFI definition `_PyCFunctionFastWithKeywords` on Python 3.7 and up. [#1384](https://github.com/PyO3/pyo3/pull/1384)\n- Add `PyDateTime::new_with_fold` method. [#1398](https://github.com/PyO3/pyo3/pull/1398)\n- Add `size_hint` impls for `{PyDict,PyList,PySet,PyTuple}Iterator`s. [#1699](https://github.com/PyO3/pyo3/pull/1699)\n\n### Changed\n\n- `prepare_freethreaded_python` will no longer register an `atexit` handler to call `Py_Finalize`. This resolves a number of issues with incompatible C extensions causing crashes at finalization. [#1355](https://github.com/PyO3/pyo3/pull/1355)\n- Mark `PyLayout::py_init`, `PyClassDict::clear_dict`, and `opt_to_pyobj` safe, as they do not perform any unsafe operations. [#1404](https://github.com/PyO3/pyo3/pull/1404)\n\n### Fixed\n\n- Fix support for using `r#raw_idents` as argument names in pyfunctions. [#1383](https://github.com/PyO3/pyo3/pull/1383)\n- Fix typo in FFI definition for `PyFunction_GetCode` (was incorrectly `PyFunction_Code`). [#1387](https://github.com/PyO3/pyo3/pull/1387)\n- Fix FFI definitions `PyMarshal_WriteObjectToString` and `PyMarshal_ReadObjectFromString` as available in limited API. [#1387](https://github.com/PyO3/pyo3/pull/1387)\n- Fix FFI definitions `PyListObject` and those from `funcobject.h` as requiring non-limited API. [#1387](https://github.com/PyO3/pyo3/pull/1387)\n- Fix unqualified `Result` usage in `pyobject_native_type_base`. [#1402](https://github.com/PyO3/pyo3/pull/1402)\n- Fix build on systems where the default Python encoding is not UTF-8. [#1405](https://github.com/PyO3/pyo3/pull/1405)\n- Fix build on mingw / MSYS2. [#1423](https://github.com/PyO3/pyo3/pull/1423)\n\n## [0.13.1] - 2021-01-10\n\n### Added\n\n- Add support for `#[pyclass(dict)]` and `#[pyclass(weakref)]` with the `abi3` feature on Python 3.9 and up. [#1342](https://github.com/PyO3/pyo3/pull/1342)\n- Add FFI definitions `PyOS_BeforeFork`, `PyOS_AfterFork_Parent`, `PyOS_AfterFork_Child` for Python 3.7 and up. [#1348](https://github.com/PyO3/pyo3/pull/1348)\n- Add an `auto-initialize` feature to control whether PyO3 should automatically initialize an embedded Python interpreter. For compatibility this feature is enabled by default in PyO3 0.13.1, but is planned to become opt-in from PyO3 0.14.0. [#1347](https://github.com/PyO3/pyo3/pull/1347)\n- Add support for cross-compiling to Windows without needing `PYO3_CROSS_INCLUDE_DIR`. [#1350](https://github.com/PyO3/pyo3/pull/1350)\n\n### Deprecated\n\n- Deprecate FFI definitions `PyEval_CallObjectWithKeywords`, `PyEval_CallObject`, `PyEval_CallFunction`, `PyEval_CallMethod` when building for Python 3.9. [#1338](https://github.com/PyO3/pyo3/pull/1338)\n- Deprecate FFI definitions `PyGetSetDef_DICT` and `PyGetSetDef_INIT` which have never been in the Python API. [#1341](https://github.com/PyO3/pyo3/pull/1341)\n- Deprecate FFI definitions `PyGen_NeedsFinalizing`, `PyImport_Cleanup` (removed in 3.9), and `PyOS_InitInterrupts` (3.10). [#1348](https://github.com/PyO3/pyo3/pull/1348)\n- Deprecate FFI definition `PyOS_AfterFork` for Python 3.7 and up. [#1348](https://github.com/PyO3/pyo3/pull/1348)\n- Deprecate FFI definitions `PyCoro_Check`, `PyAsyncGen_Check`, and `PyCoroWrapper_Check`, which have never been in the Python API (for the first two, it is possible to use `PyCoro_CheckExact` and `PyAsyncGen_CheckExact` instead; these are the actual functions provided by the Python API). [#1348](https://github.com/PyO3/pyo3/pull/1348)\n- Deprecate FFI definitions for `PyUnicode_FromUnicode`, `PyUnicode_AsUnicode` and `PyUnicode_AsUnicodeAndSize`, which will be removed from 3.12 and up due to [PEP 623](https://www.python.org/dev/peps/pep-0623/). [#1370](https://github.com/PyO3/pyo3/pull/1370)\n\n### Removed\n\n- Remove FFI definition `PyFrame_ClearFreeList` when building for Python 3.9. [#1341](https://github.com/PyO3/pyo3/pull/1341)\n- Remove FFI definition `_PyDict_Contains` when building for Python 3.10. [#1341](https://github.com/PyO3/pyo3/pull/1341)\n- Remove FFI definitions `PyGen_NeedsFinalizing` and `PyImport_Cleanup` (for 3.9 and up), and `PyOS_InitInterrupts` (3.10). [#1348](https://github.com/PyO3/pyo3/pull/1348)\n\n### Fixed\n\n- Stop including `Py_TRACE_REFS` config setting automatically if `Py_DEBUG` is set on Python 3.8 and up. [#1334](https://github.com/PyO3/pyo3/pull/1334)\n- Remove `#[deny(warnings)]` attribute (and instead refuse warnings only in CI). [#1340](https://github.com/PyO3/pyo3/pull/1340)\n- Fix deprecation warning for missing `__module__` with `#[pyclass]`. [#1343](https://github.com/PyO3/pyo3/pull/1343)\n- Correct return type of `PyFrozenSet::empty` to `&PyFrozenSet` (was incorrectly `&PySet`). [#1351](https://github.com/PyO3/pyo3/pull/1351)\n- Fix missing `Py_INCREF` on heap type objects on Python versions before 3.8. [#1365](https://github.com/PyO3/pyo3/pull/1365)\n\n## [0.13.0] - 2020-12-22\n\n### Packaging\n\n- Drop support for Python 3.5 (as it is now end-of-life). [#1250](https://github.com/PyO3/pyo3/pull/1250)\n- Bump minimum supported Rust version to 1.45. [#1272](https://github.com/PyO3/pyo3/pull/1272)\n- Bump indoc dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272)\n- Bump paste dependency to 1.0. [#1272](https://github.com/PyO3/pyo3/pull/1272)\n- Rename internal crates `pyo3cls` and `pyo3-derive-backend` to `pyo3-macros` and `pyo3-macros-backend` respectively. [#1317](https://github.com/PyO3/pyo3/pull/1317)\n\n### Added\n\n- Add support for building for CPython limited API. Opting-in to the limited API enables a single extension wheel built with PyO3 to be installable on multiple Python versions. This required a few minor changes to runtime behavior of of PyO3 `#[pyclass]` types. See the migration guide for full details. [#1152](https://github.com/PyO3/pyo3/pull/1152)\n  - Add feature flags `abi3-py36`, `abi3-py37`, `abi3-py38` etc. to set the minimum Python version when using the limited API. [#1263](https://github.com/PyO3/pyo3/pull/1263)\n- Add argument names to `TypeError` messages generated by pymethod wrappers. [#1212](https://github.com/PyO3/pyo3/pull/1212)\n- Add FFI definitions for PEP 587 \"Python Initialization Configuration\". [#1247](https://github.com/PyO3/pyo3/pull/1247)\n- Add FFI definitions for `PyEval_SetProfile` and `PyEval_SetTrace`. [#1255](https://github.com/PyO3/pyo3/pull/1255)\n- Add FFI definitions for context.h functions (`PyContext_New`, etc). [#1259](https://github.com/PyO3/pyo3/pull/1259)\n- Add `PyAny::is_instance` method. [#1276](https://github.com/PyO3/pyo3/pull/1276)\n- Add support for conversion between `char` and `PyString`. [#1282](https://github.com/PyO3/pyo3/pull/1282)\n- Add FFI definitions for `PyBuffer_SizeFromFormat`, `PyObject_LengthHint`, `PyObject_CallNoArgs`, `PyObject_CallOneArg`, `PyObject_CallMethodNoArgs`, `PyObject_CallMethodOneArg`, `PyObject_VectorcallDict`, and `PyObject_VectorcallMethod`. [#1287](https://github.com/PyO3/pyo3/pull/1287)\n- Add conversions between `u128`/`i128` and `PyLong` for PyPy. [#1310](https://github.com/PyO3/pyo3/pull/1310)\n- Add `Python::version` and `Python::version_info` to get the running interpreter version. [#1322](https://github.com/PyO3/pyo3/pull/1322)\n- Add conversions for tuples of length 10, 11, and 12. [#1454](https://github.com/PyO3/pyo3/pull/1454)\n\n### Changed\n\n- Change return type of `PyType::name` from `Cow<str>` to `PyResult<&str>`. [#1152](https://github.com/PyO3/pyo3/pull/1152)\n- `#[pyclass(subclass)]` is now required for subclassing from Rust (was previously just required for subclassing from Python). [#1152](https://github.com/PyO3/pyo3/pull/1152)\n- Change `PyIterator` to be consistent with other native types: it is now used as `&PyIterator` instead of `PyIterator<'a>`. [#1176](https://github.com/PyO3/pyo3/pull/1176)\n- Change formatting of `PyDowncastError` messages to be closer to Python's builtin error messages. [#1212](https://github.com/PyO3/pyo3/pull/1212)\n- Change `Debug` and `Display` impls for `PyException` to be consistent with `PyAny`. [#1275](https://github.com/PyO3/pyo3/pull/1275)\n- Change `Debug` impl of `PyErr` to output more helpful information (acquiring the GIL if necessary). [#1275](https://github.com/PyO3/pyo3/pull/1275)\n- Rename `PyTypeInfo::is_instance` and `PyTypeInfo::is_exact_instance` to `PyTypeInfo::is_type_of` and `PyTypeInfo::is_exact_type_of`. [#1278](https://github.com/PyO3/pyo3/pull/1278)\n- Optimize `PyAny::call0`, `Py::call0` and `PyAny::call_method0` and `Py::call_method0` on Python 3.9 and up. [#1287](https://github.com/PyO3/pyo3/pull/1285)\n- Require double-quotes for pyclass name argument e.g `#[pyclass(name = \"MyClass\")]`. [#1303](https://github.com/PyO3/pyo3/pull/1303)\n\n### Deprecated\n\n- Deprecate `Python::is_instance`, `Python::is_subclass`, `Python::release`, and `Python::xdecref`. [#1292](https://github.com/PyO3/pyo3/pull/1292)\n\n### Removed\n\n- Remove deprecated ffi definitions `PyUnicode_AsUnicodeCopy`, `PyUnicode_GetMax`, `_Py_CheckRecursionLimit`, `PyObject_AsCharBuffer`, `PyObject_AsReadBuffer`, `PyObject_CheckReadBuffer` and `PyObject_AsWriteBuffer`, which will be removed in Python 3.10. [#1217](https://github.com/PyO3/pyo3/pull/1217)\n- Remove unused `python3` feature. [#1235](https://github.com/PyO3/pyo3/pull/1235)\n\n### Fixed\n\n- Fix missing field in `PyCodeObject` struct (`co_posonlyargcount`) - caused invalid access to other fields in Python >3.7. [#1260](https://github.com/PyO3/pyo3/pull/1260)\n- Fix building for `x86_64-unknown-linux-musl` target from `x86_64-unknown-linux-gnu` host. [#1267](https://github.com/PyO3/pyo3/pull/1267)\n- Fix `#[text_signature]` interacting badly with rust `r#raw_identifiers`. [#1286](https://github.com/PyO3/pyo3/pull/1286)\n- Fix FFI definitions for `PyObject_Vectorcall` and `PyVectorcall_Call`. [#1287](https://github.com/PyO3/pyo3/pull/1285)\n- Fix building with Anaconda python inside a virtualenv. [#1290](https://github.com/PyO3/pyo3/pull/1290)\n- Fix definition of opaque FFI types. [#1312](https://github.com/PyO3/pyo3/pull/1312)\n- Fix using custom error type in pyclass `#[new]` methods. [#1319](https://github.com/PyO3/pyo3/pull/1319)\n\n## [0.12.4] - 2020-11-28\n\n### Fixed\n\n- Fix reference count bug in implementation of `From<Py<T>>` for `PyObject`, a regression introduced in PyO3 0.12. [#1297](https://github.com/PyO3/pyo3/pull/1297)\n\n## [0.12.3] - 2020-10-12\n\n### Fixed\n\n- Fix support for Rust versions 1.39 to 1.44, broken by an incorrect internal update to paste 1.0 which was done in PyO3 0.12.2. [#1234](https://github.com/PyO3/pyo3/pull/1234)\n\n## [0.12.2] - 2020-10-12\n\n### Added\n\n- Add support for keyword-only arguments without default values in `#[pyfunction]`. [#1209](https://github.com/PyO3/pyo3/pull/1209)\n- Add `Python::check_signals` as a safe a wrapper for `PyErr_CheckSignals`. [#1214](https://github.com/PyO3/pyo3/pull/1214)\n\n### Fixed\n\n- Fix invalid document for protocol methods. [#1169](https://github.com/PyO3/pyo3/pull/1169)\n- Hide docs of PyO3 private implementation details in `pyo3::class::methods`. [#1169](https://github.com/PyO3/pyo3/pull/1169)\n- Fix unnecessary rebuild on PATH changes when the python interpreter is provided by PYO3_PYTHON. [#1231](https://github.com/PyO3/pyo3/pull/1231)\n\n## [0.12.1] - 2020-09-16\n\n### Fixed\n\n- Fix building for a 32-bit Python on 64-bit Windows with a 64-bit Rust toolchain. [#1179](https://github.com/PyO3/pyo3/pull/1179)\n- Fix building on platforms where `c_char` is `u8`. [#1182](https://github.com/PyO3/pyo3/pull/1182)\n\n## [0.12.0] - 2020-09-12\n\n### Added\n\n- Add FFI definitions `Py_FinalizeEx`, `PyOS_getsig`, and `PyOS_setsig`. [#1021](https://github.com/PyO3/pyo3/pull/1021)\n- Add `PyString::to_str` for accessing `PyString` as `&str`. [#1023](https://github.com/PyO3/pyo3/pull/1023)\n- Add `Python::with_gil` for executing a closure with the Python GIL. [#1037](https://github.com/PyO3/pyo3/pull/1037)\n- Add type information to failures in `PyAny::downcast`. [#1050](https://github.com/PyO3/pyo3/pull/1050)\n- Implement `Debug` for `PyIterator`. [#1051](https://github.com/PyO3/pyo3/pull/1051)\n- Add `PyBytes::new_with` and `PyByteArray::new_with` for initialising `bytes` and `bytearray` objects using a closure. [#1074](https://github.com/PyO3/pyo3/pull/1074)\n- Add `#[derive(FromPyObject)]` macro for enums and structs. [#1065](https://github.com/PyO3/pyo3/pull/1065)\n- Add `Py::as_ref` and `Py::into_ref` for converting `Py<T>` to `&T`. [#1098](https://github.com/PyO3/pyo3/pull/1098)\n- Add ability to return `Result` types other than `PyResult` from `#[pyfunction]`, `#[pymethod]` and `#[pyproto]` functions. [#1106](https://github.com/PyO3/pyo3/pull/1118).\n- Implement `ToPyObject`, `IntoPy`, and `FromPyObject` for [hashbrown](https://crates.io/crates/hashbrown)'s `HashMap` and `HashSet` types (requires the `hashbrown` feature). [#1114](https://github.com/PyO3/pyo3/pull/1114)\n- Add `#[pyfunction(pass_module)]` and `#[pyfn(pass_module)]` to pass the module object as the first function argument. [#1143](https://github.com/PyO3/pyo3/pull/1143)\n- Add `PyModule::add_function` and `PyModule::add_submodule` as typed alternatives to `PyModule::add_wrapped`. [#1143](https://github.com/PyO3/pyo3/pull/1143)\n- Add native `PyCFunction` and `PyFunction` types. [#1163](https://github.com/PyO3/pyo3/pull/1163)\n\n### Changed\n\n- Rework exception types: [#1024](https://github.com/PyO3/pyo3/pull/1024) [#1115](https://github.com/PyO3/pyo3/pull/1115)\n  - Rename exception types from e.g. `RuntimeError` to `PyRuntimeError`. The old names continue to exist but are deprecated.\n  - Exception objects are now accessible as `&T` or `Py<T>`, just like other Python-native types.\n  - Rename `PyException::py_err` to `PyException::new_err`.\n  - Rename `PyUnicodeDecodeErr::new_err` to `PyUnicodeDecodeErr::new`.\n  - Remove `PyStopIteration::stop_iteration`.\n- Require `T: Send` for the return value `T` of `Python::allow_threads`. [#1036](https://github.com/PyO3/pyo3/pull/1036)\n- Rename `PYTHON_SYS_EXECUTABLE` to `PYO3_PYTHON`. The old name will continue to work (undocumented) but will be removed in a future release. [#1039](https://github.com/PyO3/pyo3/pull/1039)\n- Remove `unsafe` from signature of `PyType::as_type_ptr`. [#1047](https://github.com/PyO3/pyo3/pull/1047)\n- Change return type of `PyIterator::from_object` to `PyResult<PyIterator>` (was `Result<PyIterator, PyDowncastError>`). [#1051](https://github.com/PyO3/pyo3/pull/1051)\n- `IntoPy` is no longer implied by `FromPy`. [#1063](https://github.com/PyO3/pyo3/pull/1063)\n- Change `PyObject` to be a type alias for `Py<PyAny>`. [#1063](https://github.com/PyO3/pyo3/pull/1063)\n- Rework `PyErr` to be compatible with the `std::error::Error` trait: [#1067](https://github.com/PyO3/pyo3/pull/1067) [#1115](https://github.com/PyO3/pyo3/pull/1115)\n  - Implement `Display`, `Error`, `Send` and `Sync` for `PyErr` and `PyErrArguments`.\n  - Add `PyErr::instance` for accessing `PyErr` as `&PyBaseException`.\n  - `PyErr`'s fields are now an implementation detail. The equivalent values can be accessed with `PyErr::ptype`, `PyErr::pvalue` and `PyErr::ptraceback`.\n  - Change receiver of `PyErr::print` and `PyErr::print_and_set_sys_last_vars` to `&self` (was `self`).\n  - Remove `PyErrValue`, `PyErr::from_value`, `PyErr::into_normalized`, and `PyErr::normalize`.\n  - Remove `PyException::into`.\n  - Remove `Into<PyResult<T>>` for `PyErr` and `PyException`.\n- Change methods generated by `#[pyproto]` to return `NotImplemented` if Python should try a reversed operation. #[1072](https://github.com/PyO3/pyo3/pull/1072)\n- Change argument to `PyModule::add` to `impl IntoPy<PyObject>` (was `impl ToPyObject`). #[1124](https://github.com/PyO3/pyo3/pull/1124)\n\n### Removed\n\n- Remove many exception and `PyErr` APIs; see the \"changed\" section above. [#1024](https://github.com/PyO3/pyo3/pull/1024) [#1067](https://github.com/PyO3/pyo3/pull/1067) [#1115](https://github.com/PyO3/pyo3/pull/1115)\n- Remove `PyString::to_string` (use new `PyString::to_str`). [#1023](https://github.com/PyO3/pyo3/pull/1023)\n- Remove `PyString::as_bytes`. [#1023](https://github.com/PyO3/pyo3/pull/1023)\n- Remove `Python::register_any`. [#1023](https://github.com/PyO3/pyo3/pull/1023)\n- Remove `GILGuard::acquire` from the public API. Use `Python::acquire_gil` or `Python::with_gil`. [#1036](https://github.com/PyO3/pyo3/pull/1036)\n- Remove the `FromPy` trait. [#1063](https://github.com/PyO3/pyo3/pull/1063)\n- Remove the `AsPyRef` trait. [#1098](https://github.com/PyO3/pyo3/pull/1098)\n\n### Fixed\n\n- Correct FFI definitions `Py_SetProgramName` and `Py_SetPythonHome` to take `*const` arguments (was `*mut`). [#1021](https://github.com/PyO3/pyo3/pull/1021)\n- Fix `FromPyObject` for `num_bigint::BigInt` for Python objects with an `__index__` method. [#1027](https://github.com/PyO3/pyo3/pull/1027)\n- Correct FFI definition `_PyLong_AsByteArray` to take `*mut c_uchar` argument (was `*const c_uchar`). [#1029](https://github.com/PyO3/pyo3/pull/1029)\n- Fix segfault with `#[pyclass(dict, unsendable)]`. [#1058](https://github.com/PyO3/pyo3/pull/1058) [#1059](https://github.com/PyO3/pyo3/pull/1059)\n- Fix using `&Self` as an argument type for functions in a `#[pymethods]` block. [#1071](https://github.com/PyO3/pyo3/pull/1071)\n- Fix best-effort build against PyPy 3.6. [#1092](https://github.com/PyO3/pyo3/pull/1092)\n- Fix many cases of lifetime elision in `#[pyproto]` implementations. [#1093](https://github.com/PyO3/pyo3/pull/1093)\n- Fix detection of Python build configuration when cross-compiling. [#1095](https://github.com/PyO3/pyo3/pull/1095)\n- Always link against libpython on android with the `extension-module` feature. [#1095](https://github.com/PyO3/pyo3/pull/1095)\n- Fix the `+` operator not trying `__radd__` when both `__add__` and `__radd__` are defined in `PyNumberProtocol` (and similar for all other reversible operators). [#1107](https://github.com/PyO3/pyo3/pull/1107)\n- Fix building with Anaconda python. [#1175](https://github.com/PyO3/pyo3/pull/1175)\n\n## [0.11.1] - 2020-06-30\n\n### Added\n\n- `#[pyclass(unsendable)]`. [#1009](https://github.com/PyO3/pyo3/pull/1009)\n\n### Changed\n\n- Update `parking_lot` dependency to `0.11`. [#1010](https://github.com/PyO3/pyo3/pull/1010)\n\n## [0.11.0] - 2020-06-28\n\n### Added\n\n- Support stable versions of Rust (>=1.39). [#969](https://github.com/PyO3/pyo3/pull/969)\n- Add FFI definition `PyObject_AsFileDescriptor`. [#938](https://github.com/PyO3/pyo3/pull/938)\n- Add `PyByteArray::data`, `PyByteArray::as_bytes`, and `PyByteArray::as_bytes_mut`. [#967](https://github.com/PyO3/pyo3/pull/967)\n- Add `GILOnceCell` to use in situations where `lazy_static` or `once_cell` can deadlock. [#975](https://github.com/PyO3/pyo3/pull/975)\n- Add `Py::borrow`, `Py::borrow_mut`, `Py::try_borrow`, and `Py::try_borrow_mut` for accessing `#[pyclass]` values. [#976](https://github.com/PyO3/pyo3/pull/976)\n- Add `IterNextOutput` and `IterANextOutput` for returning from `__next__` / `__anext__`. [#997](https://github.com/PyO3/pyo3/pull/997)\n\n### Changed\n\n- Simplify internals of `#[pyo3(get)]` attribute. (Remove the hidden API `GetPropertyValue`.) [#934](https://github.com/PyO3/pyo3/pull/934)\n- Call `Py_Finalize` at exit to flush buffers, etc. [#943](https://github.com/PyO3/pyo3/pull/943)\n- Add type parameter to PyBuffer. #[951](https://github.com/PyO3/pyo3/pull/951)\n- Require `Send` bound for `#[pyclass]`. [#966](https://github.com/PyO3/pyo3/pull/966)\n- Add `Python` argument to most methods on `PyObject` and `Py<T>` to ensure GIL safety. [#970](https://github.com/PyO3/pyo3/pull/970)\n- Change signature of `PyTypeObject::type_object` - now takes `Python` argument and returns `&PyType`. [#970](https://github.com/PyO3/pyo3/pull/970)\n- Change return type of `PyTuple::slice` and `PyTuple::split_from` from `Py<PyTuple>` to `&PyTuple`. [#970](https://github.com/PyO3/pyo3/pull/970)\n- Change return type of `PyTuple::as_slice` to `&[&PyAny]`. [#971](https://github.com/PyO3/pyo3/pull/971)\n- Rename `PyTypeInfo::type_object` to `type_object_raw`, and add `Python` argument. [#975](https://github.com/PyO3/pyo3/pull/975)\n- Update `num-complex` optional dependency from `0.2` to `0.3`. [#977](https://github.com/PyO3/pyo3/pull/977)\n- Update `num-bigint` optional dependency from `0.2` to `0.3`. [#978](https://github.com/PyO3/pyo3/pull/978)\n- `#[pyproto]` is re-implemented without specialization. [#961](https://github.com/PyO3/pyo3/pull/961)\n- `PyClassAlloc::alloc` is renamed to `PyClassAlloc::new`. [#990](https://github.com/PyO3/pyo3/pull/990)\n- `#[pyproto]` methods can now have return value `T` or `PyResult<T>` (previously only `PyResult<T>` was supported). [#996](https://github.com/PyO3/pyo3/pull/996)\n- `#[pyproto]` methods can now skip annotating the return type if it is `()`. [#998](https://github.com/PyO3/pyo3/pull/998)\n\n### Removed\n\n- Remove `ManagedPyRef` (unused, and needs specialization) [#930](https://github.com/PyO3/pyo3/pull/930)\n\n### Fixed\n\n- Fix passing explicit `None` to `Option<T>` argument `#[pyfunction]` with a default value. [#936](https://github.com/PyO3/pyo3/pull/936)\n- Fix `PyClass.__new__`'s not respecting subclasses when inherited by a Python class. [#990](https://github.com/PyO3/pyo3/pull/990)\n- Fix returning `Option<T>` from `#[pyproto]` methods. [#996](https://github.com/PyO3/pyo3/pull/996)\n- Fix accepting `PyRef<Self>` and `PyRefMut<Self>` to `#[getter]` and `#[setter]` methods. [#999](https://github.com/PyO3/pyo3/pull/999)\n\n## [0.10.1] - 2020-05-14\n\n### Fixed\n\n- Fix deadlock in `Python::acquire_gil` after dropping a `PyObject` or `Py<T>`. [#924](https://github.com/PyO3/pyo3/pull/924)\n\n## [0.10.0] - 2020-05-13\n\n### Added\n\n- Add FFI definition `_PyDict_NewPresized`. [#849](https://github.com/PyO3/pyo3/pull/849)\n- Implement `IntoPy<PyObject>` for `HashSet` and `BTreeSet`. [#864](https://github.com/PyO3/pyo3/pull/864)\n- Add `PyAny::dir` method. [#886](https://github.com/PyO3/pyo3/pull/886)\n- Gate macros behind a `macros` feature (enabled by default). [#897](https://github.com/PyO3/pyo3/pull/897)\n- Add ability to define class attributes using `#[classattr]` on functions in `#[pymethods]`. [#905](https://github.com/PyO3/pyo3/pull/905)\n- Implement `Clone` for `PyObject` and `Py<T>`. [#908](https://github.com/PyO3/pyo3/pull/908)\n- Implement `Deref<Target = PyAny>` for all builtin types. (`PyList`, `PyTuple`, `PyDict` etc.) [#911](https://github.com/PyO3/pyo3/pull/911)\n- Implement `Deref<Target = PyAny>` for `PyCell<T>`. [#911](https://github.com/PyO3/pyo3/pull/911)\n- Add `#[classattr]` support for associated constants in `#[pymethods]`. [#914](https://github.com/PyO3/pyo3/pull/914)\n\n### Changed\n\n- Panics will now be raised as a Python `PanicException`. [#797](https://github.com/PyO3/pyo3/pull/797)\n- Change `PyObject` and `Py<T>` reference counts to decrement immediately upon drop when the GIL is held. [#851](https://github.com/PyO3/pyo3/pull/851)\n- Allow `PyIterProtocol` methods to use either `PyRef` or `PyRefMut` as the receiver type. [#856](https://github.com/PyO3/pyo3/pull/856)\n- Change the implementation of `FromPyObject` for `Py<T>` to apply to a wider range of `T`, including all `T: PyClass`. [#880](https://github.com/PyO3/pyo3/pull/880)\n- Move all methods from the `ObjectProtocol` trait to the `PyAny` struct. [#911](https://github.com/PyO3/pyo3/pull/911)\n- Remove need for `#![feature(specialization)]` in crates depending on PyO3. [#917](https://github.com/PyO3/pyo3/pull/917)\n\n### Removed\n\n- Remove `PyMethodsProtocol` trait. [#889](https://github.com/PyO3/pyo3/pull/889)\n- Remove `num-traits` dependency. [#895](https://github.com/PyO3/pyo3/pull/895)\n- Remove `ObjectProtocol` trait. [#911](https://github.com/PyO3/pyo3/pull/911)\n- Remove `PyAny::None`. Users should use `Python::None` instead. [#911](https://github.com/PyO3/pyo3/pull/911)\n- Remove all `*ProtocolImpl` traits. [#917](https://github.com/PyO3/pyo3/pull/917)\n\n### Fixed\n\n- Fix support for `__radd__` and other `__r*__` methods as implementations for Python mathematical operators. [#839](https://github.com/PyO3/pyo3/pull/839)\n- Fix panics during garbage collection when traversing objects that were already mutably borrowed. [#855](https://github.com/PyO3/pyo3/pull/855)\n- Prevent `&'static` references to Python objects as arguments to `#[pyfunction]` and `#[pymethods]`. [#869](https://github.com/PyO3/pyo3/pull/869)\n- Fix lifetime safety bug with `AsPyRef::as_ref`. [#876](https://github.com/PyO3/pyo3/pull/876)\n- Fix `#[pyo3(get)]` attribute on `Py<T>` fields. [#880](https://github.com/PyO3/pyo3/pull/880)\n- Fix segmentation faults caused by functions such as `PyList::get_item` returning borrowed objects when it was not safe to do so. [#890](https://github.com/PyO3/pyo3/pull/890)\n- Fix segmentation faults caused by nested `Python::acquire_gil` calls creating dangling references. [#893](https://github.com/PyO3/pyo3/pull/893)\n- Fix segmentatation faults when a panic occurs during a call to `Python::allow_threads`. [#912](https://github.com/PyO3/pyo3/pull/912)\n\n## [0.9.2] - 2020-04-09\n\n### Added\n\n- `FromPyObject` implementations for `HashSet` and `BTreeSet`. [#842](https://github.com/PyO3/pyo3/pull/842)\n\n### Fixed\n\n- Correctly detect 32bit architecture. [#830](https://github.com/PyO3/pyo3/pull/830)\n\n## [0.9.1] - 2020-03-23\n\n### Fixed\n\n- Error messages for `#[pyclass]`. [#826](https://github.com/PyO3/pyo3/pull/826)\n- `FromPyObject` implementation for `PySequence`. [#827](https://github.com/PyO3/pyo3/pull/827)\n\n## [0.9.0] - 2020-03-19\n\n### Added\n\n- `PyCell`, which has RefCell-like features. [#770](https://github.com/PyO3/pyo3/pull/770)\n- `PyClass`, `PyLayout`, `PyClassInitializer`. [#683](https://github.com/PyO3/pyo3/pull/683)\n- Implemented `IntoIterator` for `PySet` and `PyFrozenSet`. [#716](https://github.com/PyO3/pyo3/pull/716)\n- `FromPyObject` is now automatically implemented for `T: Clone` pyclasses. [#730](https://github.com/PyO3/pyo3/pull/730)\n- `#[pyo3(get)]` and `#[pyo3(set)]` will now use the Rust doc-comment from the field for the Python property. [#755](https://github.com/PyO3/pyo3/pull/755)\n- `#[setter]` functions may now take an argument of `Pyo3::Python`. [#760](https://github.com/PyO3/pyo3/pull/760)\n- `PyTypeInfo::BaseLayout` and `PyClass::BaseNativeType`. [#770](https://github.com/PyO3/pyo3/pull/770)\n- `PyDowncastImpl`. [#770](https://github.com/PyO3/pyo3/pull/770)\n- Implement `FromPyObject` and `IntoPy<PyObject>` traits for arrays (up to 32). [#778](https://github.com/PyO3/pyo3/pull/778)\n- `migration.md` and `types.md` in the guide. [#795](https://github.com/PyO3/pyo3/pull/795), #[802](https://github.com/PyO3/pyo3/pull/802)\n- `ffi::{_PyBytes_Resize, _PyDict_Next, _PyDict_Contains, _PyDict_GetDictPtr}`. #[820](https://github.com/PyO3/pyo3/pull/820)\n\n### Changed\n\n- `#[new]` does not take `PyRawObject` and can return `Self`. [#683](https://github.com/PyO3/pyo3/pull/683)\n- The blanket implementations for `FromPyObject` for `&T` and `&mut T` are no longer specializable. Implement `PyTryFrom` for your type to control the behavior of `FromPyObject::extract` for your types. [#713](https://github.com/PyO3/pyo3/pull/713)\n- The implementation for `IntoPy<U> for T` where `U: FromPy<T>` is no longer specializable. Control the behavior of this via the implementation of `FromPy`. [#713](https://github.com/PyO3/pyo3/pull/713)\n- Use `parking_lot::Mutex` instead of `spin::Mutex`. [#734](https://github.com/PyO3/pyo3/pull/734)\n- Bumped minimum Rust version to `1.42.0-nightly 2020-01-21`. [#761](https://github.com/PyO3/pyo3/pull/761)\n- `PyRef` and `PyRefMut` are renewed for `PyCell`. [#770](https://github.com/PyO3/pyo3/pull/770)\n- Some new FFI functions for Python 3.8. [#784](https://github.com/PyO3/pyo3/pull/784)\n- `PyAny` is now on the top level module and prelude. [#816](https://github.com/PyO3/pyo3/pull/816)\n\n### Removed\n\n- `PyRawObject`. [#683](https://github.com/PyO3/pyo3/pull/683)\n- `PyNoArgsFunction`. [#741](https://github.com/PyO3/pyo3/pull/741)\n- `initialize_type`. To set the module name for a `#[pyclass]`, use the `module` argument to the macro. #[751](https://github.com/PyO3/pyo3/pull/751)\n- `AsPyRef::as_mut/with/with_mut/into_py/into_mut_py`. [#770](https://github.com/PyO3/pyo3/pull/770)\n- `PyTryFrom::try_from_mut/try_from_mut_exact/try_from_mut_unchecked`. [#770](https://github.com/PyO3/pyo3/pull/770)\n- `Python::mut_from_owned_ptr/mut_from_borrowed_ptr`. [#770](https://github.com/PyO3/pyo3/pull/770)\n- `ObjectProtocol::get_base/get_mut_base`. [#770](https://github.com/PyO3/pyo3/pull/770)\n\n### Fixed\n\n- Fixed unsoundness of subclassing. [#683](https://github.com/PyO3/pyo3/pull/683).\n- Clear error indicator when the exception is handled on the Rust side. [#719](https://github.com/PyO3/pyo3/pull/719)\n- Usage of raw identifiers with `#[pyo3(set)]`. [#745](https://github.com/PyO3/pyo3/pull/745)\n- Usage of `PyObject` with `#[pyo3(get)]`. [#760](https://github.com/PyO3/pyo3/pull/760)\n- `#[pymethods]` used in conjunction with `#[cfg]`. #[769](https://github.com/PyO3/pyo3/pull/769)\n- `\"*\"` in a `#[pyfunction()]` argument list incorrectly accepting any number of positional arguments (use `args = \"*\"` when this behavior is desired). #[792](https://github.com/PyO3/pyo3/pull/792)\n- `PyModule::dict`. #[809](https://github.com/PyO3/pyo3/pull/809)\n- Fix the case where `DESCRIPTION` is not null-terminated. #[822](https://github.com/PyO3/pyo3/pull/822)\n\n## [0.8.5] - 2020-01-05\n\n### Added\n\n- Implemented `FromPyObject` for `HashMap` and `BTreeMap`\n- Support for `#[name = \"foo\"]` attribute for `#[pyfunction]` and in `#[pymethods]`. [#692](https://github.com/PyO3/pyo3/pull/692)\n\n## [0.8.4] - 2019-12-14\n\n### Added\n\n- Support for `#[text_signature]` attribute. [#675](https://github.com/PyO3/pyo3/pull/675)\n\n## [0.8.3] - 2019-11-23\n\n### Removed\n\n- `#[init]` is removed. [#658](https://github.com/PyO3/pyo3/pull/658)\n\n### Fixed\n\n- Now all `&Py~` types have `!Send` bound. [#655](https://github.com/PyO3/pyo3/pull/655)\n- Fix a compile error raised by the stabilization of `!` type. [#672](https://github.com/PyO3/pyo3/issues/672).\n\n## [0.8.2] - 2019-10-27\n\n### Added\n\n- FFI compatibility for PEP 590 Vectorcall. [#641](https://github.com/PyO3/pyo3/pull/641)\n\n### Fixed\n\n- Fix PySequenceProtocol::set_item. [#624](https://github.com/PyO3/pyo3/pull/624)\n- Fix a corner case of BigInt::FromPyObject. [#630](https://github.com/PyO3/pyo3/pull/630)\n- Fix index errors in parameter conversion. [#631](https://github.com/PyO3/pyo3/pull/631)\n- Fix handling of invalid utf-8 sequences in `PyString::as_bytes`. [#639](https://github.com/PyO3/pyo3/pull/639)\n  and `PyString::to_string_lossy` [#642](https://github.com/PyO3/pyo3/pull/642).\n- Remove `__contains__` and `__iter__` from PyMappingProtocol. [#644](https://github.com/PyO3/pyo3/pull/644)\n- Fix proc-macro definition of PySetAttrProtocol. [#645](https://github.com/PyO3/pyo3/pull/645)\n\n## [0.8.1] - 2019-10-08\n\n### Added\n\n- Conversion between [num-bigint](https://github.com/rust-num/num-bigint) and Python int. [#608](https://github.com/PyO3/pyo3/pull/608)\n\n### Fixed\n\n- Make sure the right Python interpreter is used in OSX builds. [#604](https://github.com/PyO3/pyo3/pull/604)\n- Patch specialization being broken by Rust 1.40. [#614](https://github.com/PyO3/pyo3/issues/614)\n- Fix a segfault around PyErr. [#597](https://github.com/PyO3/pyo3/pull/597)\n\n## [0.8.0] - 2019-09-16\n\n### Added\n\n- `module` argument to `pyclass` macro. [#499](https://github.com/PyO3/pyo3/pull/499)\n- `py_run!` macro [#512](https://github.com/PyO3/pyo3/pull/512)\n- Use existing fields and methods before calling custom **getattr**. [#505](https://github.com/PyO3/pyo3/pull/505)\n- `PyBytes` can now be indexed just like `Vec<u8>`\n- Implement `IntoPy<PyObject>` for `PyRef` and `PyRefMut`.\n\n### Changed\n\n- Implementing the Using the `gc` parameter for `pyclass` (e.g. `#[pyclass(gc)]`) without implementing the `class::PyGCProtocol` trait is now a compile-time error. Failing to implement this trait could lead to segfaults. [#532](https://github.com/PyO3/pyo3/pull/532)\n- `PyByteArray::data` has been replaced with `PyDataArray::to_vec` because returning a `&[u8]` is unsound. (See [this comment](https://github.com/PyO3/pyo3/issues/373#issuecomment-512332696) for a great write-up for why that was unsound)\n- Replace `mashup` with `paste`.\n- `GILPool` gained a `Python` marker to prevent it from being misused to release Python objects without the GIL held.\n\n### Removed\n\n- `IntoPyObject` was replaced with `IntoPy<PyObject>`\n- `#[pyclass(subclass)]` is hidden a `unsound-subclass` feature because it's causing segmentation faults.\n\n### Fixed\n\n- More readable error message for generics in pyclass [#503](https://github.com/PyO3/pyo3/pull/503)\n\n## [0.7.0] - 2019-05-26\n\n### Added\n\n- PyPy support by omerbenamram in [#393](https://github.com/PyO3/pyo3/pull/393)\n- Have `PyModule` generate an index of its members (`__all__` list).\n- Allow `slf: PyRef<T>` for pyclass(#419)\n- Allow to use lifetime specifiers in `pymethods`\n- Add `marshal` module. [#460](https://github.com/PyO3/pyo3/pull/460)\n\n### Changed\n\n- `Python::run` returns `PyResult<()>` instead of `PyResult<&PyAny>`.\n- Methods decorated with `#[getter]` and `#[setter]` can now omit wrapping the\n  result type in `PyResult` if they don't raise exceptions.\n\n### Fixed\n\n- `type_object::PyTypeObject` has been marked unsafe because breaking the contract `type_object::PyTypeObject::init_type` can lead to UB.\n- Fixed automatic derive of `PySequenceProtocol` implementation in [#423](https://github.com/PyO3/pyo3/pull/423).\n- Capitalization & better wording to README.md.\n- Docstrings of properties is now properly set using the doc of the `#[getter]` method.\n- Fixed issues with `pymethods` crashing on doc comments containing double quotes.\n- `PySet::new` and `PyFrozenSet::new` now return `PyResult<&Py[Frozen]Set>`; exceptions are raised if\n  the items are not hashable.\n- Fixed building using `venv` on Windows.\n- `PyTuple::new` now returns `&PyTuple` instead of `Py<PyTuple>`.\n- Fixed several issues with argument parsing; notable, the `*args` and `**kwargs`\n  tuple/dict now doesn't contain arguments that are otherwise assigned to parameters.\n\n## [0.6.0] - 2019-03-28\n\n### Regressions\n\n- Currently, [#341](https://github.com/PyO3/pyo3/issues/341) causes `cargo test` to fail with weird linking errors when the `extension-module` feature is activated. For now you can work around this by making the `extension-module` feature optional and running the tests with `cargo test --no-default-features`:\n\n```toml\n[dependencies.pyo3]\nversion = \"0.6.0\"\n\n[features]\nextension-module = [\"pyo3/extension-module\"]\ndefault = [\"extension-module\"]\n```\n\n### Added\n\n- Added a `wrap_pymodule!` macro similar to the existing `wrap_pyfunction!` macro. Only available on python 3\n- Added support for cross compiling (e.g. to arm v7) by mtp401 in [#327](https://github.com/PyO3/pyo3/pull/327). See the \"Cross Compiling\" section in the \"Building and Distribution\" chapter of the guide for more details.\n- The `PyRef` and `PyRefMut` types, which allow to differentiate between an instance of a rust struct on the rust heap and an instance that is embedded inside a python object. By kngwyu in [#335](https://github.com/PyO3/pyo3/pull/335)\n- Added `FromPy<T>` and `IntoPy<T>` which are equivalent to `From<T>` and `Into<T>` except that they require a gil token.\n- Added `ManagedPyRef`, which should eventually replace `ToBorrowedObject`.\n\n### Changed\n\n- Renamed `PyObjectRef` to `PyAny` in #388\n- Renamed `add_function` to `add_wrapped` as it now also supports modules.\n- Renamed `#[pymodinit]` to `#[pymodule]`\n- `py.init(|| value)` becomes `Py::new(value)`\n- `py.init_ref(|| value)` becomes `PyRef::new(value)`\n- `py.init_mut(|| value)` becomes `PyRefMut::new(value)`.\n- `PyRawObject::init` is now infallible, e.g. it returns `()` instead of `PyResult<()>`.\n- Renamed `py_exception!` to `create_exception!` and refactored the error macros.\n- Renamed `wrap_function!` to `wrap_pyfunction!`\n- Renamed `#[prop(get, set)]` to `#[pyo3(get, set)]`\n- `#[pyfunction]` now supports the same arguments as `#[pyfn()]`\n- Some macros now emit proper spanned errors instead of panics.\n- Migrated to the 2018 edition\n- `crate::types::exceptions` moved to `crate::exceptions`\n- Replace `IntoPyTuple` with `IntoPy<Py<PyTuple>>`.\n- `IntoPyPointer` and `ToPyPointer` moved into the crate root.\n- `class::CompareOp` moved into `class::basic::CompareOp`\n- PyTypeObject is now a direct subtrait PyTypeCreate, removing the old cyclical implementation in [#350](https://github.com/PyO3/pyo3/pull/350)\n- Add `PyList::{sort, reverse}` by chr1sj0nes in [#357](https://github.com/PyO3/pyo3/pull/357) and [#358](https://github.com/PyO3/pyo3/pull/358)\n- Renamed the `typeob` module to `type_object`\n\n### Removed\n\n- `PyToken` was removed due to unsoundness (See [#94](https://github.com/PyO3/pyo3/issues/94)).\n- Removed the unnecessary type parameter from `PyObjectAlloc`\n- `NoArgs`. Just use an empty tuple\n- `PyObjectWithGIL`. `PyNativeType` is sufficient now that PyToken is removed.\n\n### Fixed\n\n- A soudness hole where every instances of a `#[pyclass]` struct was considered to be part of a python object, even though you can create instances that are not part of the python heap. This was fixed through `PyRef` and `PyRefMut`.\n- Fix kwargs support in [#328](https://github.com/PyO3/pyo3/pull/328).\n- Add full support for `__dict__` in [#403](https://github.com/PyO3/pyo3/pull/403).\n\n## [0.5.3] - 2019-01-04\n\n### Fixed\n\n- Fix memory leak in ArrayList by kngwyu [#316](https://github.com/PyO3/pyo3/pull/316)\n\n## [0.5.2] - 2018-11-25\n\n### Fixed\n\n- Fix indeterministic segfaults when creating many objects by kngwyu in [#281](https://github.com/PyO3/pyo3/pull/281)\n\n## [0.5.1] - 2018-11-24\n\nYanked\n\n## [0.5.0] - 2018-11-11\n\n### Added\n\n- `#[pyclass]` objects can now be returned from rust functions\n- `PyComplex` by kngwyu in [#226](https://github.com/PyO3/pyo3/pull/226)\n- `PyDict::from_sequence`, equivalent to `dict([(key, val), ...])`\n- Bindings for the `datetime` standard library types: `PyDate`, `PyTime`, `PyDateTime`, `PyTzInfo`, `PyDelta` with associated `ffi` types, by pganssle [#200](https://github.com/PyO3/pyo3/pull/200).\n- `PyString`, `PyUnicode`, and `PyBytes` now have an `as_bytes` method that returns `&[u8]`.\n- `PyObjectProtocol::get_type_ptr` by ijl in [#242](https://github.com/PyO3/pyo3/pull/242)\n\n### Changed\n\n- Removes the types from the root module and the prelude. They now live in `pyo3::types` instead.\n- All exceptions are constructed with `py_err` instead of `new`, as they return `PyErr` and not `Self`.\n- `as_mut` and friends take and `&mut self` instead of `&self`\n- `ObjectProtocol::call` now takes an `Option<&PyDict>` for the kwargs instead of an `IntoPyDictPointer`.\n- `IntoPyDictPointer` was replace by `IntoPyDict` which doesn't convert `PyDict` itself anymore and returns a `PyDict` instead of `*mut PyObject`.\n- `PyTuple::new` now takes an `IntoIterator` instead of a slice\n- Updated to syn 0.15\n- Split `PyTypeObject` into `PyTypeObject` without the create method and `PyTypeCreate` with requires `PyObjectAlloc<Self> + PyTypeInfo + Sized`.\n- Ran `cargo edition --fix` which prefixed path with `crate::` for rust 2018\n- Renamed `async` to `pyasync` as async will be a keyword in the 2018 edition.\n- Starting to use `NonNull<*mut PyObject>` for Py and PyObject by ijl [#260](https://github.com/PyO3/pyo3/pull/260)\n\n### Removed\n\n- Removed most entries from the prelude. The new prelude is small and clear.\n- Slowly removing specialization uses\n- `PyString`, `PyUnicode`, and `PyBytes` no longer have a `data` method\n  (replaced by `as_bytes`) and `PyStringData` has been removed.\n- The pyobject_extract macro\n\n### Fixed\n\n- Added an explanation that the GIL can temporarily be released even while holding a GILGuard.\n- Lots of clippy errors\n- Fix segfault on calling an unknown method on a PyObject\n- Work around a [bug](https://github.com/rust-lang/rust/issues/55380) in the rust compiler by kngwyu [#252](https://github.com/PyO3/pyo3/pull/252)\n- Fixed a segfault with subclassing pyo3 create classes and using `__class__` by kngwyu [#263](https://github.com/PyO3/pyo3/pull/263)\n\n## [0.4.1] - 2018-08-20\n\n### Changed\n\n- PyTryFrom's error is always to `PyDowncastError`\n\n### Fixed\n\n- Fixed compilation on nightly since `use_extern_macros` was stabilized\n\n### Removed\n\n- The pyobject_downcast macro\n\n## [0.4.0] - 2018-07-30\n\n### Changed\n\n- Merged both examples into one\n- Rustfmt all the things :heavy_check_mark:\n- Switched to [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)\n\n### Removed\n\n- Conversions from tuples to PyDict due to [rust-lang/rust#52050](https://github.com/rust-lang/rust/issues/52050)\n\n## [0.3.2] - 2018-07-22\n\n### Changed\n\n- Replaced `concat_idents` with mashup\n\n## [0.3.1] - 2018-07-18\n\n### Fixed\n\n- Fixed scoping bug in pyobject_native_type that would break rust-numpy\n\n## [0.3.0] - 2018-07-18\n\n### Added\n\n- A few internal macros became part of the public api ([#155](https://github.com/PyO3/pyo3/pull/155), [#186](https://github.com/PyO3/pyo3/pull/186))\n- Always clone in getters. This allows using the get-annotation on all Clone-Types\n\n### Changed\n\n- Upgraded to syn 0.14 which means much better error messages :tada:\n- 128 bit integer support by [kngwyu](https://github.com/kngwyu) ([#137](https://github.com/PyO3/pyo3/pull/173))\n- `proc_macro` has been stabilized on nightly ([rust-lang/rust#52081](https://github.com/rust-lang/rust/pull/52081)). This means that we can remove the `proc_macro` feature, but now we need the `use_extern_macros` from the 2018 edition instead.\n- All proc macro are now prefixed with `py` and live in the prelude. This means you can use `#[pyclass]`, `#[pymethods]`, `#[pyproto]`, `#[pyfunction]` and `#[pymodinit]` directly, at least after a `use pyo3::prelude::*`. They were also moved into a module called `proc_macro`. You shouldn't use `#[pyo3::proc_macro::pyclass]` or other longer paths in attributes because `proc_macro_path_invoc` isn't going to be stabilized soon.\n- Renamed the `base` option in the `pyclass` macro to `extends`.\n- `#[pymodinit]` uses the function name as module name, unless the name is overridden with `#[pymodinit(name)]`\n- The guide is now properly versioned.\n\n## [0.2.7] - 2018-05-18\n\n### Fixed\n\n- Fix nightly breakage with proc_macro_path\n\n## [0.2.6] - 2018-04-03\n\n### Fixed\n\n- Fix compatibility with TryFrom trait #137\n\n## [0.2.5] - 2018-02-21\n\n### Added\n\n- CPython 3.7 support\n\n### Fixed\n\n- Embedded CPython 3.7b1 crashes on initialization #110\n- Generated extension functions are weakly typed #108\n- call_method\\* crashes when the method does not exist #113\n- Allow importing exceptions from nested modules #116\n\n## [0.2.4] - 2018-01-19\n\n### Added\n\n- Allow to get mutable ref from PyObject #106\n- Drop `RefFromPyObject` trait\n- Add Python::register_any method\n\n### Fixed\n\n- Fix impl `FromPyObject` for `Py<T>`\n- Mark method that work with raw pointers as unsafe #95\n\n## [0.2.3] - 11-27-2017\n\n### Changed\n\n- Rustup to 1.23.0-nightly 2017-11-07\n\n### Fixed\n\n- Proper `c_char` usage #93\n\n### Removed\n\n- Remove use of now unneeded 'AsciiExt' trait\n\n## [0.2.2] - 09-26-2017\n\n### Changed\n\n- Rustup to 1.22.0-nightly 2017-09-30\n\n## [0.2.1] - 09-26-2017\n\n### Fixed\n\n- Fix rustc const_fn nightly breakage\n\n## [0.2.0] - 08-12-2017\n\n### Added\n\n- Added inheritance support #15\n- Added weakref support #56\n- Added subclass support #64\n- Added `self.__dict__` support #68\n- Added `pyo3::prelude` module #70\n- Better `Iterator` support for PyTuple, PyList, PyDict #75\n- Introduce IntoPyDictPointer similar to IntoPyTuple #69\n\n### Changed\n\n- Allow to add gc support without implementing PyGCProtocol #57\n- Refactor `PyErr` implementation. Drop `py` parameter from constructor.\n\n## [0.1.0] - 07-23-2017\n\n### Added\n\n- Initial release\n\n[Unreleased]: https://github.com/pyo3/pyo3/compare/v0.28.2...HEAD\n[0.28.2]: https://github.com/pyo3/pyo3/compare/v0.28.1...v0.28.2\n[0.28.1]: https://github.com/pyo3/pyo3/compare/v0.28.0...v0.28.1\n[0.28.0]: https://github.com/pyo3/pyo3/compare/v0.27.2...v0.28.0\n[0.27.2]: https://github.com/pyo3/pyo3/compare/v0.27.1...v0.27.2\n[0.27.1]: https://github.com/pyo3/pyo3/compare/v0.27.0...v0.27.1\n[0.27.0]: https://github.com/pyo3/pyo3/compare/v0.26.0...v0.27.0\n[0.26.0]: https://github.com/pyo3/pyo3/compare/v0.25.1...v0.26.0\n[0.25.1]: https://github.com/pyo3/pyo3/compare/v0.25.0...v0.25.1\n[0.25.0]: https://github.com/pyo3/pyo3/compare/v0.24.2...v0.25.0\n[0.24.2]: https://github.com/pyo3/pyo3/compare/v0.24.1...v0.24.2\n[0.24.1]: https://github.com/pyo3/pyo3/compare/v0.24.0...v0.24.1\n[0.24.0]: https://github.com/pyo3/pyo3/compare/v0.23.5...v0.24.0\n[0.23.5]: https://github.com/pyo3/pyo3/compare/v0.23.4...v0.23.5\n[0.23.4]: https://github.com/pyo3/pyo3/compare/v0.23.3...v0.23.4\n[0.23.3]: https://github.com/pyo3/pyo3/compare/v0.23.2...v0.23.3\n[0.23.2]: https://github.com/pyo3/pyo3/compare/v0.23.1...v0.23.2\n[0.23.1]: https://github.com/pyo3/pyo3/compare/v0.23.0...v0.23.1\n[0.23.0]: https://github.com/pyo3/pyo3/compare/v0.22.5...v0.23.0\n[0.22.5]: https://github.com/pyo3/pyo3/compare/v0.22.4...v0.22.5\n[0.22.4]: https://github.com/pyo3/pyo3/compare/v0.22.3...v0.22.4\n[0.22.3]: https://github.com/pyo3/pyo3/compare/v0.22.2...v0.22.3\n[0.22.2]: https://github.com/pyo3/pyo3/compare/v0.22.1...v0.22.2\n[0.22.1]: https://github.com/pyo3/pyo3/compare/v0.22.0...v0.22.1\n[0.22.0]: https://github.com/pyo3/pyo3/compare/v0.21.2...v0.22.0\n[0.21.2]: https://github.com/pyo3/pyo3/compare/v0.21.1...v0.21.2\n[0.21.1]: https://github.com/pyo3/pyo3/compare/v0.21.0...v0.21.1\n[0.21.0]: https://github.com/pyo3/pyo3/compare/v0.20.3...v0.21.0\n[0.21.0-beta.0]: https://github.com/pyo3/pyo3/compare/v0.20.3...v0.21.0-beta.0\n[0.20.3]: https://github.com/pyo3/pyo3/compare/v0.20.2...v0.20.3\n[0.20.2]: https://github.com/pyo3/pyo3/compare/v0.20.1...v0.20.2\n[0.20.1]: https://github.com/pyo3/pyo3/compare/v0.20.0...v0.20.1\n[0.20.0]: https://github.com/pyo3/pyo3/compare/v0.19.2...v0.20.0\n[0.19.2]: https://github.com/pyo3/pyo3/compare/v0.19.1...v0.19.2\n[0.19.1]: https://github.com/pyo3/pyo3/compare/v0.19.0...v0.19.1\n[0.19.0]: https://github.com/pyo3/pyo3/compare/v0.18.3...v0.19.0\n[0.18.3]: https://github.com/pyo3/pyo3/compare/v0.18.2...v0.18.3\n[0.18.2]: https://github.com/pyo3/pyo3/compare/v0.18.1...v0.18.2\n[0.18.1]: https://github.com/pyo3/pyo3/compare/v0.18.0...v0.18.1\n[0.18.0]: https://github.com/pyo3/pyo3/compare/v0.17.3...v0.18.0\n[0.17.3]: https://github.com/pyo3/pyo3/compare/v0.17.2...v0.17.3\n[0.17.2]: https://github.com/pyo3/pyo3/compare/v0.17.1...v0.17.2\n[0.17.1]: https://github.com/pyo3/pyo3/compare/v0.17.0...v0.17.1\n[0.17.0]: https://github.com/pyo3/pyo3/compare/v0.16.6...v0.17.0\n[0.16.6]: https://github.com/pyo3/pyo3/compare/v0.16.5...v0.16.6\n[0.16.5]: https://github.com/pyo3/pyo3/compare/v0.16.4...v0.16.5\n[0.16.4]: https://github.com/pyo3/pyo3/compare/v0.16.3...v0.16.4\n[0.16.3]: https://github.com/pyo3/pyo3/compare/v0.16.2...v0.16.3\n[0.16.2]: https://github.com/pyo3/pyo3/compare/v0.16.1...v0.16.2\n[0.16.1]: https://github.com/pyo3/pyo3/compare/v0.16.0...v0.16.1\n[0.16.0]: https://github.com/pyo3/pyo3/compare/v0.15.1...v0.16.0\n[0.15.2]: https://github.com/pyo3/pyo3/compare/v0.15.1...v0.15.2\n[0.15.1]: https://github.com/pyo3/pyo3/compare/v0.15.0...v0.15.1\n[0.15.0]: https://github.com/pyo3/pyo3/compare/v0.14.5...v0.15.0\n[0.14.5]: https://github.com/pyo3/pyo3/compare/v0.14.4...v0.14.5\n[0.14.4]: https://github.com/pyo3/pyo3/compare/v0.14.3...v0.14.4\n[0.14.3]: https://github.com/pyo3/pyo3/compare/v0.14.2...v0.14.3\n[0.14.2]: https://github.com/pyo3/pyo3/compare/v0.14.1...v0.14.2\n[0.14.1]: https://github.com/pyo3/pyo3/compare/v0.14.0...v0.14.1\n[0.14.0]: https://github.com/pyo3/pyo3/compare/v0.13.2...v0.14.0\n[0.13.2]: https://github.com/pyo3/pyo3/compare/v0.13.1...v0.13.2\n[0.13.1]: https://github.com/pyo3/pyo3/compare/v0.13.0...v0.13.1\n[0.13.0]: https://github.com/pyo3/pyo3/compare/v0.12.4...v0.13.0\n[0.12.4]: https://github.com/pyo3/pyo3/compare/v0.12.3...v0.12.4\n[0.12.3]: https://github.com/pyo3/pyo3/compare/v0.12.2...v0.12.3\n[0.12.2]: https://github.com/pyo3/pyo3/compare/v0.12.1...v0.12.2\n[0.12.1]: https://github.com/pyo3/pyo3/compare/v0.12.0...v0.12.1\n[0.12.0]: https://github.com/pyo3/pyo3/compare/v0.11.1...v0.12.0\n[0.11.1]: https://github.com/pyo3/pyo3/compare/v0.11.0...v0.11.1\n[0.11.0]: https://github.com/pyo3/pyo3/compare/v0.10.1...v0.11.0\n[0.10.1]: https://github.com/pyo3/pyo3/compare/v0.10.0...v0.10.1\n[0.10.0]: https://github.com/pyo3/pyo3/compare/v0.9.2...v0.10.0\n[0.9.2]: https://github.com/pyo3/pyo3/compare/v0.9.1...v0.9.2\n[0.9.1]: https://github.com/pyo3/pyo3/compare/v0.9.0...v0.9.1\n[0.9.0]: https://github.com/pyo3/pyo3/compare/v0.8.5...v0.9.0\n[0.8.5]: https://github.com/pyo3/pyo3/compare/v0.8.4...v0.8.5\n[0.8.4]: https://github.com/pyo3/pyo3/compare/v0.8.3...v0.8.4\n[0.8.3]: https://github.com/pyo3/pyo3/compare/v0.8.2...v0.8.3\n[0.8.2]: https://github.com/pyo3/pyo3/compare/v0.8.1...v0.8.2\n[0.8.1]: https://github.com/pyo3/pyo3/compare/v0.8.0...v0.8.1\n[0.8.0]: https://github.com/pyo3/pyo3/compare/v0.7.0...v0.8.0\n[0.7.0]: https://github.com/pyo3/pyo3/compare/v0.6.0...v0.7.0\n[0.6.0]: https://github.com/pyo3/pyo3/compare/v0.5.3...v0.6.0\n[0.5.3]: https://github.com/pyo3/pyo3/compare/v0.5.2...v0.5.3\n[0.5.2]: https://github.com/pyo3/pyo3/compare/v0.5.1...v0.5.2\n[0.5.1]: https://github.com/pyo3/pyo3/compare/v0.5.0...v0.5.1\n[0.5.0]: https://github.com/pyo3/pyo3/compare/v0.4.1...v0.5.0\n[0.4.1]: https://github.com/pyo3/pyo3/compare/v0.4.0...v0.4.1\n[0.4.0]: https://github.com/pyo3/pyo3/compare/v0.3.2...v0.4.0\n[0.3.2]: https://github.com/pyo3/pyo3/compare/v0.3.1...v0.3.2\n[0.3.1]: https://github.com/pyo3/pyo3/compare/v0.3.0...v0.3.1\n[0.3.0]: https://github.com/pyo3/pyo3/compare/v0.2.7...v0.3.0\n[0.2.7]: https://github.com/pyo3/pyo3/compare/v0.2.6...v0.2.7\n[0.2.6]: https://github.com/pyo3/pyo3/compare/v0.2.5...v0.2.6\n[0.2.5]: https://github.com/pyo3/pyo3/compare/v0.2.4...v0.2.5\n[0.2.4]: https://github.com/pyo3/pyo3/compare/v0.2.3...v0.2.4\n[0.2.3]: https://github.com/pyo3/pyo3/compare/v0.2.2...v0.2.3\n[0.2.2]: https://github.com/pyo3/pyo3/compare/v0.2.1...v0.2.2\n[0.2.1]: https://github.com/pyo3/pyo3/compare/v0.2.0...v0.2.1\n[0.2.0]: https://github.com/pyo3/pyo3/compare/v0.1.0...v0.2.0\n[0.1.0]: https://github.com/PyO3/pyo3/tree/0.1.0\n"
  },
  {
    "path": "CITATION.cff",
    "content": "cff-version: 1.2.0\ntitle: PyO3\nmessage: >-\n  If you use this software as part of a publication and wish to cite\n  it, please use the metadata from this file.\ntype: software\nauthors:\n  - name: PyO3 Project and Contributors\n    website: https://github.com/PyO3\nlicense:\n  - Apache-2.0\n  - MIT\n"
  },
  {
    "path": "Cargo.toml",
    "content": "[package]\nname = \"pyo3\"\nversion = \"0.28.2\"\ndescription = \"Bindings to Python interpreter\"\nauthors = [\"PyO3 Project and Contributors <https://github.com/PyO3>\"]\nreadme = \"README.md\"\nkeywords = [\"pyo3\", \"python\", \"cpython\", \"ffi\"]\nhomepage = \"https://github.com/pyo3/pyo3\"\nrepository = \"https://github.com/pyo3/pyo3\"\ndocumentation = \"https://docs.rs/crate/pyo3/\"\ncategories = [\"api-bindings\", \"development-tools::ffi\"]\nlicense = \"MIT OR Apache-2.0\"\nexclude = [\n    \"/.gitignore\",\n    \".cargo/config\",\n    \"/codecov.yml\",\n    \"/Makefile\",\n    \"/pyproject.toml\",\n    \"/noxfile.py\",\n    \"/.github\",\n    \"/tests/test_compile_error.rs\",\n    \"/tests/ui\",\n]\nedition = \"2021\"\nrust-version.workspace = true\n\n[dependencies]\nlibc = \"0.2.62\"\nonce_cell = \"1.21\"\n\n# ffi bindings to the python interpreter, split into a separate crate so they can be used independently\npyo3-ffi = { path = \"pyo3-ffi\", version = \"=0.28.2\" }\n\n# support crate for macros feature\npyo3-macros = { path = \"pyo3-macros\", version = \"=0.28.2\", optional = true }\n\n# support crate for multiple-pymethods feature\ninventory = { version = \"0.3.5\", optional = true }\n\n# crate integrations that can be added using the eponymous features\nanyhow = { version = \"1.0.1\", optional = true }\nbigdecimal = { version = \"0.4.7\", optional = true }\nbytes = { version = \"1.10\", optional = true }\nchrono = { version = \"0.4.25\", default-features = false, optional = true }\nchrono-tz = { version = \">= 0.10, < 0.11\", default-features = false, optional = true }\neither = { version = \"1.9\", optional = true }\neyre = { version = \">= 0.6.8, < 0.7\", optional = true }\nhashbrown = { version = \">= 0.15.0, < 0.17\", optional = true, default-features = false }\nindexmap = { version = \">= 2.5.0, < 3\", optional = true }\njiff-02 = { package = \"jiff\", version = \"0.2\", optional = true }\nnum-bigint = { version = \"0.4.4\", optional = true }\nnum-complex = { version = \">= 0.4.6, < 0.5\", optional = true }\nnum-rational = { version = \"0.4.1\", optional = true }\nnum-traits = { version = \"0.2.16\", optional = true }\nordered-float = { version = \"5.0.0\", default-features = false, optional = true }\nrust_decimal = { version = \"1.15\", default-features = false, optional = true }\ntime = { version = \"0.3.38\", default-features = false, optional = true }\nserde = { version = \"1.0\", optional = true }\nsmallvec = { version = \"1.0\", optional = true }\nuuid = { version = \"1.12.0\", optional = true }\nlock_api = { version = \"0.4\", optional = true }\nparking_lot = { version = \"0.12\", optional = true }\niana-time-zone = { version = \"0.1\", optional = true, features = [\"fallback\"]}\n\n[target.'cfg(not(target_has_atomic = \"64\"))'.dependencies]\nportable-atomic = \"1.0\"\n\n[dev-dependencies]\nassert_approx_eq = \"1.1.0\"\nchrono = \"0.4.25\"\nchrono-tz = \">= 0.10, < 0.11\"\ntrybuild = \">=1.0.115\"\nproptest = { version = \"1.0\", default-features = false, features = [\"std\"] }\nsend_wrapper = \"0.6\"\nserde = { version = \"1.0\", features = [\"derive\"] }\nserde_json = \"1.0.61\"\nrayon = \"1.6.1\"\nfutures = \"0.3.28\"\ntempfile = \"3.12.0\"\nstatic_assertions = \"1.1.0\"\nuuid = { version = \"1.10.0\", features = [\"v4\"] }\nparking_lot = { version = \"0.12.3\", features = [\"arc_lock\"] }\n\n[build-dependencies]\npyo3-build-config = { path = \"pyo3-build-config\", version = \"=0.28.2\", features = [\"resolve-config\"] }\n\n[features]\ndefault = [\"macros\"]\n\n# Enables support for `async fn` for `#[pyfunction]` and `#[pymethods]`.\nexperimental-async = [\"macros\", \"pyo3-macros/experimental-async\"]\n\n# Enables pyo3::inspect module and additional type information on FromPyObject\n# and IntoPy traits\nexperimental-inspect = [\"pyo3-macros/experimental-inspect\"]\n\n# Enables macros: #[pyclass], #[pymodule], #[pyfunction] etc.\nmacros = [\"pyo3-macros\"]\n\n# Enables multiple #[pymethods] per #[pyclass]\nmultiple-pymethods = [\"inventory\", \"pyo3-macros/multiple-pymethods\"]\n\n# Deprecated: use the `PYO3_BUILD_EXTENSION_MODULE` environment variable when\n# building a Python extension module (set automatically by `setuptools-rust` and\n# `maturin`).\nextension-module = [\"pyo3-ffi/extension-module\"]\n\n# Use the Python limited API. See https://www.python.org/dev/peps/pep-0384/ for more.\nabi3 = [\"pyo3-build-config/abi3\", \"pyo3-ffi/abi3\"]\n\n# With abi3, we can manually set the minimum Python version.\nabi3-py37 = [\"abi3-py38\", \"pyo3-build-config/abi3-py37\", \"pyo3-ffi/abi3-py37\"]\nabi3-py38 = [\"abi3-py39\", \"pyo3-build-config/abi3-py38\", \"pyo3-ffi/abi3-py38\"]\nabi3-py39 = [\"abi3-py310\", \"pyo3-build-config/abi3-py39\", \"pyo3-ffi/abi3-py39\"]\nabi3-py310 = [\"abi3-py311\", \"pyo3-build-config/abi3-py310\", \"pyo3-ffi/abi3-py310\"]\nabi3-py311 = [\"abi3-py312\", \"pyo3-build-config/abi3-py311\", \"pyo3-ffi/abi3-py311\"]\nabi3-py312 = [\"abi3-py313\", \"pyo3-build-config/abi3-py312\", \"pyo3-ffi/abi3-py312\"]\nabi3-py313 = [\"abi3-py314\", \"pyo3-build-config/abi3-py313\", \"pyo3-ffi/abi3-py313\"]\nabi3-py314 = [\"abi3\", \"pyo3-build-config/abi3-py314\", \"pyo3-ffi/abi3-py314\"]\n\n# deprecated: no longer needed, raw-dylib is used instead\ngenerate-import-lib = [\"pyo3-ffi/generate-import-lib\"]\n\n# Changes `Python::attach` to automatically initialize the Python interpreter if needed.\nauto-initialize = []\n\n# Enables `Clone`ing references to Python objects `Py<T>` which panics if the\n# thread is not attached to the Python interpreter.\npy-clone = []\n\n# Adds `OnceExt` and `MutexExt` implementations to the `parking_lot` types\nparking_lot = [\"dep:parking_lot\", \"lock_api\"]\narc_lock = [\"lock_api\", \"lock_api/arc_lock\", \"parking_lot?/arc_lock\"]\n\nnum-bigint = [\"dep:num-bigint\", \"dep:num-traits\"]\nbigdecimal = [\"dep:bigdecimal\", \"num-bigint\"]\n\nchrono-local = [\"chrono/clock\", \"dep:iana-time-zone\"]\n\n\n# Optimizes PyObject to Vec conversion and so on.\nnightly = []\n\n# Activates all additional features\n# This is mostly intended for testing purposes - activating *all* of these isn't particularly useful.\nfull = [\n    \"macros\",\n    # \"multiple-pymethods\", # Not supported by wasm\n    \"anyhow\",\n    \"arc_lock\",\n    \"bigdecimal\",\n    \"bytes\",\n    \"chrono\",\n    \"chrono-local\",\n    \"chrono-tz\",\n    \"either\",\n    \"experimental-async\",\n    \"experimental-inspect\",\n    \"eyre\",\n    \"hashbrown\",\n    \"indexmap\",\n    \"jiff-02\",\n    \"lock_api\",\n    \"num-bigint\",\n    \"num-complex\",\n    \"num-rational\",\n    \"ordered-float\",\n    \"parking_lot\",\n    \"py-clone\",\n    \"rust_decimal\",\n    \"serde\",\n    \"smallvec\",\n    \"time\",\n    \"uuid\",\n]\n\n[workspace]\nmembers = [\n    \"pyo3-ffi\",\n    \"pyo3-build-config\",\n    \"pyo3-macros\",\n    \"pyo3-macros-backend\",\n    \"pyo3-introspection\",\n    \"pytests\",\n    \"examples\",\n]\npackage.rust-version = \"1.83\"\n\n[package.metadata.docs.rs]\nno-default-features = true\nfeatures = [\"full\"]\nrustdoc-args = [\"--cfg\", \"docsrs\"]\n\n[workspace.lints.clippy]\nchecked_conversions = \"warn\"\ndbg_macro = \"warn\"\nexplicit_into_iter_loop = \"warn\"\nexplicit_iter_loop = \"warn\"\nfilter_map_next = \"warn\"\nflat_map_option = \"warn\"\nlet_unit_value = \"warn\"\nmanual_assert = \"warn\"\nmanual_ok_or = \"warn\"\ntodo = \"warn\"\n# TODO: make this \"warn\"\n# https://github.com/PyO3/pyo3/issues/5487\nundocumented_unsafe_blocks = \"allow\"\nunnecessary_wraps = \"warn\"\nuseless_transmute = \"warn\"\nused_underscore_binding = \"warn\"\n\n[workspace.lints.rust]\nelided_lifetimes_in_paths = \"warn\"\ninvalid_doc_attributes = \"warn\"\nrust_2018_idioms = { level = \"warn\", priority = -1 }\nrust_2021_prelude_collisions = \"warn\"\nunused_lifetimes = \"warn\"\nunsafe_op_in_unsafe_fn = \"warn\"\n\n[workspace.lints.rustdoc]\nbroken_intra_doc_links = \"warn\"\nbare_urls = \"warn\"\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "Code-of-Conduct.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n\n"
  },
  {
    "path": "Contributing.md",
    "content": "# Contributing\n\nThank you for your interest in contributing to PyO3! All are welcome - please consider reading our [Code of Conduct](https://github.com/PyO3/pyo3/blob/main/Code-of-Conduct.md) to keep our community positive and inclusive.\n\nIf you are searching for ideas how to contribute, proceed to the [\"Getting started contributing\"](#getting-started-contributing) section. If you have found a specific issue to contribute to and need information about the development process, you may find the section [\"Writing pull requests\"](#writing-pull-requests) helpful.\n\nIf you want to become familiar with the codebase, see\n[Architecture.md](https://github.com/PyO3/pyo3/blob/main/Architecture.md).\n\n## Getting started contributing\n\nPlease join in with any part of PyO3 which interests you. We use GitHub issues to record all bugs and ideas. Feel free to request an issue to be assigned to you if you want to work on it.\n\nYou can browse the API of the non-public parts of PyO3 [here](https://pyo3.netlify.app/internal/doc/pyo3/index.html).\n\nThe following sections also contain specific ideas on where to start contributing to PyO3.\n\n## Setting up a development environment\n\nTo work and develop PyO3, you need Python & Rust installed on your system.\n\n* We encourage the use of [rustup](https://rustup.rs/) to be able to select and choose specific toolchains based on the project.\n* [Pyenv](https://github.com/pyenv/pyenv) is also highly recommended for being able to choose a specific Python version.\n* [virtualenv](https://virtualenv.pypa.io/en/latest/) can also be used with or without Pyenv to use specific installed Python versions.\n* [`nox`][nox] is used to automate many of our CI tasks.\n\n### Testing, linting, etc. with nox\n\n[`Nox`][nox] is used to automate many of our CI tasks and can be used locally to handle verification tasks as you code. We recommend running these actions via nox to make use of our preferred configuration options. You can install nox into your global python with pip: `pip install nox` or (recommended) with [`pipx`][pipx] `pip install pipx`, `pipx install nox`\n\nThe main nox commands we have implemented are:\n\n* `nox -s test` will run the full suite of recommended rust and python tests (>10 minutes)\n* `nox -s test-rust -- skip-full` will run a short suite of rust tests (2-3 minutes)\n* `nox -s ruff` will check python linting and apply standard formatting rules\n* `nox -s rustfmt` will check basic rust linting and apply standard formatting rules\n* `nox -s rumdl` will check the markdown in the guide\n* `nox -s clippy` will run clippy to make recommendations on rust style\n* `nox -s bench` will benchmark your rust code\n* `nox -s codspeed` will run our suite of rust and python performance tests\n* `nox -s coverage` will analyse test coverage and output `coverage.json` (alternatively: `nox -s coverage lcov` outputs `lcov.info`)\n* `nox -s check-guide` will use [`lychee`][lychee] to check all the links in the guide and doc comments.\n\nUse  `nox -l` to list the full set of subcommands you can run.\n\n#### UI Tests\n\nPyO3 uses [`trybuild`][trybuild] to develop UI tests to capture error messages from the Rust compiler for some of the macro functionality.\n\nThe Rust compiler's error output differs depending on whether the `rust-src` component is installed. PyO3's CI has `rust-src` installed, so you need it locally for your UI test output to match:\n\n```bash\nrustup component add rust-src\n```\n\nBecause there are several feature combinations for these UI tests, when updating them all (e.g. for a new Rust compiler version) it may be helpful to use the `update-ui-tests` nox session:\n```bash\nnox -s update-ui-tests\n```\n\n## Ways to help\n\n### Help users identify bugs\n\nThe [PyO3 Discord server](https://discord.gg/33kcChzH7f) is very active with users who are new to PyO3, and often completely new to Rust. Helping them debug is a great way to get experience with the PyO3 codebase.\n\nHelping others often reveals bugs, documentation weaknesses, and missing APIs. It's a good idea to open GitHub issues for these immediately so the resolution can be designed and implemented!\n\n### Implement issues ready for development\n\nIssues where the solution is clear and work is not in progress use the [needs-implementer](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Aneeds-implementer) label.\n\nDon't be afraid if the solution is not clear to you! The core PyO3 contributors will be happy to mentor you through any questions you have to help you write the solution.\n\n### Help write great docs\n\nPyO3 has a user guide (using mdbook) as well as the usual Rust API docs. The aim is for both of these to be detailed, easy to understand, and up-to-date. Pull requests are always welcome to fix typos, change wording, add examples, etc.\n\nThere are some specific areas of focus where help is currently needed for the documentation:\n\n- Issues requesting documentation improvements are tracked with the [documentation](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Adocumentation) label.\n- Not all APIs had docs or examples when they were made. The goal is to have documentation on all PyO3 APIs ([#306](https://github.com/PyO3/pyo3/issues/306)). If you see an API lacking a doc, please write one and open a PR!\n\nTo build the docs (including all features), install [`nox`][nox] and then run\n\n```shell\nnox -s docs -- open\n```\n\n#### Doctests\n\nWe use lots of code blocks in our docs. Run `cargo test --doc` when making changes to check that\nthe doctests still work, or `cargo test` to run all the Rust tests including doctests. See\nhttps://doc.rust-lang.org/rustdoc/documentation-tests.html for a guide on doctests.\n\n#### Building the guide\n\nYou can preview the user guide by building it locally with `mdbook`.\n\nFirst, install [`mdbook`][mdbook], the [`mdbook-tabs`][mdbook-tabs] plugin and [`nox`][nox]. Then, run\n\n```shell\nnox -s build-guide -- --open\n```\n\nTo check all links in the guide are valid, also install [`lychee`][lychee] and use the `check-guide` session instead:\n\n```shell\nnox -s check-guide\n```\n\n### Help design the next PyO3\n\nIssues which don't yet have a clear solution use the [needs-design](https://github.com/PyO3/pyo3/issues?q=is%3Aissue+is%3Aopen+label%3Aneeds-design) label.\n\nIf any of these issues interest you, please join in with the conversation on the issue! All opinions are valued, and if you're interested in going further with e.g. draft PRs to experiment with API designs, even better!\n\n### Review pull requests\n\nEverybody is welcome to submit comments on open PRs. Please help ensure new PyO3 APIs are safe, performant, tidy, and easy to use!\n\n## Writing pull requests\n\nHere are a few things to note when you are writing PRs.\n\n### Testing and Continuous Integration\n\nThe PyO3 repo uses GitHub Actions.\nPRs are blocked from merging if CI is not successful.\nFormatting, linting and tests are checked for all Rust and Python code (the pipeline will abort early if formatting fails to save resources).\nIn addition, all warnings in Rust code are disallowed (using `RUSTFLAGS=\"-D warnings\"`).\n\nTests run with all supported Python versions with the latest stable Rust compiler, as well as for Python 3.9 with the minimum supported Rust version.\n\nIf you are adding a new feature, you should add it to the `full` feature in our *Cargo.toml** so that it is tested in CI.\n\nYou can run the CI pipeline components yourself with `nox`, see [the testing section above](#testing-linting-etc-with-nox).\n\n### Documenting changes\n\nWe use [towncrier](https://towncrier.readthedocs.io/en/stable/index.html) to generate a CHANGELOG for each release.\n\nTo include your changes in the release notes, you should create one (or more) news items in the `newsfragments` directory. Valid news items should be saved as `<PR>.<CATEGORY>.md` where `<PR>` is the pull request number and `<CATEGORY>` is one of the following:\n- `packaging` - for dependency changes and Python / Rust version compatibility changes\n- `added` - for new features\n- `changed` - for features which already existed but have been altered or deprecated\n- `removed` - for features which have been removed\n- `fixed` - for \"changed\" features which were classed as a bugfix\n\nDocs-only PRs do not need news items; start your PR title with `docs:` to skip the check.\n\n### Style guide\n\n#### Generic code\n\nPyO3 has a lot of generic APIs to increase usability. These can come at the cost of generic code bloat. Where reasonable, try to implement a concrete sub-portion of generic functions. There are two forms of this:\n\n- If the concrete sub-portion doesn't benefit from re-use by other functions, name it `inner` and keep it as a local to the function.\n- If the concrete sub-portion is re-used by other functions, preferably name it `_foo` and place it directly below `foo` in the source code (where `foo` is the original generic function).\n\n#### FFI calls\n\nPyO3 makes a lot of FFI calls to Python's C API using raw pointers. Where possible try to avoid using pointers-to-temporaries in expressions:\n\n```rust\n// dangerous\npyo3::ffi::Something(name.to_object(py).as_ptr());\n\n// because the following refactoring is a use-after-free error:\nlet name = name.to_object(py).as_ptr();\npyo3::ffi::Something(name)\n```\n\nInstead, prefer to bind the safe owned `PyObject` wrapper before passing to ffi functions:\n\n```rust\nlet name: PyObject = name.to_object(py);\npyo3::ffi::Something(name.as_ptr())\n// name will automatically be freed when it falls out of scope\n```\n\n## Python and Rust version support policy\n\nPyO3 aims to keep sufficient compatibility to make packaging Python extensions built with PyO3 feasible on most common package managers.\n\nTo keep package maintainers' lives simpler, PyO3 will commit, wherever possible, to only adjust minimum supported Rust and Python versions at the same time. This bump will only come in an `0.x` release, roughly once per year, after the oldest supported Python version reaches its end-of-life. (Check https://endoflife.date/python for a clear timetable on these.)\n\nBelow are guidelines on what compatibility all PRs are expected to deliver for each language.\n\n### Python\n\nPyO3 supports all officially supported Python versions, as well as the latest PyPy3 release. All of these versions are tested in CI.\n\n#### Adding support for new CPython versions\n\nIf you plan to add support for a pre-release version of CPython, here's a (non-exhaustive) checklist:\n\n - [ ] Wait until the last alpha release (usually alpha7), since ABI is not guaranteed until the first beta release\n - [ ] Add prerelease_ver-dev (e.g. `3.14-dev`) to `.github/workflows/ci.yml`, and bump version in `noxfile.py`, `pyo3-ffi/Cargo.toml` under `max-version` within  `[package.metadata.cpython]`, and `max` within `pyo3-ffi/build.rs`\n- [ ] Add a new abi3-prerelease feature for the version (e.g. `abi3-py314`)\n   - In `pyo3-build-config/Cargo.toml`, set abi3-most_current_stable to [\"abi3-prerelease\"] and abi3-prerelease to [\"abi3\"]\n   - In `pyo3-ffi/Cargo.toml`, set abi3-most_current_stable to [\"abi3-prerelease\", \"pyo3-build-config/abi3-most_current_stable\"] and abi3-prerelease to [\"abi3\", \"pyo3-build-config/abi3-prerelease\"]\n   - In `Cargo.toml`, set abi3-most_current_stable to [\"abi3-prerelease\", \"pyo3-ffi/abi3-most_current_stable\"] and abi3-prerelease to [\"abi3\", \"pyo3-ffi/abi3-prerelease\"]\n - [ ] Use `#[cfg(Py_prerelease])` (e.g. `#[cfg(Py_3_14)]`) and `#[cfg(not(Py_prerelease]))` to indicate changes between the stable branches of CPython and the pre-release\n - [ ] Do not add a Rust binding to any function, struct, or global variable prefixed with `_` in CPython's headers\n - [ ] Ping @ngoldbaum and @davidhewitt for assistance\n\n### Rust\n\nPyO3 aims to make use of up-to-date Rust language features to keep the implementation as efficient as possible.\n\nThe minimum Rust version supported will be decided when the release which bumps Python and Rust versions is made. At the time, the minimum Rust version will be set no higher than the lowest Rust version shipped in the current Debian, RHEL and Alpine Linux distributions.\n\nCI tests both the most recent stable Rust version and the minimum supported Rust version. Because of Rust's stability guarantees this is sufficient to confirm support for all Rust versions in between.\n\n## Benchmarking\n\nPyO3 has two sets of benchmarks for evaluating some aspects of its performance. The benchmark suite is currently very small - please open PRs with new benchmarks if you're interested in helping to expand it!\n\nFirst, there are Rust-based benchmarks located in the `pyo3-benches` subdirectory. You can run these benchmarks with:\n\n    nox -s bench\n\nSecond, there is a Python-based benchmark contained in the `pytests` subdirectory. You can read more about it [here](https://github.com/PyO3/pyo3/tree/main/pytests).\n\n## Code coverage\n\nYou can view what code is and isn't covered by PyO3's tests. We aim to have 100% coverage - please check coverage and add tests if you notice a lack of coverage!\n\n- First, ensure the llvm-cov cargo plugin is installed. You may need to run the plugin through cargo once before using it with `nox`.\n```shell\ncargo install cargo-llvm-cov\ncargo llvm-cov\n```\n- Then, generate an `lcov.info` file with\n```shell\nnox -s coverage -- lcov\n```\nYou can install an IDE plugin to view the coverage. For example, if you use VSCode:\n- Add the [coverage-gutters](https://marketplace.visualstudio.com/items?itemName=ryanluker.vscode-coverage-gutters) plugin.\n- Add these settings to VSCode's `settings.json`:\n```json\n{\n    \"coverage-gutters.coverageFileNames\": [\n        \"lcov.info\",\n        \"cov.xml\",\n        \"coverage.xml\",\n    ],\n    \"coverage-gutters.showLineCoverage\": true\n}\n```\n- You should now be able to see green highlights for code that is tested, and red highlights for code that is not tested.\n\n## Sponsor this project\n\nAt the moment there is no official organisation that accepts sponsorship on PyO3's behalf. If you're seeking to provide significant funding to the PyO3 ecosystem, please reach out to us on [GitHub](https://github.com/PyO3/pyo3/issues/new) or [Discord](https://discord.gg/33kcChzH7f) and we can discuss.\n\nIn the meanwhile, some of our maintainers have personal GitHub sponsorship pages and would be grateful for your support:\n\n- [davidhewitt](https://github.com/sponsors/davidhewitt)\n- [messense](https://github.com/sponsors/messense)\n\n[mdbook]: https://rust-lang.github.io/mdBook/cli/index.html\n[mdbook-tabs]: https://mdbook-plugins.rustforweb.org/tabs.html\n[lychee]: https://github.com/lycheeverse/lychee\n[nox]: https://github.com/theacodes/nox\n[pipx]: https://pipx.pypa.io/stable/\n[trybuild]: https://github.com/dtolnay/trybuild\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "Copyright (c) 2017-present PyO3 Project and Contributors.  https://github.com/PyO3\n\n                              Apache License\n                        Version 2.0, January 2004\n                     http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n   \"License\" shall mean the terms and conditions for use, reproduction,\n   and distribution as defined by Sections 1 through 9 of this document.\n\n   \"Licensor\" shall mean the copyright owner or entity authorized by\n   the copyright owner that is granting the License.\n\n   \"Legal Entity\" shall mean the union of the acting entity and all\n   other entities that control, are controlled by, or are under common\n   control with that entity. For the purposes of this definition,\n   \"control\" means (i) the power, direct or indirect, to cause the\n   direction or management of such entity, whether by contract or\n   otherwise, or (ii) ownership of fifty percent (50%) or more of the\n   outstanding shares, or (iii) beneficial ownership of such entity.\n\n   \"You\" (or \"Your\") shall mean an individual or Legal Entity\n   exercising permissions granted by this License.\n\n   \"Source\" form shall mean the preferred form for making modifications,\n   including but not limited to software source code, documentation\n   source, and configuration files.\n\n   \"Object\" form shall mean any form resulting from mechanical\n   transformation or translation of a Source form, including but\n   not limited to compiled object code, generated documentation,\n   and conversions to other media types.\n\n   \"Work\" shall mean the work of authorship, whether in Source or\n   Object form, made available under the License, as indicated by a\n   copyright notice that is included in or attached to the work\n   (an example is provided in the Appendix below).\n\n   \"Derivative Works\" shall mean any work, whether in Source or Object\n   form, that is based on (or derived from) the Work and for which the\n   editorial revisions, annotations, elaborations, or other modifications\n   represent, as a whole, an original work of authorship. For the purposes\n   of this License, Derivative Works shall not include works that remain\n   separable from, or merely link (or bind by name) to the interfaces of,\n   the Work and Derivative Works thereof.\n\n   \"Contribution\" shall mean any work of authorship, including\n   the original version of the Work and any modifications or additions\n   to that Work or Derivative Works thereof, that is intentionally\n   submitted to Licensor for inclusion in the Work by the copyright owner\n   or by an individual or Legal Entity authorized to submit on behalf of\n   the copyright owner. For the purposes of this definition, \"submitted\"\n   means any form of electronic, verbal, or written communication sent\n   to the Licensor or its representatives, including but not limited to\n   communication on electronic mailing lists, source code control systems,\n   and issue tracking systems that are managed by, or on behalf of, the\n   Licensor for the purpose of discussing and improving the Work, but\n   excluding communication that is conspicuously marked or otherwise\n   designated in writing by the copyright owner as \"Not a Contribution.\"\n\n   \"Contributor\" shall mean Licensor and any individual or Legal Entity\n   on behalf of whom a Contribution has been received by Licensor and\n   subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   copyright license to reproduce, prepare Derivative Works of,\n   publicly display, publicly perform, sublicense, and distribute the\n   Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n   this License, each Contributor hereby grants to You a perpetual,\n   worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n   (except as stated in this section) patent license to make, have made,\n   use, offer to sell, sell, import, and otherwise transfer the Work,\n   where such license applies only to those patent claims licensable\n   by such Contributor that are necessarily infringed by their\n   Contribution(s) alone or by combination of their Contribution(s)\n   with the Work to which such Contribution(s) was submitted. If You\n   institute patent litigation against any entity (including a\n   cross-claim or counterclaim in a lawsuit) alleging that the Work\n   or a Contribution incorporated within the Work constitutes direct\n   or contributory patent infringement, then any patent licenses\n   granted to You under this License for that Work shall terminate\n   as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n   Work or Derivative Works thereof in any medium, with or without\n   modifications, and in Source or Object form, provided that You\n   meet the following conditions:\n\n   (a) You must give any other recipients of the Work or\n       Derivative Works a copy of this License; and\n\n   (b) You must cause any modified files to carry prominent notices\n       stating that You changed the files; and\n\n   (c) You must retain, in the Source form of any Derivative Works\n       that You distribute, all copyright, patent, trademark, and\n       attribution notices from the Source form of the Work,\n       excluding those notices that do not pertain to any part of\n       the Derivative Works; and\n\n   (d) If the Work includes a \"NOTICE\" text file as part of its\n       distribution, then any Derivative Works that You distribute must\n       include a readable copy of the attribution notices contained\n       within such NOTICE file, excluding those notices that do not\n       pertain to any part of the Derivative Works, in at least one\n       of the following places: within a NOTICE text file distributed\n       as part of the Derivative Works; within the Source form or\n       documentation, if provided along with the Derivative Works; or,\n       within a display generated by the Derivative Works, if and\n       wherever such third-party notices normally appear. The contents\n       of the NOTICE file are for informational purposes only and\n       do not modify the License. You may add Your own attribution\n       notices within Derivative Works that You distribute, alongside\n       or as an addendum to the NOTICE text from the Work, provided\n       that such additional attribution notices cannot be construed\n       as modifying the License.\n\n   You may add Your own copyright statement to Your modifications and\n   may provide additional or different license terms and conditions\n   for use, reproduction, or distribution of Your modifications, or\n   for any such Derivative Works as a whole, provided Your use,\n   reproduction, and distribution of the Work otherwise complies with\n   the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n   any Contribution intentionally submitted for inclusion in the Work\n   by You to the Licensor shall be under the terms and conditions of\n   this License, without any additional terms or conditions.\n   Notwithstanding the above, nothing herein shall supersede or modify\n   the terms of any separate license agreement you may have executed\n   with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n   names, trademarks, service marks, or product names of the Licensor,\n   except as required for reasonable and customary use in describing the\n   origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n   agreed to in writing, Licensor provides the Work (and each\n   Contributor provides its Contributions) on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n   implied, including, without limitation, any warranties or conditions\n   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n   PARTICULAR PURPOSE. You are solely responsible for determining the\n   appropriateness of using or redistributing the Work and assume any\n   risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n   whether in tort (including negligence), contract, or otherwise,\n   unless required by applicable law (such as deliberate and grossly\n   negligent acts) or agreed to in writing, shall any Contributor be\n   liable to You for damages, including any direct, indirect, special,\n   incidental, or consequential damages of any character arising as a\n   result of this License or out of the use or inability to use the\n   Work (including but not limited to damages for loss of goodwill,\n   work stoppage, computer failure or malfunction, or any and all\n   other commercial damages or losses), even if such Contributor\n   has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n   the Work or Derivative Works thereof, You may choose to offer,\n   and charge a fee for, acceptance of support, warranty, indemnity,\n   or other liability obligations and/or rights consistent with this\n   License. However, in accepting such obligations, You may act only\n   on Your own behalf and on Your sole responsibility, not on behalf\n   of any other Contributor, and only if You agree to indemnify,\n   defend, and hold each Contributor harmless for any liability\n   incurred by, or claims asserted against, such Contributor by reason\n   of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "LICENSE-MIT",
    "content": "Copyright (c) 2023-present PyO3 Project and Contributors.  https://github.com/PyO3\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the\nSoftware without restriction, including without\nlimitation the rights to use, copy, modify, merge,\npublish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software\nis furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice\nshall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF\nANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\nTO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\nPARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\nSHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR\nIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# PyO3\n\n[![actions status](https://img.shields.io/github/actions/workflow/status/PyO3/pyo3/ci.yml?branch=main&logo=github&style=)](https://github.com/PyO3/pyo3/actions)\n[![benchmark](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://codspeed.io/PyO3/pyo3)\n[![codecov](https://img.shields.io/codecov/c/gh/PyO3/pyo3?logo=codecov)](https://codecov.io/gh/PyO3/pyo3)\n[![crates.io](https://img.shields.io/crates/v/pyo3?logo=rust)](https://crates.io/crates/pyo3)\n[![minimum rustc 1.83](https://img.shields.io/badge/rustc-1.83+-blue?logo=rust)](https://rust-lang.github.io/rfcs/2495-min-rust-version.html)\n[![discord server](https://img.shields.io/discord/1209263839632424990?logo=discord)](https://discord.gg/33kcChzH7f)\n[![contributing notes](https://img.shields.io/badge/contribute-on%20github-Green?logo=github)](https://github.com/PyO3/pyo3/blob/main/Contributing.md)\n\n[Rust](https://www.rust-lang.org/) bindings for [Python](https://www.python.org/), including tools for creating native Python extension modules. Running and interacting with Python code from a Rust binary is also supported.\n\n- User Guide: [stable](https://pyo3.rs) | [main](https://pyo3.rs/main)\n\n- API Documentation: [stable](https://docs.rs/pyo3/) | [main](https://pyo3.rs/main/doc)\n\n## Usage\n\nRequires Rust 1.83 or greater.\n\nPyO3 supports the following Python distributions:\n  - CPython 3.7 or greater\n  - PyPy 7.3 (Python 3.11+)\n  - GraalPy 25.0 or greater (Python 3.12+)\n\nYou can use PyO3 to write a native Python module in Rust, or to embed Python in a Rust binary. The following sections explain each of these in turn.\n\n### Using Rust from Python\n\nPyO3 can be used to generate a native Python module. The easiest way to try this out for the first time is to use [`maturin`](https://github.com/PyO3/maturin). `maturin` is a tool for building and publishing Rust-based Python packages with minimal configuration. The following steps install `maturin`, use it to generate and build a new Python package, and then launch Python to import and execute a function from the package.\n\nFirst, follow the commands below to create a new directory containing a new Python `virtualenv`, and install `maturin` into the virtualenv using Python's package manager, `pip`:\n\n```bash\n# (replace string_sum with the desired package name)\n$ mkdir string_sum\n$ cd string_sum\n$ python -m venv .env\n$ source .env/bin/activate\n$ pip install maturin\n```\n\nStill inside this `string_sum` directory, now run `maturin init`. This will generate the new package source. When given the choice of bindings to use, select pyo3 bindings:\n\n```bash\n$ maturin init\n✔ 🤷 What kind of bindings to use? · pyo3\n  ✨ Done! New project created string_sum\n```\n\nThe most important files generated by this command are `Cargo.toml` and `lib.rs`, which will look roughly like the following:\n\n**`Cargo.toml`**\n\n```toml\n[package]\nname = \"string_sum\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\n# The name of the native library. This is the name which will be used in Python to import the\n# library (i.e. `import string_sum`). If you change this, you must also change the name of the\n# `#[pymodule]` in `src/lib.rs`.\nname = \"string_sum\"\n# \"cdylib\" is necessary to produce a shared library for Python to import from.\n#\n# Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able\n# to `use string_sum;` unless the \"rlib\" or \"lib\" crate type is also included, e.g.:\n# crate-type = [\"cdylib\", \"rlib\"]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = \"0.28.2\"\n```\n\n**`src/lib.rs`**\n\n```rust\n/// A Python module implemented in Rust. The name of this module must match\n/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to\n/// import the module.\n#[pyo3::pymodule]\nmod string_sum {\n  use pyo3::prelude::*;\n\n  /// Formats the sum of two numbers as string.\n  #[pyfunction]\n  fn sum_as_string(a: usize, b: usize) -> PyResult<String> {\n    Ok((a + b).to_string())\n  }\n}\n```\n\nFinally, run `maturin develop`. This will build the package and install it into the Python virtualenv previously created and activated. The package is then ready to be used from `python`:\n\n```bash\n$ maturin develop\n# lots of progress output as maturin runs the compilation...\n$ python\n>>> import string_sum\n>>> string_sum.sum_as_string(5, 20)\n'25'\n```\n\nTo make changes to the package, just edit the Rust source code and then re-run `maturin develop` to recompile.\n\nTo run this all as a single copy-and-paste, use the bash script below (replace `string_sum` in the first command with the desired package name):\n\n```bash\nmkdir string_sum && cd \"$_\"\npython -m venv .env\nsource .env/bin/activate\npip install maturin\nmaturin init --bindings pyo3\nmaturin develop\n```\n\nIf you want to be able to run `cargo test` or use this project in a Cargo workspace and are running into linker issues, there are some workarounds in [the FAQ](https://pyo3.rs/latest/faq.html#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror).\n\nAs well as with `maturin`, it is possible to build using [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) or [manually](https://pyo3.rs/latest/building-and-distribution.html#manual-builds). Both offer more flexibility than `maturin` but require more configuration to get started.\n\n### Using Python from Rust\n\nTo embed Python into a Rust binary, you need to ensure that your Python installation contains a shared library. The following steps demonstrate how to ensure this (for Ubuntu), and then give some example code which runs an embedded Python interpreter.\n\nTo install the Python shared library on Ubuntu:\n\n```bash\nsudo apt install python3-dev\n```\n\nTo install the Python shared library on RPM based distributions (e.g. Fedora, Red Hat, SuSE), install the `python3-devel` package.\n\n\nStart a new project with `cargo new` and add  `pyo3` to the `Cargo.toml` like this:\n\n```toml\n[dependencies.pyo3]\nversion = \"0.28.2\"\n# Enabling this cargo feature will cause PyO3 to start a Python interpreter on first call to `Python::attach`\nfeatures = [\"auto-initialize\"]\n```\n\nExample program displaying the value of `sys.version` and the current user name:\n\n```rust\nuse pyo3::prelude::*;\nuse pyo3::types::IntoPyDict;\n\nfn main() -> PyResult<()> {\n    Python::attach(|py| {\n        let sys = py.import(\"sys\")?;\n        let version: String = sys.getattr(\"version\")?.extract()?;\n\n        let locals = [(\"os\", py.import(\"os\")?)].into_py_dict(py)?;\n        let code = c\"os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'\";\n        let user: String = py.eval(code, None, Some(&locals))?.extract()?;\n\n        println!(\"Hello {}, I'm Python {}\", user, version);\n        Ok(())\n    })\n}\n```\n\nThe guide has [a section](https://pyo3.rs/latest/python-from-rust.html) with lots of examples\nabout this topic.\n\n## Tools and libraries\n\n- [maturin](https://github.com/PyO3/maturin) _Build and publish crates with pyo3, rust-cpython or cffi bindings as well as rust binaries as python packages_\n- [setuptools-rust](https://github.com/PyO3/setuptools-rust) _Setuptools plugin for Rust support_.\n- [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://docs.rs/pyo3/*/pyo3/types/struct.PyDict.html)_\n- [rust-numpy](https://github.com/PyO3/rust-numpy) _Rust binding of NumPy C-API_\n- [dict-derive](https://github.com/gperinazzo/dict-derive) _Derive FromPyObject to automatically transform Python dicts into Rust structs_\n- [pyo3-log](https://github.com/vorner/pyo3-log) _Bridge from Rust to Python logging_\n- [pythonize](https://github.com/davidhewitt/pythonize) _Serde serializer for converting Rust objects to JSON-compatible Python objects_\n- [pyo3-async-runtimes](https://github.com/PyO3/pyo3-async-runtimes) _Utilities for interoperability with Python's Asyncio library and Rust's async runtimes._\n- [rustimport](https://github.com/mityax/rustimport) _Directly import Rust files or crates from Python, without manual compilation step. Provides pyo3 integration by default and generates pyo3 binding code automatically._\n- [pyo3-arrow](https://crates.io/crates/pyo3-arrow) _Lightweight [Apache Arrow](https://arrow.apache.org/) integration for pyo3._\n- [pyo3-bytes](https://crates.io/crates/pyo3-bytes) _Integration between [`bytes`](https://crates.io/crates/bytes) and pyo3._\n- [pyo3-object_store](https://github.com/developmentseed/obstore/tree/main/pyo3-object_store) _Integration between [`object_store`](https://docs.rs/object_store) and [`pyo3`](https://github.com/PyO3/pyo3)._\n\n## Examples\n\n- [anise](https://github.com/nyx-space/anise) _A modern, high-performance toolkit for spacecraft mission design, notably used to help softly land Firefly Blue Ghost on the Moon on 02 Feb 2025._\n- [arro3](https://github.com/kylebarron/arro3) _A minimal Python library for Apache Arrow, connecting to the Rust arrow crate._\n    - [arro3-compute](https://github.com/kylebarron/arro3/tree/main/arro3-compute) _`arro3-compute`_\n    - [arro3-core](https://github.com/kylebarron/arro3/tree/main/arro3-core) _`arro3-core`_\n    - [arro3-io](https://github.com/kylebarron/arro3/tree/main/arro3-io) _`arro3-io`_\n- [bed-reader](https://github.com/fastlmm/bed-reader) _Read and write the PLINK BED format, simply and efficiently._\n    - Shows Rayon/ndarray::parallel (including capturing errors, controlling thread num), Python types to Rust generics, Github Actions\n- [blake3-py](https://github.com/oconnor663/blake3-py) _Python bindings for the [BLAKE3](https://github.com/BLAKE3-team/BLAKE3) cryptographic hash function._\n    - Parallelized [builds](https://github.com/oconnor663/blake3-py/blob/master/.github/workflows/dists.yml) on GitHub Actions for MacOS, Linux, Windows, including free-threaded 3.13t wheels.\n- [cellular_raza](https://cellular-raza.com) _A cellular agent-based simulation framework for building complex models from a clean slate._\n- [connector-x](https://github.com/sfu-db/connector-x/tree/main/connectorx-python) _Fastest library to load data from DB to DataFrames in Rust and Python._\n- [cryptography](https://github.com/pyca/cryptography/tree/main/src/rust) _Python cryptography library with some functionality in Rust._\n- [css-inline](https://github.com/Stranger6667/css-inline/tree/master/bindings/python) _CSS inlining for Python implemented in Rust._\n- [datafusion-python](https://github.com/apache/arrow-datafusion-python) _A Python library that binds to Apache Arrow in-memory query engine DataFusion._\n- [deltalake-python](https://github.com/delta-io/delta-rs/tree/main/python) _Native Delta Lake Python binding based on delta-rs with Pandas integration._\n- [fastbloom](https://github.com/yankun1992/fastbloom) _A fast [bloom filter](https://github.com/yankun1992/fastbloom#BloomFilter) | [counting bloom filter](https://github.com/yankun1992/fastbloom#countingbloomfilter) implemented by Rust for Rust and Python!_\n- [fastuuid](https://github.com/thedrow/fastuuid/) _Python bindings to Rust's UUID library._\n- [fast-paseto](https://github.com/CodingCogs-OSS/Fast-Paseto) _High-performance PASETO (Platform-Agnostic Security Tokens) implementation with Python bindings._\n- [feos](https://github.com/feos-org/feos) _Lightning fast thermodynamic modeling in Rust with fully developed Python interface._\n- [finalytics](https://github.com/Nnamdi-sys/finalytics) _Investment Analysis library in Rust | Python._\n- [forust](https://github.com/jinlow/forust) _A lightweight gradient boosted decision tree library written in Rust._\n- [geo-index](https://github.com/kylebarron/geo-index) _A Rust crate and [Python library](https://github.com/kylebarron/geo-index/tree/main/python) for packed, immutable, zero-copy spatial indexes._\n- [granian](https://github.com/emmett-framework/granian) _A Rust HTTP server for Python applications._\n- [haem](https://github.com/BooleanCat/haem) _A Python library for working on Bioinformatics problems._\n- [hifitime](https://github.com/nyx-space/hifitime) _A high fidelity time management library for engineering and scientific applications where general relativity and time dilation matter._\n- [html2text-rs](https://github.com/deedy5/html2text_rs) _Python library for converting HTML to markup or plain text._\n- [html-py-ever](https://github.com/PyO3/setuptools-rust/tree/main/examples/html-py-ever) _Using [html5ever](https://github.com/servo/html5ever) through [kuchiki](https://github.com/kuchiki-rs/kuchiki) to speed up html parsing and css-selecting._\n- [hudi-rs](https://github.com/apache/hudi-rs) _The native Rust implementation for Apache Hudi, with C++ & Python API bindings._\n- [inline-python](https://github.com/m-ou-se/inline-python) _Inline Python code directly in your Rust code._\n- [johnnycanencrypt](https://github.com/kushaldas/johnnycanencrypt) OpenPGP library with Yubikey support.\n- [jsonschema](https://github.com/Stranger6667/jsonschema/tree/master/crates/jsonschema-py) _A high-performance JSON Schema validator for Python._\n- [mocpy](https://github.com/cds-astro/mocpy) _Astronomical Python library offering data structures for describing any arbitrary coverage regions on the unit sphere._\n- [obstore](https://github.com/developmentseed/obstore) _The simplest, highest-throughput Python interface to Amazon S3, Google Cloud Storage, Azure Storage, & other S3-compliant APIs, powered by Rust._\n- [opendal](https://github.com/apache/opendal/tree/main/bindings/python) _A data access layer that allows users to easily and efficiently retrieve data from various storage services in a unified way._\n- [orjson](https://github.com/ijl/orjson) _Fast Python JSON library._\n- [ormsgpack](https://github.com/aviramha/ormsgpack) _Fast Python msgpack library._\n- [polars](https://github.com/pola-rs/polars) _Fast multi-threaded DataFrame library in Rust | Python | Node.js._\n- [pycrdt](https://github.com/jupyter-server/pycrdt) _Python bindings for the Rust CRDT implementation [Yrs](https://github.com/y-crdt/y-crdt)._\n- [pydantic-core](https://github.com/pydantic/pydantic-core) _Core validation logic for pydantic written in Rust._\n- [primp](https://github.com/deedy5/primp) _The fastest python HTTP client that can impersonate web browsers by mimicking their headers and TLS/JA3/JA4/HTTP2 fingerprints._\n- [radiate](https://github.com/pkalivas/radiate): _A high-performance evolution engine for genetic programming and evolutionary algorithms._\n- [rateslib](https://github.com/attack68/rateslib) _A fixed income library for Python using Rust extensions._\n- [river](https://github.com/online-ml/river) _Online machine learning in python, the computationally heavy statistics algorithms are implemented in Rust._\n- [robyn](https://github.com/sparckles/Robyn) A Super Fast Async Python Web Framework with a Rust runtime.\n- [rust-python-coverage](https://github.com/cjermain/rust-python-coverage) _Example PyO3 project with automated test coverage for Rust and Python._\n- [rnet](https://github.com/0x676e67/rnet) Asynchronous Python HTTP Client with Black Magic\n- [sail](https://github.com/lakehq/sail) _Unifying stream, batch, and AI workloads with Apache Spark compatibility._\n- [tiktoken](https://github.com/openai/tiktoken) _A fast BPE tokeniser for use with OpenAI's models._\n- [tokenizers](https://github.com/huggingface/tokenizers/tree/main/bindings/python) _Python bindings to the Hugging Face tokenizers (NLP) written in Rust._\n- [tzfpy](http://github.com/ringsaturn/tzfpy) _A fast package to convert longitude/latitude to timezone name._\n- [toml-rs](https://github.com/lava-sh/toml-rs) _A High-Performance TOML v1.0.0 and v1.1.0 parser for Python written in Rust._\n- [utiles](https://github.com/jessekrubin/utiles) _Fast Python web-map tile utilities_\n\n## Articles and other media\n\n- [(Video) Using Rust in Free-Threaded vs Regular Python 3.13](https://www.youtube.com/watch?v=J7phN_M4GLM) - Jun 4, 2025\n- [(Video) Techniques learned from five years finding the way for Rust in Python](https://www.youtube.com/watch?v=KTQn_PTHNCw) - Feb 26, 2025\n- [(Podcast) Bridging Python and Rust: An Interview with PyO3 Maintainer David Hewitt](https://www.youtube.com/watch?v=P47JUMSQagU) - Aug 30, 2024\n- [(Video) PyO3: From Python to Rust and Back Again](https://www.youtube.com/watch?v=UmL_CA-v3O8) - Jul 3, 2024\n- [Parsing Python ASTs 20x Faster with Rust](https://www.gauge.sh/blog/parsing-python-asts-20x-faster-with-rust) - Jun 17, 2024\n- [(Video) How Python Harnesses Rust through PyO3](https://www.youtube.com/watch?v=UilujdubqVU) - May 18, 2024\n- [(Video) Combining Rust and Python: The Best of Both Worlds?](https://www.youtube.com/watch?v=lyG6AKzu4ew) - Mar 1, 2024\n- [(Video) Extending Python with Rust using PyO3](https://www.youtube.com/watch?v=T45ZEmSR1-s) - Dec 16, 2023\n- [A Week of PyO3 + rust-numpy (How to Speed Up Your Data Pipeline X Times)](https://terencezl.github.io/blog/2023/06/06/a-week-of-pyo3-rust-numpy/) - Jun 6, 2023\n- [(Podcast) PyO3 with David Hewitt](https://rustacean-station.org/episode/david-hewitt/) - May 19, 2023\n- [Making Python 100x faster with less than 100 lines of Rust](https://ohadravid.github.io/posts/2023-03-rusty-python/) - Mar 28, 2023\n- [How Pydantic V2 leverages Rust's Superpowers](https://fosdem.org/2023/schedule/event/rust_how_pydantic_v2_leverages_rusts_superpowers/) - Feb 4, 2023\n- [How we extended the River stats module with Rust using PyO3](https://boring-guy.sh/posts/river-rust/) - Dec 23, 2022\n- [Nine Rules for Writing Python Extensions in Rust](https://towardsdatascience.com/nine-rules-for-writing-python-extensions-in-rust-d35ea3a4ec29?sk=f8d808d5f414154fdb811e4137011437) - Dec 31, 2021\n- [Calling Rust from Python using PyO3](https://saidvandeklundert.net/learn/2021-11-18-calling-rust-from-python-using-pyo3/) - Nov 18, 2021\n- [davidhewitt's 2021 talk at Rust Manchester meetup](https://www.youtube.com/watch?v=-XyWG_klSAw&t=320s) - Aug 19, 2021\n- [Incrementally porting a small Python project to Rust](https://blog.waleedkhan.name/port-python-to-rust/) - Apr 29, 2021\n- [Vortexa - Integrating Rust into Python](https://www.vortexa.com/blog/integrating-rust-into-python) - Apr 12, 2021\n- [Writing and publishing a Python module in Rust](https://blog.yossarian.net/2020/08/02/Writing-and-publishing-a-python-module-in-rust) - Aug 2, 2020\n\n## Contributing\n\nEveryone is welcomed to contribute to PyO3! There are many ways to support the project, such as:\n\n- help PyO3 users with issues on GitHub and [Discord](https://discord.gg/33kcChzH7f)\n- improve documentation\n- write features and bugfixes\n- publish blogs and examples of how to use PyO3\n\nOur [contributing notes](https://github.com/PyO3/pyo3/blob/main/Contributing.md) and [architecture guide](https://github.com/PyO3/pyo3/blob/main/Architecture.md) have more resources if you wish to volunteer time for PyO3 and are searching where to start.\n\nIf you don't have time to contribute yourself but still wish to support the project's future success, some of our maintainers have GitHub sponsorship pages:\n\n- [davidhewitt](https://github.com/sponsors/davidhewitt)\n- [messense](https://github.com/sponsors/messense)\n\n## License\n\nPyO3 is licensed under the [Apache-2.0 license](LICENSE-APACHE) or the [MIT license](LICENSE-MIT), at your option.\n\nPython is licensed under the [Python License](https://docs.python.org/3/license.html).\n\nUnless you explicitly state otherwise, any contribution intentionally submitted for inclusion in PyO3 by you, as defined in the Apache License, shall be dual-licensed as above, without any additional terms or conditions.\n\n<a href=\"https://www.netlify.com\"> <img src=\"https://www.netlify.com/v3/img/components/netlify-color-accent.svg\" alt=\"Deploys by Netlify\" /> </a>\n"
  },
  {
    "path": "Releasing.md",
    "content": "# Releasing\n\nThis is notes for the current process of releasing a new PyO3 version. Replace `<version>` in all instructions below with the new version.\n\n## 1. Prepare the release commit\n\nFollow the process below to update all required pieces to bump the version. All these changes are done in a single commit because it makes it clear to git readers what happened to bump the version. It also makes it easy to cherry-pick the version bump onto the `main` branch when tidying up branch history at the end of the release process.\n\n1. Replace all instances of the PyO3 current version and the with the new version to be released. Places to check:\n   - `Cargo.toml` for all PyO3 crates in the repository.\n   - Examples in `README.md`\n   - PyO3 version embedded into documentation like the README.\n   - `pre-script.rhai` templates for the examples.\n   - `[towncrier]` section in `pyproject.toml`.\n\n   Some of the above locations may already have the new version with a `-dev` suffix, which needs to be removed.\n\n   **Make sure not to modify the CHANGELOG during this step!**\n\n2. Run `towncrier build` to generate the CHANGELOG. The version used by `towncrier` should automatically be correct because of the update to `pyproject.toml` in step 1.\n\n3. Manually edit the CHANGELOG for final notes. Steps to do:\n   - Adjust wording of any release lines to make them clearer for users / fix typos.\n   - Add a new link at the bottom for the new version, and update the `Unreleased` link.\n\n4. Create the commit containing all the above changes, with a message of `release: <version>`. Push to `release-<BRANCH_VER>` branch on the main PyO3 repository, where `<BRANCH_VER>` depends on whether this is a major or minor release:\n   - for O.X.0 minor releases, just use `0.X`, e.g. `release-0.17`. This will become the maintenance branch after release.\n   - for 0.X.Y patch releases, use the full `0.X.Y`, e.g. `release-0.17.1`. This will be deleted after merge.\n\n## 2. Create the release PR and draft release notes\n\nOpen a PR for the branch, and confirm that it passes CI. For `0.X.0` minor releases, the PR should be merging into `main`, for `0.X.Y` patch releases, the PR should be merging the `release-0.X` maintenance branch.\n\nOn https://github.com/PyO3/pyo3/releases, click \"Draft a new release\". The tag will be a new tag of `v<version>` (note preceding `v`) and target should be the `release-<BRANCH_VER>` branch you just pushed.\n\nWrite release notes which match the style of previous releases. You can get the list of contributors by running `nox -s contributors -- v<prev-version> release-<BRANCH_VER>` to get contributors from the previous version tag through to the branch tip you just pushed. (This uses the GitHub API, so you'll need to push the branch first.)\n\nSave as a draft and wait for now.\n\n## 3. Leave for a cooling off period\n\nWait a couple of days in case anyone wants to hold up the release to add bugfixes etc.\n\n## 4. Put live\n\nTo put live:\n- 1. merge the release PR\n- 2. publish a release on GitHub targeting the release branch\n\nCI will automatically push to `crates.io`.\n\n## 5. Tidy the main branch\n\nIf the release PR targeted a branch other than main, you will need to cherry-pick the version bumps, CHANGELOG modifications and removal of towncrier `newsfragments` and open another PR to land these on main.\n\n## 6. Delete the release branch (patch releases only)\n\nFor 0.X.Y patch releases, the release branch is no longer needed, so it should be deleted.\n"
  },
  {
    "path": "assets/script.py",
    "content": "# Used in PyModule examples.\n\n\nclass Blah:\n    pass\n"
  },
  {
    "path": "build.rs",
    "content": "use std::env;\n\nuse pyo3_build_config::pyo3_build_script_impl::{cargo_env_var, errors::Result};\nuse pyo3_build_config::{\n    add_python_framework_link_args, bail, print_feature_cfgs, InterpreterConfig,\n};\n\nfn ensure_auto_initialize_ok(interpreter_config: &InterpreterConfig) -> Result<()> {\n    if cargo_env_var(\"CARGO_FEATURE_AUTO_INITIALIZE\").is_some() && !interpreter_config.shared {\n        bail!(\n            \"The `auto-initialize` feature is enabled, but your python installation only supports \\\n            embedding the Python interpreter statically. If you are attempting to run tests, or a \\\n            binary which is okay to link dynamically, install a Python distribution which ships \\\n            with the Python shared library.\\n\\\n            \\n\\\n            Embedding the Python interpreter statically does not yet have first-class support in \\\n            PyO3. If you are sure you intend to do this, disable the `auto-initialize` feature.\\n\\\n            \\n\\\n            For more information, see \\\n            https://pyo3.rs/v{pyo3_version}/\\\n                building-and-distribution.html#embedding-python-in-rust\",\n            pyo3_version = env::var(\"CARGO_PKG_VERSION\").unwrap()\n        );\n    }\n    Ok(())\n}\n\n/// Prepares the PyO3 crate for compilation.\n///\n/// This loads the config from pyo3-build-config and then makes some additional checks to improve UX\n/// for users.\n///\n/// Emits the cargo configuration based on this config as well as a few checks of the Rust compiler\n/// version to enable features which aren't supported on MSRV.\nfn configure_pyo3() -> Result<()> {\n    let interpreter_config = pyo3_build_config::get();\n\n    ensure_auto_initialize_ok(interpreter_config)?;\n\n    for cfg in interpreter_config.build_script_outputs() {\n        println!(\"{cfg}\")\n    }\n\n    print_feature_cfgs();\n\n    // Make `cargo test` etc work on macOS with Xcode bundled Python\n    add_python_framework_link_args();\n\n    Ok(())\n}\n\nfn main() {\n    pyo3_build_config::print_expected_cfgs();\n    if let Err(e) = configure_pyo3() {\n        eprintln!(\"error: {}\", e.report());\n        std::process::exit(1)\n    }\n}\n"
  },
  {
    "path": "codecov.yml",
    "content": "comment: off\n\ncoverage:\n  status:\n    project:\n      default:\n        target: auto\n        # Allow a tiny drop of overall project coverage in PR due to\n        # not all configurations being tested in PR runs.\n        #\n        # (Note that patch coverage will still be required to be at least\n        # the project coverage.)\n        threshold: 1%\n\nignore:\n  - tests/\n  - pytests/\n  - src/test_hygiene/*.rs\n"
  },
  {
    "path": "emscripten/.gitignore",
    "content": "pybuilddir.txt\nbuilddir\n"
  },
  {
    "path": "emscripten/Makefile",
    "content": "CURDIR=$(abspath .)\n\n# These three are passed in from nox.\nBUILDROOT ?= $(CURDIR)/builddir\nPYTHON ?= python3\nPYMAJORMINORMICRO ?= $(shell $(PYTHON) --version 2>&1 | awk '{print $$2}')\n\nexport EMSDKDIR = $(PYTHONBUILD)/emsdk-cache\n\nPLATFORM=wasm32_emscripten\nSYSCONFIGDATA_NAME=_sysconfigdata__$(PLATFORM)\n\n# Set version variables.\nversion_tuple := $(subst ., ,$(PYMAJORMINORMICRO:v%=%))\nPYMAJOR=$(word 1,$(version_tuple))\nPYMINOR=$(word 2,$(version_tuple))\nPYMICRO=$(word 3,$(version_tuple))\nPYVERSION=$(PYMAJORMINORMICRO)\nPYMAJORMINOR=$(PYMAJOR).$(PYMINOR)\n\n\nPYTHONURL=https://www.python.org/ftp/python/$(PYMAJORMINORMICRO)/Python-$(PYVERSION).tgz\n# TODO: resume download once 3.14.4 ships with emscripten cache\n# PYTHONTARBALL=$(BUILDROOT)/downloads/Python-$(PYVERSION).tgz\n# PYTHONBUILD=$(BUILDROOT)/build/Python-$(PYVERSION)\nPYTHONBUILD=$(BUILDROOT)/build/cpython\n\nPYTHONLIBDIR=$(BUILDROOT)/install/Python-$(PYVERSION)/lib\n\nCROSS_PYTHON=$(PYTHONBUILD)/cross-build/wasm32-emscripten/build/python/python.sh\n\nall: $(PYTHONLIBDIR)/libpython$(PYMAJORMINOR).a\n\n$(BUILDROOT)/.exists:\n\tmkdir -p $(BUILDROOT)\n\ttouch $@\n\n# TODO: use tarball once 3.14.4 ships with emscripten cache\n\n# $(PYTHONTARBALL):\n# \t[ -d $(BUILDROOT)/downloads ] || mkdir -p $(BUILDROOT)/downloads\n# \twget -q -O $@ $(PYTHONURL)\n\n# $(PYTHONBUILD)/.patched: $(PYTHONTARBALL)\n# \t[ -d $(PYTHONBUILD) ] || ( \\\n# \t\tmkdir -p $(dir $(PYTHONBUILD));\\\n# \t\ttar -C $(dir $(PYTHONBUILD)) -xf $(PYTHONTARBALL) \\\n# \t)\n# \ttouch $@\n\nifneq ($(PYMAJORMINOR),3.14)\n$(error PYMAJORMINOR must be 3.14, got '$(PYMAJORMINOR)')\nendif\n\n$(PYTHONBUILD)/.patched: $(BUILDROOT)/.exists\n\t[ -d $(PYTHONBUILD) ] || ( \\\n\t\tmkdir -p $(dir $(PYTHONBUILD));\\\n\t\tgit clone --depth 1 --branch 3.14 https://github.com/python/cpython $(PYTHONBUILD) \\\n\t)\n\ttouch $@\n\n$(CROSS_PYTHON): $(PYTHONBUILD)/.patched\n\tcd $(PYTHONBUILD) && \\\n\t$(PYTHON) Tools/wasm/emscripten install-emscripten --quiet --emsdk-cache=$(EMSDKDIR) && \\\n\t$(PYTHON) Tools/wasm/emscripten build --quiet --emsdk-cache=$(EMSDKDIR)\n\n$(PYTHONLIBDIR)/libpython$(PYMAJORMINOR).a: $(CROSS_PYTHON)\n\t# Generate sysconfigdata\n\t_PYTHON_SYSCONFIGDATA_NAME=$(SYSCONFIGDATA_NAME) _PYTHON_PROJECT_BASE=$(PYTHONBUILD)/cross-build/wasm32-emscripten/build/python $(CROSS_PYTHON) -m sysconfig --generate-posix-vars\n\tcp `cat pybuilddir.txt`/$(SYSCONFIGDATA_NAME).py $(PYTHONBUILD)/Lib\n\n\tmkdir -p $(PYTHONLIBDIR)\n\t# Make a static library for _hacl, for some reason these are missing from the build?\n\t# source emsdk_env.sh to get emar in PATH, works best when done from the emsdk directory\n\tEMSDK_ENV=$$(find $(PYTHONBUILD)/emsdk-cache -name 'emsdk_env.sh' | head -n 1) && \\\n\t    cd $$(dirname $$EMSDK_ENV) && \\\n\t\t. $$EMSDK_ENV && \\\n\t    cd $(PYTHONBUILD)/cross-build/wasm32-emscripten/build/python && \\\n\t\temar rcs Modules/_hacl/libhacl.a Modules/_hacl/*.o\n\t# Copy all .a libraries\n\tfind $(PYTHONBUILD)/cross-build/wasm32-emscripten/ -name '*.a' -exec cp {} $(PYTHONLIBDIR) \\;\n\t# Install Python stdlib\n\tcp -r $(PYTHONBUILD)/Lib $(PYTHONLIBDIR)/python$(PYMAJORMINOR)\nclean:\n\trm -rf $(BUILDROOT)\n"
  },
  {
    "path": "emscripten/runner.py",
    "content": "#!/usr/local/bin/python\nimport pathlib\nimport sys\nimport subprocess\n\np = pathlib.Path(sys.argv[1])\n\ncommand = [\"node\", p.name, *sys.argv[2:]]\nprint(\"Running:\", \" \".join(command))\n\nsys.exit(subprocess.call(command, cwd=p.parent))\n"
  },
  {
    "path": "examples/Cargo.toml",
    "content": "[package]\nname = \"pyo3-examples\"\nversion = \"0.0.0\"\npublish = false\nedition = \"2021\"\nrust-version = \"1.83\"\n\n[dev-dependencies]\npyo3 = { path = \"..\", features = [\"auto-initialize\"] }\n\n[[example]]\nname = \"decorator\"\npath = \"decorator/src/lib.rs\"\ncrate-type = [\"cdylib\"]\ndoc-scrape-examples = true\n"
  },
  {
    "path": "examples/README.md",
    "content": "# PyO3 Examples\n\nThese example crates are a collection of toy extension modules built with PyO3. They are all tested using `nox` in PyO3's CI.\n\nBelow is a brief description of each of these:\n\n| Example | Description |\n| ------- | ----------- |\n| `decorator` | A project showcasing the example from the [Emulating callable objects](https://pyo3.rs/latest/class/call.html) chapter of the guide. |\n| `maturin-starter` | A template project which is configured to use [`maturin`](https://github.com/PyO3/maturin) for development. |\n| `setuptools-rust-starter` | A template project which is configured to use [`setuptools_rust`](https://github.com/PyO3/setuptools-rust/) for development. |\n| `plugin` | Illustrates how to use Python as a scripting language within a Rust application |\n\nNote that there are also other examples in the `pyo3-ffi/examples`\ndirectory that illustrate how to create rust extensions using raw FFI calls into\nthe CPython C API instead of using PyO3's abstractions.\n\n## Creating new projects from these examples\n\nTo copy an example, use [`cargo-generate`](https://crates.io/crates/cargo-generate). Follow the commands below, replacing `<example>` with the example to start from:\n\n```bash\n$ cargo install cargo-generate\n$ cargo generate --git https://github.com/PyO3/pyo3 examples/<example>\n```\n\n(`cargo generate` will take a little while to clone the PyO3 repo first; be patient when waiting for the command to run.)\n"
  },
  {
    "path": "examples/decorator/.template/Cargo.toml",
    "content": "[package]\nauthors = [\"{{authors}}\"]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\nname = \"decorator\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = \"{{PYO3_VERSION}}\"\n"
  },
  {
    "path": "examples/decorator/.template/pre-script.rhai",
    "content": "variable::set(\"PYO3_VERSION\", \"0.28.2\");\nfile::rename(\".template/Cargo.toml\", \"Cargo.toml\");\nfile::rename(\".template/pyproject.toml\", \"pyproject.toml\");\nfile::delete(\".template\");\n"
  },
  {
    "path": "examples/decorator/.template/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n"
  },
  {
    "path": "examples/decorator/Cargo.toml",
    "content": "[package]\nname = \"decorator\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.83\"\n\n[lib]\nname = \"decorator\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = { path = \"../../\" }\n\n[workspace]\n"
  },
  {
    "path": "examples/decorator/MANIFEST.in",
    "content": "include pyproject.toml Cargo.toml\nrecursive-include src *\n"
  },
  {
    "path": "examples/decorator/README.md",
    "content": "# decorator\n\nA project showcasing the example from the [Emulating callable objects](https://pyo3.rs/latest/class/call.html) chapter of the guide.\n\n## Building and Testing\n\nTo build this package, first install `maturin`:\n\n```shell\npip install maturin\n```\n\nTo build and test use `maturin develop`:\n\n```shell\npip install -r requirements-dev.txt\nmaturin develop\npytest\n```\n\nAlternatively, install nox and run the tests inside an isolated environment:\n\n```shell\nnox\n```\n\n## Copying this example\n\nUse [`cargo-generate`](https://crates.io/crates/cargo-generate):\n\n```bash\n$ cargo install cargo-generate\n$ cargo generate --git https://github.com/PyO3/pyo3 examples/decorator\n```\n\n(`cargo generate` will take a little while to clone the PyO3 repo first; be patient when waiting for the command to run.)\n"
  },
  {
    "path": "examples/decorator/cargo-generate.toml",
    "content": "[template]\nignore = [\".nox\"]\n\n[hooks]\npre = [\".template/pre-script.rhai\"]\n"
  },
  {
    "path": "examples/decorator/noxfile.py",
    "content": "import nox\n\n\n@nox.session\ndef python(session: nox.Session):\n    session.env[\"MATURIN_PEP517_ARGS\"] = \"--profile=dev\"\n    session.install(\".[dev]\")\n    session.run(\"pytest\")\n"
  },
  {
    "path": "examples/decorator/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"decorator\"\nversion = \"0.1.0\"\nclassifiers = [\n    \"License :: OSI Approved :: MIT License\",\n    \"Development Status :: 3 - Alpha\",\n    \"Intended Audience :: Developers\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Rust\",\n    \"Operating System :: POSIX\",\n    \"Operating System :: MacOS :: MacOS X\",\n]\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n"
  },
  {
    "path": "examples/decorator/src/lib.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::{PyDict, PyTuple};\nuse std::sync::atomic::{AtomicU64, Ordering};\n\n/// A function decorator that keeps track how often it is called.\n///\n/// It otherwise doesn't do anything special.\n#[pyclass(name = \"Counter\")]\npub struct PyCounter {\n    // Keeps track of how many calls have gone through.\n    //\n    // See the discussion at the end for why `AtomicU64` is used.\n    count: AtomicU64,\n\n    // This is the actual function being wrapped.\n    wraps: Py<PyAny>,\n}\n\n#[pymethods]\nimpl PyCounter {\n    // Note that we don't validate whether `wraps` is actually callable.\n    //\n    // While we could use `PyAny::is_callable` for that, it has some flaws:\n    //    1. It doesn't guarantee the object can actually be called successfully\n    //    2. We still need to handle any exceptions that the function might raise\n    #[new]\n    fn __new__(wraps: Py<PyAny>) -> Self {\n        PyCounter {\n            count: AtomicU64::new(0),\n            wraps,\n        }\n    }\n\n    #[getter]\n    fn count(&self) -> u64 {\n        self.count.load(Ordering::Relaxed)\n    }\n\n    #[pyo3(signature = (*args, **kwargs))]\n    fn __call__(\n        &self,\n        py: Python<'_>,\n        args: &Bound<'_, PyTuple>,\n        kwargs: Option<&Bound<'_, PyDict>>,\n    ) -> PyResult<Py<PyAny>> {\n        let new_count = self.count.fetch_add(1, Ordering::Relaxed);\n        let name = self.wraps.getattr(py, \"__name__\")?;\n\n        println!(\"{name} has been called {new_count} time(s).\");\n\n        // After doing something, we finally forward the call to the wrapped function\n        let ret = self.wraps.call(py, args, kwargs)?;\n\n        // We could do something with the return value of\n        // the function before returning it\n        Ok(ret)\n    }\n}\n\n#[pymodule]\npub fn decorator(module: &Bound<'_, PyModule>) -> PyResult<()> {\n    module.add_class::<PyCounter>()?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/decorator/tests/example.py",
    "content": "from decorator import Counter\n\n\n@Counter\ndef say_hello():\n    print(\"hello\")\n\n\nsay_hello()\nsay_hello()\nsay_hello()\nsay_hello()\n\nassert say_hello.count == 4\n"
  },
  {
    "path": "examples/decorator/tests/test_.py",
    "content": "from decorator import Counter\n\n\ndef test_no_args():\n    @Counter\n    def say_hello():\n        print(\"hello\")\n\n    say_hello()\n    say_hello()\n    say_hello()\n    say_hello()\n\n    assert say_hello.count == 4\n\n\ndef test_arg():\n    @Counter\n    def say_hello(name):\n        print(f\"hello {name}\")\n\n    say_hello(\"a\")\n    say_hello(\"b\")\n    say_hello(\"c\")\n    say_hello(\"d\")\n\n    assert say_hello.count == 4\n\n\ndef test_default_arg():\n    @Counter\n    def say_hello(name=\"default\"):\n        print(f\"hello {name}\")\n\n    say_hello(\"a\")\n    say_hello()\n    say_hello(\"c\")\n    say_hello()\n\n    assert say_hello.count == 4\n\n\n# https://github.com/PyO3/pyo3/discussions/2598\ndef test_discussion_2598():\n    @Counter\n    def say_hello():\n        if say_hello.count < 2:\n            print(\"hello from decorator\")\n\n    say_hello()\n    say_hello()\n"
  },
  {
    "path": "examples/getitem/.template/Cargo.toml",
    "content": "[package]\nauthors = [\"{{authors}}\"]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\nname = \"getitem\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = \"{{PYO3_VERSION}}\"\n"
  },
  {
    "path": "examples/getitem/.template/pre-script.rhai",
    "content": "variable::set(\"PYO3_VERSION\", \"0.19.0\");\nfile::rename(\".template/Cargo.toml\", \"Cargo.toml\");\nfile::rename(\".template/pyproject.toml\", \"pyproject.toml\");\nfile::delete(\".template\");\n"
  },
  {
    "path": "examples/getitem/.template/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n"
  },
  {
    "path": "examples/getitem/Cargo.toml",
    "content": "[package]\nname = \"getitem\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.83\"\n\n[lib]\nname = \"getitem\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = { path = \"../../\" }\n\n[workspace]\n"
  },
  {
    "path": "examples/getitem/MANIFEST.in",
    "content": "include pyproject.toml Cargo.toml\nrecursive-include src *\n"
  },
  {
    "path": "examples/getitem/README.md",
    "content": "# getitem\n\nA project showcasing how to create a `__getitem__` override that also showcases how to deal with multiple incoming types\n\n## Relevant Documentation\n\nSome of the relevant documentation links for this example:\n\n* Converting Slices to Indices: https://docs.rs/pyo3/latest/pyo3/types/struct.PySlice.html#method.indices\n* GetItem Docs: https://pyo3.rs/latest/class/protocols.html?highlight=__getitem__#mapping--sequence-types\n* Extract: https://pyo3.rs/latest/conversions/traits.html?highlight=extract#extract-and-the-frompyobject-trait\n* Downcast and getattr: https://pyo3.rs/v0.19.0/types.html?highlight=getattr#pyany\n\n\n## Building and Testing\n\nTo build this package, first install `maturin`:\n\n```shell\npip install maturin\n```\n\nTo build and test use `maturin develop`:\n\n```shell\npip install -r requirements-dev.txt\nmaturin develop\npytest\n```\n\nAlternatively, install nox and run the tests inside an isolated environment:\n\n```shell\nnox\n```\n\n## Copying this example\n\nUse [`cargo-generate`](https://crates.io/crates/cargo-generate):\n\n```bash\n$ cargo install cargo-generate\n$ cargo generate --git https://github.com/PyO3/pyo3 examples/decorator\n```\n\n(`cargo generate` will take a little while to clone the PyO3 repo first; be patient when waiting for the command to run.)\n"
  },
  {
    "path": "examples/getitem/cargo-generate.toml",
    "content": "[template]\nignore = [\".nox\"]\n\n[hooks]\npre = [\".template/pre-script.rhai\"]\n"
  },
  {
    "path": "examples/getitem/noxfile.py",
    "content": "import nox\n\n\n@nox.session\ndef python(session: nox.Session):\n    session.env[\"MATURIN_PEP517_ARGS\"] = \"--profile=dev\"\n    session.install(\".[dev]\")\n    session.run(\"pytest\")\n"
  },
  {
    "path": "examples/getitem/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"getitem\"\nversion = \"0.1.0\"\nclassifiers = [\n    \"License :: OSI Approved :: MIT License\",\n    \"Development Status :: 3 - Alpha\",\n    \"Intended Audience :: Developers\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Rust\",\n    \"Operating System :: POSIX\",\n    \"Operating System :: MacOS :: MacOS X\",\n]\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n"
  },
  {
    "path": "examples/getitem/src/lib.rs",
    "content": "// This is a very fake example of how to check __getitem__ parameter and handle appropriately\nuse pyo3::exceptions::PyTypeError;\nuse pyo3::prelude::*;\nuse pyo3::types::PySlice;\n\n#[derive(FromPyObject)]\nenum IntOrSlice<'py> {\n    Int(i32),\n    Slice(Bound<'py, PySlice>),\n}\n\n#[pyclass]\nstruct ExampleContainer {\n    // represent the maximum length our container is pretending to be\n    max_length: i32,\n}\n\n#[pymethods]\nimpl ExampleContainer {\n    #[new]\n    fn new() -> Self {\n        ExampleContainer { max_length: 100 }\n    }\n\n    fn __getitem__(&self, key: &Bound<'_, PyAny>) -> PyResult<i32> {\n        if let Ok(position) = key.extract::<i32>() {\n            return Ok(position);\n        } else if let Ok(slice) = key.cast::<PySlice>() {\n            // METHOD 1 - the use PySliceIndices to help with bounds checking and for cases when only start or end are provided\n            // in this case the start/stop/step all filled in to give valid values based on the max_length given\n            let index = slice.indices(self.max_length as isize).unwrap();\n            let _delta = index.stop - index.start;\n\n            // METHOD 2 - Do the getattr manually really only needed if you have some special cases for stop/_step not being present\n            // convert to indices and this will help you deal with stop being the max length\n            let start: i32 = slice.getattr(\"start\")?.extract()?;\n            // This particular example assumes stop is present, but note that if not present, this will cause us to return due to the\n            // extract failing. Not needing custom code to deal with this is a good reason to use the Indices method.\n            let stop: i32 = slice.getattr(\"stop\")?.extract()?;\n            // example of grabbing step since it is not always present\n            let _step: i32 = match slice.getattr(\"step\")?.extract() {\n                // if no value found assume step is 1\n                Ok(v) => v,\n                Err(_) => 1 as i32,\n            };\n\n            // Use something like this if you don't support negative stepping and want to give users\n            // leeway on how they provide their ordering\n            let (start, stop) = if start > stop {\n                (stop, start)\n            } else {\n                (start, stop)\n            };\n            let delta = stop - start;\n\n            return Ok(delta);\n        } else {\n            return Err(PyTypeError::new_err(\"Unsupported type\"));\n        }\n    }\n    fn __setitem__(&self, idx: IntOrSlice, value: u32) -> PyResult<()> {\n        match idx {\n            IntOrSlice::Slice(slice) => {\n                let index = slice.indices(self.max_length as isize).unwrap();\n                println!(\n                    \"Got a slice! {}-{}, step: {}, value: {}\",\n                    index.start, index.stop, index.step, value\n                );\n            }\n            IntOrSlice::Int(index) => {\n                println!(\"Got an index! {} : value: {}\", index, value);\n            }\n        }\n        Ok(())\n    }\n}\n\n#[pymodule(name = \"getitem\")]\nfn example(m: &Bound<'_, PyModule>) -> PyResult<()> {\n    // ? -https://github.com/PyO3/maturin/issues/475\n    m.add_class::<ExampleContainer>()?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/getitem/tests/test_getitem.py",
    "content": "import getitem\nimport pytest\n\n\ndef test_simple():\n    container = getitem.ExampleContainer()\n    assert container[3] == 3\n    assert container[4] == 4\n    assert container[-1] == -1\n    assert container[5:3] == 2\n    assert container[3:5] == 2\n    # test setitem, but this just displays, no return to check\n    container[3:5] = 2\n    container[2] = 2\n    # and note we will get an error on this one since we didn't\n    # add strings\n    with pytest.raises(TypeError):\n        container[\"foo\"] = 2\n"
  },
  {
    "path": "examples/maturin-starter/.template/Cargo.toml",
    "content": "[package]\nauthors = [\"{{authors}}\"]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\nname = \"maturin_starter\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = \"{{PYO3_VERSION}}\"\n"
  },
  {
    "path": "examples/maturin-starter/.template/pre-script.rhai",
    "content": "variable::set(\"PYO3_VERSION\", \"0.28.2\");\nfile::rename(\".template/Cargo.toml\", \"Cargo.toml\");\nfile::rename(\".template/pyproject.toml\", \"pyproject.toml\");\nfile::delete(\".template\");\n"
  },
  {
    "path": "examples/maturin-starter/.template/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n"
  },
  {
    "path": "examples/maturin-starter/Cargo.toml",
    "content": "[package]\nname = \"maturin-starter\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.83\"\n\n[lib]\nname = \"maturin_starter\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = { path = \"../../\" }\n\n[features]\nabi3 = [\"pyo3/abi3-py37\"]\n\n[workspace]\n"
  },
  {
    "path": "examples/maturin-starter/MANIFEST.in",
    "content": "include pyproject.toml Cargo.toml\nrecursive-include src *\n"
  },
  {
    "path": "examples/maturin-starter/README.md",
    "content": "# maturin-starter\n\nAn example of a basic Python extension module built using PyO3 and [`maturin`](https://github.com/PyO3/maturin).\n\n## Building and Testing\n\nTo build this package, first install `maturin`:\n\n```shell\npip install maturin\n```\n\nTo build and test use `maturin develop`:\n\n```shell\npip install -r requirements-dev.txt\nmaturin develop && pytest\n```\n\nAlternatively, install nox and run the tests inside an isolated environment:\n\n```shell\nnox\n```\n\n## Copying this example\n\nUse [`cargo-generate`](https://crates.io/crates/cargo-generate):\n\n```bash\n$ cargo install cargo-generate\n$ cargo generate --git https://github.com/PyO3/pyo3 examples/maturin-starter\n```\n\n(`cargo generate` will take a little while to clone the PyO3 repo first; be patient when waiting for the command to run.)\n"
  },
  {
    "path": "examples/maturin-starter/cargo-generate.toml",
    "content": "[template]\nignore = [\".nox\"]\n\n[hooks]\npre = [\".template/pre-script.rhai\"]\n"
  },
  {
    "path": "examples/maturin-starter/maturin_starter/__init__.py",
    "content": "# import the contents of the Rust library into the Python extension\nfrom .maturin_starter import *\nfrom .maturin_starter import __all__\n\n# optional: include the documentation from the Rust module\nfrom .maturin_starter import __doc__  # noqa: F401\n\n__all__ = __all__ + [\"PythonClass\"]\n\n\nclass PythonClass:\n    def __init__(self, value: int) -> None:\n        self.value = value\n"
  },
  {
    "path": "examples/maturin-starter/noxfile.py",
    "content": "import nox\n\n\n@nox.session\ndef python(session):\n    session.env[\"MATURIN_PEP517_ARGS\"] = \"--profile=dev\"\n    session.install(\".[dev]\")\n    session.run(\"pytest\")\n"
  },
  {
    "path": "examples/maturin-starter/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"maturin-starter\"\nversion = \"0.1.0\"\nclassifiers = [\n    \"License :: OSI Approved :: MIT License\",\n    \"Development Status :: 3 - Alpha\",\n    \"Intended Audience :: Developers\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Rust\",\n    \"Operating System :: POSIX\",\n    \"Operating System :: MacOS :: MacOS X\",\n]\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n"
  },
  {
    "path": "examples/maturin-starter/src/lib.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::PyDict;\nuse pyo3::wrap_pymodule;\n\nmod submodule;\n\n#[pyclass]\nstruct ExampleClass {\n    #[pyo3(get, set)]\n    value: i32,\n}\n\n#[pymethods]\nimpl ExampleClass {\n    #[new]\n    pub fn new(value: i32) -> Self {\n        ExampleClass { value }\n    }\n}\n\n/// An example module implemented in Rust using PyO3.\n#[pymodule]\nfn maturin_starter(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {\n    m.add_class::<ExampleClass>()?;\n    m.add_wrapped(wrap_pymodule!(submodule::submodule))?;\n\n    // Inserting to sys.modules allows importing submodules nicely from Python\n    // e.g. from maturin_starter.submodule import SubmoduleClass\n\n    let sys = PyModule::import(py, \"sys\")?;\n    let sys_modules: Bound<'_, PyDict> = sys.getattr(\"modules\")?.cast_into()?;\n    sys_modules.set_item(\"maturin_starter.submodule\", m.getattr(\"submodule\")?)?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "examples/maturin-starter/src/submodule.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass]\nstruct SubmoduleClass {}\n\n#[pymethods]\nimpl SubmoduleClass {\n    #[new]\n    pub fn __new__() -> Self {\n        SubmoduleClass {}\n    }\n\n    pub fn greeting(&self) -> &'static str {\n        \"Hello, world!\"\n    }\n}\n\n#[pymodule]\npub fn submodule(m: &Bound<'_, PyModule>) -> PyResult<()> {\n    m.add_class::<SubmoduleClass>()?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/maturin-starter/tests/test_maturin_starter.py",
    "content": "from maturin_starter import ExampleClass, PythonClass\n\n\ndef test_python_class() -> None:\n    py_class = PythonClass(value=10)\n    assert py_class.value == 10\n\n\ndef test_example_class() -> None:\n    example = ExampleClass(value=11)\n    assert example.value == 11\n\n\ndef test_doc() -> None:\n    import maturin_starter\n\n    assert (\n        maturin_starter.__doc__ == \"An example module implemented in Rust using PyO3.\"\n    )\n"
  },
  {
    "path": "examples/maturin-starter/tests/test_submodule.py",
    "content": "from maturin_starter.submodule import SubmoduleClass\n\n\ndef test_submodule_class() -> None:\n    submodule_class = SubmoduleClass()\n    assert submodule_class.greeting() == \"Hello, world!\"\n"
  },
  {
    "path": "examples/plugin/.template/Cargo.toml",
    "content": "[package]\nauthors = [\"{{authors}}\"]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[dependencies]\npyo3 = \"{{PYO3_VERSION}}\"\nplugin_api = { path = \"plugin_api\" }\n"
  },
  {
    "path": "examples/plugin/.template/plugin_api/Cargo.toml",
    "content": "[package]\nname = \"plugin_api\"\nversion = \"0.1.0\"\ndescription = \"Plugin API example\"\nedition = \"2021\"\n\n[lib]\nname = \"plugin_api\"\ncrate-type = [\"cdylib\", \"rlib\"]\n\n[dependencies]\npyo3 = \"{{PYO3_VERSION}}\"\n"
  },
  {
    "path": "examples/plugin/.template/pre-script.rhai",
    "content": "variable::set(\"PYO3_VERSION\", \"0.28.2\");\nfile::rename(\".template/Cargo.toml\", \"Cargo.toml\");\nfile::rename(\".template/plugin_api/Cargo.toml\", \"plugin_api/Cargo.toml\");\nfile::delete(\".template\");\n"
  },
  {
    "path": "examples/plugin/Cargo.toml",
    "content": "[package]\nname = \"plugin_example\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.83\"\n\n[dependencies]\npyo3 = { path = \"../../\", features = [\"macros\"] }\nplugin_api = { path = \"plugin_api\" }\n\n\n[workspace]\n"
  },
  {
    "path": "examples/plugin/README.md",
    "content": "# plugin\n\nAn example of a Rust app that uses Python for a plugin. A Python extension module built using PyO3 and [`maturin`](https://github.com/PyO3/maturin) is used to provide\ninterface types that can be used to exchange data between Rust and Python. This also deals with how to separately test and load python modules.\n\n# Building and Testing\n## Host application\nTo run the app itself, you only need to run\n\n```shell\ncargo run\n```\nIt will build the app, as well as the plugin API, then run the app, load the plugin and show it working.\n\n## Plugin API testing\n\nThe plugin API is in a separate crate `plugin_api`, so you can test it separately from the main app.\n\nTo build the API only package, install and build with `maturin`:\n\n```shell\npip install maturin\ncd plugin_api\nmaturin build\n```\n\nAlternatively, install nox and run the tests inside an isolated environment:\n\n```shell\nnox\n```\n\n## Copying this example\n\nUse [`cargo-generate`](https://crates.io/crates/cargo-generate):\n\n```bash\n$ cargo install cargo-generate\n$ cargo generate --git https://github.com/PyO3/pyo3 examples/plugin\n```\n\n(`cargo generate` will take a little while to clone the PyO3 repo first; be patient when waiting for the command to run.)\n"
  },
  {
    "path": "examples/plugin/cargo-generate.toml",
    "content": "[template]\nignore = [\".nox\"]\n\n[hooks]\npre = [\".template/pre-script.rhai\"]\n"
  },
  {
    "path": "examples/plugin/plugin_api/Cargo.toml",
    "content": "[package]\nname = \"plugin_api\"\nversion = \"0.1.0\"\ndescription = \"Plugin API example\"\nedition = \"2021\"\n\n[lib]\nname = \"plugin_api\"\ncrate-type = [\"cdylib\", \"rlib\"]\n\n[dependencies]\npyo3 = { path = \"../../../\" }\n"
  },
  {
    "path": "examples/plugin/plugin_api/noxfile.py",
    "content": "import nox\n\n\n@nox.session\ndef python(session):\n    session.env[\"MATURIN_PEP517_ARGS\"] = \"--profile=dev\"\n    session.install(\".[dev]\")\n    session.run(\"pytest\")\n"
  },
  {
    "path": "examples/plugin/plugin_api/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"plugin_api\"\nrequires-python = \">=3.7\"\nclassifiers = [\n    \"Programming Language :: Rust\",\n    \"Programming Language :: Python :: Implementation :: CPython\",\n    \"Programming Language :: Python :: Implementation :: PyPy\",\n]\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n"
  },
  {
    "path": "examples/plugin/plugin_api/src/lib.rs",
    "content": "use pyo3::prelude::*;\n\n///this is our Gadget that python plugin code can create, and rust app can then access natively.\n#[pyclass]\npub struct Gadget {\n    #[pyo3(get, set)]\n    pub prop: usize,\n    //this field will only be accessible to rust code\n    pub rustonly: Vec<usize>,\n}\n\n#[pymethods]\nimpl Gadget {\n    #[new]\n    fn new() -> Self {\n        Gadget {\n            prop: 777,\n            rustonly: Vec::new(),\n        }\n    }\n\n    fn push(&mut self, v: usize) {\n        self.rustonly.push(v);\n    }\n}\n\n/// A Python module for plugin interface types\n#[pymodule]\npub fn plugin_api(m: &Bound<'_, PyModule>) -> PyResult<()> {\n    m.add_class::<Gadget>()?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/plugin/plugin_api/tests/test_Gadget.py",
    "content": "import pytest\n\n\n@pytest.fixture\ndef gadget():\n    import plugin_api as pa\n\n    g = pa.Gadget()\n    return g\n\n\ndef test_creation(gadget):\n    pass\n\n\ndef test_property(gadget):\n    gadget.prop = 42\n    assert gadget.prop == 42\n\n\ndef test_push(gadget):\n    gadget.push(42)\n"
  },
  {
    "path": "examples/plugin/plugin_api/tests/test_import.py",
    "content": "def test_import():\n    import plugin_api  # noqa: F401\n"
  },
  {
    "path": "examples/plugin/python_plugin/gadget_init_plugin.py",
    "content": "import plugin_api\nimport rng\n\n\ndef start():\n    \"\"\"create an instance of Gadget, configure it and return to Rust\"\"\"\n    g = plugin_api.Gadget()\n    g.push(1)\n    g.push(2)\n    g.push(3)\n    g.prop = rng.get_random_number()\n    return g\n"
  },
  {
    "path": "examples/plugin/python_plugin/rng.py",
    "content": "def get_random_number():\n    # verified by the roll of a fair die to be random\n    return 4\n"
  },
  {
    "path": "examples/plugin/src/main.rs",
    "content": "use plugin_api::plugin_api as pylib_module;\nuse pyo3::prelude::*;\nuse pyo3::types::PyList;\n\nfn main() -> Result<(), Box<dyn std::error::Error>> {\n    //\"export\" our API module to the python runtime\n    pyo3::append_to_inittab!(pylib_module);\n    //spawn runtime\n    Python::initialize();\n    //import path for python\n    let path = \"./python_plugin/\";\n    //do useful work\n    Python::attach(|py| {\n        //add the current directory to import path of Python (do not use this in production!)\n        let syspath: Bound<PyList> = py.import(\"sys\")?.getattr(\"path\")?.extract().map_err(PyErr::from)?;\n        syspath.insert(0, &path)?;\n        println!(\"Import path is: {:?}\", syspath);\n\n        // Now we can load our python_plugin/gadget_init_plugin.py file.\n        // It can in turn import other stuff as it deems appropriate\n        let plugin = PyModule::import(py, \"gadget_init_plugin\")?;\n        // and call start function there, which will return a python reference to Gadget.\n        // Gadget here is a \"pyclass\" object reference\n        let gadget = plugin.getattr(\"start\")?.call0()?;\n\n        //now we extract (i.e. mutably borrow) the rust struct from python object\n        {\n            //this scope will have mutable access to the gadget instance, which will be dropped on\n            //scope exit so Python can access it again.\n            let mut gadget_rs: PyRefMut<'_, plugin_api::Gadget> = gadget.extract().map_err( PyErr::from)?;\n            // we can now modify it as if it was a native rust struct\n            gadget_rs.prop = 42;\n            //which includes access to rust-only fields that are not visible to python\n            println!(\"rust-only vec contains {:?}\", gadget_rs.rustonly);\n            gadget_rs.rustonly.clear();\n        }\n\n        //any modifications we make to rust object are reflected on Python object as well\n        let res: usize = gadget.getattr(\"prop\")?.extract()?;\n        println!(\"{res}\");\n        Ok(())\n    })\n}\n"
  },
  {
    "path": "examples/setuptools-rust-starter/.template/Cargo.toml",
    "content": "[package]\nauthors = [\"{{authors}}\"]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\nname = \"setuptools_rust_starter\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = \"{{PYO3_VERSION}}\"\n"
  },
  {
    "path": "examples/setuptools-rust-starter/.template/pre-script.rhai",
    "content": "variable::set(\"PYO3_VERSION\", \"0.28.2\");\nfile::rename(\".template/Cargo.toml\", \"Cargo.toml\");\nfile::rename(\".template/setup.cfg\", \"setup.cfg\");\nfile::delete(\".template\");\n"
  },
  {
    "path": "examples/setuptools-rust-starter/.template/setup.cfg",
    "content": "[metadata]\nname = {{project-name}}\nversion = 0.1.0\npackages =\n    setuptools_rust_starter\n\n[options]\ninclude_package_data = True\nzip_safe = False\n"
  },
  {
    "path": "examples/setuptools-rust-starter/Cargo.toml",
    "content": "[package]\nname = \"setuptools-rust-starter\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.83\"\n\n[lib]\nname = \"setuptools_rust_starter\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = { path = \"../../\" }\n\n[workspace]\n"
  },
  {
    "path": "examples/setuptools-rust-starter/MANIFEST.in",
    "content": "include pyproject.toml Cargo.toml\nrecursive-include src *\n"
  },
  {
    "path": "examples/setuptools-rust-starter/README.md",
    "content": "# setuptools-rust-starter\n\nAn example of a basic Python extension module built using PyO3 and [`setuptools_rust`](https://github.com/PyO3/setuptools-rust).\n\n## Building and Testing\n\nTo build this package, first install `setuptools_rust`:\n\n```shell\npip install setuptools_rust\n```\n\nTo build and test use `python setup.py develop`:\n\n```shell\npip install -r requirements-dev.txt\npython setup.py develop && pytest\n```\n\nAlternatively, install nox and run the tests inside an isolated environment:\n\n```shell\nnox\n```\n\n## Copying this example\n\nUse [`cargo-generate`](https://crates.io/crates/cargo-generate):\n\n```bash\n$ cargo install cargo-generate\n$ cargo generate --git https://github.com/PyO3/pyo3 examples/setuptools-rust-starter\n```\n\n(`cargo generate` will take a little while to clone the PyO3 repo first; be patient when waiting for the command to run.)\n"
  },
  {
    "path": "examples/setuptools-rust-starter/cargo-generate.toml",
    "content": "[template]\nignore = [\".nox\"]\n\n[hooks]\npre = [\".template/pre-script.rhai\"]\n"
  },
  {
    "path": "examples/setuptools-rust-starter/noxfile.py",
    "content": "import nox\nimport sys\n\n\n@nox.session\ndef python(session: nox.Session):\n    if sys.version_info < (3, 9):\n        session.skip(\"Python 3.9 or later is required for setuptools-rust 1.11\")\n    session.env[\"SETUPTOOLS_RUST_CARGO_PROFILE\"] = \"dev\"\n    session.install(\".[dev]\")\n    session.run(\"pytest\")\n"
  },
  {
    "path": "examples/setuptools-rust-starter/pyproject.toml",
    "content": "[build-system]\nrequires = [\"setuptools>=62.4\", \"setuptools_rust>=1.11\"]\n\n[project]\nname = \"setuptools-rust-starter\"\nversion = \"0.1.0\"\nclassifiers = [\n    \"License :: OSI Approved :: MIT License\",\n    \"Development Status :: 3 - Alpha\",\n    \"Intended Audience :: Developers\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Rust\",\n    \"Operating System :: POSIX\",\n    \"Operating System :: MacOS :: MacOS X\",\n]\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n\n[tool.setuptools.packages.find]\ninclude = [\"setuptools_rust_starter\"]\n\n[[tool.setuptools-rust.ext-modules]]\ntarget = \"setuptools_rust_starter._setuptools_rust_starter\"\npath = \"Cargo.toml\"\n"
  },
  {
    "path": "examples/setuptools-rust-starter/requirements-dev.txt",
    "content": "pytest>=3.5.0\nsetuptools_rust~=1.0.0\npip>=21.3\nwheel\n"
  },
  {
    "path": "examples/setuptools-rust-starter/setuptools_rust_starter/__init__.py",
    "content": "# import the contents of the Rust library into the Python extension\nfrom ._setuptools_rust_starter import *\nfrom ._setuptools_rust_starter import __all__\n\n# optional: include the documentation from the Rust module\nfrom ._setuptools_rust_starter import __doc__  # noqa: F401\n\n__all__ = __all__ + [\"PythonClass\"]\n\n\nclass PythonClass:\n    def __init__(self, value: int) -> None:\n        self.value = value\n"
  },
  {
    "path": "examples/setuptools-rust-starter/src/lib.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::PyDict;\nuse pyo3::wrap_pymodule;\n\nmod submodule;\n\n#[pyclass]\nstruct ExampleClass {\n    #[pyo3(get, set)]\n    value: i32,\n}\n\n#[pymethods]\nimpl ExampleClass {\n    #[new]\n    pub fn new(value: i32) -> Self {\n        ExampleClass { value }\n    }\n}\n\n/// An example module implemented in Rust using PyO3.\n#[pymodule]\nfn _setuptools_rust_starter(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {\n    m.add_class::<ExampleClass>()?;\n    m.add_wrapped(wrap_pymodule!(submodule::submodule))?;\n\n    // Inserting to sys.modules allows importing submodules nicely from Python\n    // e.g. from setuptools_rust_starter.submodule import SubmoduleClass\n\n    let sys = PyModule::import(py, \"sys\")?;\n    let sys_modules: Bound<'_, PyDict> = sys.getattr(\"modules\")?.cast_into()?;\n    sys_modules.set_item(\"setuptools_rust_starter.submodule\", m.getattr(\"submodule\")?)?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "examples/setuptools-rust-starter/src/submodule.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass]\nstruct SubmoduleClass {}\n\n#[pymethods]\nimpl SubmoduleClass {\n    #[new]\n    pub fn __new__() -> Self {\n        SubmoduleClass {}\n    }\n\n    pub fn greeting(&self) -> &'static str {\n        \"Hello, world!\"\n    }\n}\n\n#[pymodule]\npub fn submodule(m: &Bound<'_, PyModule>) -> PyResult<()> {\n    m.add_class::<SubmoduleClass>()?;\n    Ok(())\n}\n"
  },
  {
    "path": "examples/setuptools-rust-starter/tests/test_setuptools_rust_starter.py",
    "content": "from setuptools_rust_starter import ExampleClass, PythonClass\n\n\ndef test_python_class() -> None:\n    py_class = PythonClass(value=10)\n    assert py_class.value == 10\n\n\ndef test_example_class() -> None:\n    example = ExampleClass(value=11)\n    assert example.value == 11\n\n\ndef test_doc() -> None:\n    import setuptools_rust_starter\n\n    assert (\n        setuptools_rust_starter.__doc__\n        == \"An example module implemented in Rust using PyO3.\"\n    )\n"
  },
  {
    "path": "examples/setuptools-rust-starter/tests/test_submodule.py",
    "content": "from setuptools_rust_starter.submodule import SubmoduleClass\n\n\ndef test_submodule_class() -> None:\n    submodule_class = SubmoduleClass()\n    assert submodule_class.greeting() == \"Hello, world!\"\n"
  },
  {
    "path": "examples/word-count/.template/Cargo.toml",
    "content": "[package]\nauthors = [\"{{authors}}\"]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\nname = \"word_count\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = \"{{PYO3_VERSION}}\"\nrayon = \"1.0.2\"\n"
  },
  {
    "path": "examples/word-count/.template/pre-script.rhai",
    "content": "variable::set(\"PYO3_VERSION\", \"0.28.2\");\nfile::rename(\".template/Cargo.toml\", \"Cargo.toml\");\nfile::rename(\".template/pyproject.toml\", \"pyproject.toml\");\nfile::delete(\".template\");\n"
  },
  {
    "path": "examples/word-count/.template/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n\n[tool.pytest.ini_options]\naddopts = \"--benchmark-disable\"\n"
  },
  {
    "path": "examples/word-count/Cargo.toml",
    "content": "[package]\nname = \"word-count\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.83\"\n\n[lib]\nname = \"word_count\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = { path = \"../..\" }\nrayon = \"1.0.2\"\n\n[workspace]\n"
  },
  {
    "path": "examples/word-count/MANIFEST.in",
    "content": "include pyproject.toml Cargo.toml\nrecursive-include src *\n"
  },
  {
    "path": "examples/word-count/README.md",
    "content": "# word-count\n\nDemonstrates searching for a file in plain python, with rust singlethreaded and with rust multithreaded.\n\n## Build\n\n```shell\npip install .\n```\n\n## Usage\n\n```python\nfrom word_count import search_py, search, search_sequential\n\nsearch_py(\"foo bar\", \"foo\")\nsearch(\"foo bar\", \"foo\")\nsearch_sequential(\"foo bar\", \"foo\")\n```\n\n## Testing\n\nTo test install nox globally and run\n\n```shell\nnox\n```\n\n## Benchmark\n\nTo test install nox globally and run\n\n```shell\nnox -s bench\n```\n\n## Copying this example\n\nUse [`cargo-generate`](https://crates.io/crates/cargo-generate):\n\n```bash\n$ cargo install cargo-generate\n$ cargo generate --git https://github.com/PyO3/pyo3 examples/word-count\n```\n\n(`cargo generate` will take a little while to clone the PyO3 repo first; be patient when waiting for the command to run.)\n"
  },
  {
    "path": "examples/word-count/cargo-generate.toml",
    "content": "[template]\nignore = [\".nox\"]\n\n[hooks]\npre = [\".template/pre-script.rhai\"]\n"
  },
  {
    "path": "examples/word-count/noxfile.py",
    "content": "import nox\n\nnox.options.sessions = [\"test\"]\n\n\n@nox.session\ndef test(session: nox.Session):\n    session.env[\"MATURIN_PEP517_ARGS\"] = \"--profile=dev\"\n    session.install(\".[dev]\")\n    session.run(\"pytest\")\n\n\n@nox.session\ndef bench(session: nox.Session):\n    session.install(\".[dev]\")\n    session.run(\"pytest\", \"--benchmark-enable\")\n"
  },
  {
    "path": "examples/word-count/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"word-count\"\nversion = \"0.1.0\"\nclassifiers = [\n    \"License :: OSI Approved :: MIT License\",\n    \"Development Status :: 3 - Alpha\",\n    \"Intended Audience :: Developers\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Rust\",\n    \"Operating System :: POSIX\",\n    \"Operating System :: MacOS :: MacOS X\",\n]\n\n[project.optional-dependencies]\ndev = [\"pytest\", \"pytest-benchmark\"]\n\n[tool.pytest.ini_options]\naddopts = \"--benchmark-disable\"\n"
  },
  {
    "path": "examples/word-count/src/lib.rs",
    "content": "use pyo3::prelude::*;\nuse rayon::prelude::*;\n\n/// Searches for the word, parallelized by rayon\n#[pyfunction]\nfn search(contents: &str, needle: &str) -> usize {\n    contents\n        .par_lines()\n        .map(|line| count_line(line, needle))\n        .sum()\n}\n\n/// Searches for a word in a classic sequential fashion\n#[pyfunction]\nfn search_sequential(contents: &str, needle: &str) -> usize {\n    contents.lines().map(|line| count_line(line, needle)).sum()\n}\n\n#[pyfunction]\nfn search_sequential_detached(py: Python<'_>, contents: &str, needle: &str) -> usize {\n    py.detach(|| search_sequential(contents, needle))\n}\n\n/// Count the occurrences of needle in line, case insensitive\nfn count_line(line: &str, needle: &str) -> usize {\n    let mut total = 0;\n    for word in line.split(' ') {\n        if word == needle {\n            total += 1;\n        }\n    }\n    total\n}\n\n#[pymodule]\nfn word_count(m: &Bound<'_, PyModule>) -> PyResult<()> {\n    m.add_function(wrap_pyfunction!(search, m)?)?;\n    m.add_function(wrap_pyfunction!(search_sequential, m)?)?;\n    m.add_function(wrap_pyfunction!(search_sequential_detached, m)?)?;\n\n    Ok(())\n}\n"
  },
  {
    "path": "examples/word-count/tests/test_word_count.py",
    "content": "from concurrent.futures import ThreadPoolExecutor\n\nimport pytest\nimport word_count\n\n\n@pytest.fixture(scope=\"session\")\ndef contents() -> str:\n    text = \"\"\"\nThe Zen of Python, by Tim Peters\n\nBeautiful is better than ugly.\nExplicit is better than implicit.\nSimple is better than complex.\nComplex is better than complicated.\nFlat is better than nested.\nSparse is better than dense.\nReadability counts.\nSpecial cases aren't special enough to break the rules.\nAlthough practicality beats purity.\nErrors should never pass silently.\nUnless explicitly silenced.\nIn the face of ambiguity, refuse the temptation to guess.\nThere should be one-- and preferably only one --obvious way to do it.\nAlthough that way may not be obvious at first unless you're Dutch.\nNow is better than never.\nAlthough never is often better than *right* now.\nIf the implementation is hard to explain, it's a bad idea.\nIf the implementation is easy to explain, it may be a good idea.\nNamespaces are one honking great idea -- let's do more of those!\n\"\"\"\n    return text * 1000\n\n\ndef test_word_count_rust_parallel(benchmark, contents):\n    count = benchmark(word_count.search, contents, \"is\")\n    assert count == 10000\n\n\ndef test_word_count_rust_sequential(benchmark, contents):\n    count = benchmark(word_count.search_sequential, contents, \"is\")\n    assert count == 10000\n\n\ndef test_word_count_python_sequential(benchmark, contents):\n    count = benchmark(word_count.search_py, contents, \"is\")\n    assert count == 10000\n\n\ndef run_rust_sequential_twice(\n    executor: ThreadPoolExecutor, contents: str, needle: str\n) -> int:\n    future_1 = executor.submit(word_count.search_sequential_detached, contents, needle)\n    future_2 = executor.submit(word_count.search_sequential_detached, contents, needle)\n    result_1 = future_1.result()\n    result_2 = future_2.result()\n    return result_1 + result_2\n\n\ndef test_word_count_rust_sequential_twice_with_threads(benchmark, contents):\n    executor = ThreadPoolExecutor(max_workers=2)\n    count = benchmark(run_rust_sequential_twice, executor, contents, \"is\")\n    assert count == 20000\n"
  },
  {
    "path": "examples/word-count/word_count/__init__.py",
    "content": "from .word_count import search, search_sequential, search_sequential_detached\n\n__all__ = [\n    \"search_py\",\n    \"search\",\n    \"search_sequential\",\n    \"search_sequential_detached\",\n]\n\n\ndef search_py(contents: str, needle: str) -> int:\n    total = 0\n    for line in contents.splitlines():\n        for word in line.split(\" \"):\n            if word == needle:\n                total += 1\n    return total\n"
  },
  {
    "path": "guide/book.toml",
    "content": "[book]\ntitle = \"PyO3 user guide\"\ndescription = \"PyO3 user guide\"\nauthors = [\"PyO3 Project and Contributors\"]\n\n[preprocessor.pyo3_version]\ncommand = \"python3 pyo3_version.py\"\n\n[preprocessor.tabs]\n\n[output.html]\ngit-repository-url = \"https://github.com/PyO3/pyo3/tree/main/guide\"\nedit-url-template = \"https://github.com/PyO3/pyo3/edit/main/guide/{path}\"\nplayground.runnable = false\nadditional-css = [\"theme/tabs.css\"]\nadditional-js = [\"theme/tabs.js\"]\n"
  },
  {
    "path": "guide/pyclass-parameters.md",
    "content": "`#[pyclass]` can be used with the following parameters:\n\n|  Parameter  |  Description |\n| :-  | :- |\n| `constructor` | This is currently only allowed on [variants of complex enums][params-constructor]. It allows customization of the generated class constructor for each variant. It uses the same syntax and supports the same options as the `signature` attribute of functions and methods. |\n| <span style=\"white-space: pre\">`crate = \"some::path\"`</span>  | Path to import the `pyo3` crate, if it's not accessible at `::pyo3`. |\n| `dict` | Gives instances of this class an empty `__dict__` to store custom attributes. |\n| `eq` | Implements `__eq__` using the `PartialEq` implementation of the underlying Rust datatype. |\n| `eq_int` | Implements `__eq__` using `__int__` for simple enums. |\n| <span style=\"white-space: pre\">`extends = BaseType`</span>  | Use a custom baseclass. Defaults to [`PyAny`][params-1] |\n| <span style=\"white-space: pre\">`freelist = N`</span> |  Implements a [free list][params-2] of size N. This can improve performance for types that are often created and deleted in quick succession. Profile your code to see whether `freelist` is right for you.  |\n| `from_py_object` | Implement `FromPyObject` for this pyclass. Requires the pyclass to be `Clone`. |\n| <span style=\"white-space: pre\">`frozen`</span> | Declares that your pyclass is immutable. It removes the borrow checker overhead when retrieving a shared reference to the Rust struct, but disables the ability to get a mutable reference. |\n| `generic` | Implements runtime parametrization for the class following [PEP 560](https://peps.python.org/pep-0560/). |\n| `get_all` | Generates getters for all fields of the pyclass. |\n| `hash` | Implements `__hash__` using the `Hash` implementation of the underlying Rust datatype. *Requires `eq` and `frozen`* |\n| `immutable_type` | Makes the type object immutable. Supported on 3.14+ with the `abi3` feature active, or 3.10+ otherwise. |\n| `mapping` |  Inform PyO3 that this class is a [`Mapping`][params-mapping], and so leave its implementation of sequence C-API slots empty. |\n| <span style=\"white-space: pre\">`module = \"module_name\"`</span> |  Python code will see the class as being defined in this module. Defaults to `builtins`. |\n| <span style=\"white-space: pre\">`name = \"python_name\"`</span> | Sets the name that Python sees this class as. Defaults to the name of the Rust struct. |\n| `ord` | Implements `__lt__`, `__gt__`, `__le__`, & `__ge__` using the `PartialOrd` implementation of the underlying Rust datatype. *Requires `eq`* |\n| `rename_all = \"renaming_rule\"` | Applies renaming rules to every getters and setters of a struct, or every variants of an enum. Possible values are: \"camelCase\", \"kebab-case\", \"lowercase\", \"PascalCase\", \"SCREAMING-KEBAB-CASE\", \"SCREAMING_SNAKE_CASE\", \"snake_case\", \"UPPERCASE\". |\n| `sequence` |  Inform PyO3 that this class is a [`Sequence`][params-sequence], and so leave its C-API mapping length slot empty. |\n| `set_all` | Generates setters for all fields of the pyclass. |\n| `new = \"from_fields\"` | Generates a default `__new__` constructor with all fields as parameters in the `new()` method. |\n| `skip_from_py_object` | Prevents this PyClass from participating in the `FromPyObject: PyClass + Clone` blanket implementation. This allows a custom `FromPyObject` impl, even if `self` is `Clone`. |\n| `str` | Implements `__str__` using the `Display` implementation of the underlying Rust datatype or by passing an optional format string `str=\"<format string>\"`. *Note: The optional format string is only allowed for structs.  `name` and `rename_all` are incompatible with the optional format string.  Additional details can be found in the discussion on this [PR](https://github.com/PyO3/pyo3/pull/4233).* |\n| `subclass` | Allows other Python classes and `#[pyclass]` to inherit from this class. Enums cannot be subclassed. |\n| `unsendable` | Required if your struct is not [`Send`][params-3]. Rather than using `unsendable`, consider implementing your struct in a thread-safe way by e.g. substituting [`Rc`][params-4] with [`Arc`][params-5]. By using `unsendable`, your class will panic when accessed by another thread. Also note the Python's GC is multi-threaded and while unsendable classes will not be traversed on foreign threads to avoid UB, this can lead to memory leaks. |\n| `weakref` | Allows this class to be [weakly referenceable][params-6]. |\n\nAll of these parameters can either be passed directly on the `#[pyclass(...)]` annotation, or as one or more accompanying `#[pyo3(...)]` annotations, e.g.:\n\n```rust,ignore\n// Argument supplied directly to the `#[pyclass]` annotation.\n#[pyclass(name = \"SomeName\", subclass)]\nstruct MyClass {}\n\n// Argument supplied as a separate annotation.\n#[pyclass]\n#[pyo3(name = \"SomeName\", subclass)]\nstruct MyClass {}\n```\n\n[params-1]: https://docs.rs/pyo3/latest/pyo3/types/struct.PyAny.html\n[params-2]: https://en.wikipedia.org/wiki/Free_list\n[params-3]: https://doc.rust-lang.org/std/marker/trait.Send.html\n[params-4]: https://doc.rust-lang.org/std/rc/struct.Rc.html\n[params-5]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n[params-6]: https://docs.python.org/3/library/weakref.html\n[params-constructor]: https://pyo3.rs/latest/class.html#complex-enums\n[params-mapping]: https://pyo3.rs/latest/class/protocols.html#mapping--sequence-types\n[params-sequence]: https://pyo3.rs/latest/class/protocols.html#mapping--sequence-types\n"
  },
  {
    "path": "guide/pyo3_version.py",
    "content": "\"\"\"Simple mdbook preprocessor to inject pyo3 version into the guide.\n\nIt will replace:\n    - {{#PYO3_VERSION_TAG}} with the contents of the PYO3_VERSION_TAG environment var\n    - {{#PYO3_DOCS_URL}} with the location of docs (e.g. 'https://docs.rs/pyo3/0.13.2')\n    - {{#PYO3_CRATE_VERSION}} with a relevant toml snippet (e.g. 'version = \"0.13.2\"')\n\n\nTested against mdbook 0.5.0.\n\"\"\"\n\nimport json\nimport os\nimport sys\n\n# Set PYO3_VERSION in CI to build the correct version into links\nPYO3_VERSION_TAG = os.environ.get(\"PYO3_VERSION_TAG\", \"main\")\n\nif PYO3_VERSION_TAG == \"main\":\n    PYO3_DOCS_URL = \"https://pyo3.rs/main/doc\"\n    PYO3_DOCS_VERSION = \"latest\"\n    PYO3_CRATE_VERSION = 'git = \"https://github.com/pyo3/pyo3\"'\nelse:\n    # v0.13.2 -> 0.13.2\n    version = PYO3_VERSION_TAG.lstrip(\"v\")\n    PYO3_DOCS_URL = f\"https://docs.rs/pyo3/{version}\"\n    PYO3_DOCS_VERSION = version\n    PYO3_CRATE_VERSION = f'version = \"{version}\"'\n\n\ndef replace_item_content(item):\n    if not isinstance(item, dict) or \"Chapter\" not in item:\n        return\n\n    # Replace raw and url-encoded forms\n    item[\"Chapter\"][\"content\"] = (\n        item[\"Chapter\"][\"content\"]\n        .replace(\"{{#PYO3_VERSION_TAG}}\", PYO3_VERSION_TAG)\n        .replace(\"{{#PYO3_DOCS_URL}}\", PYO3_DOCS_URL)\n        .replace(\"{{#PYO3_DOCS_VERSION}}\", PYO3_DOCS_VERSION)\n        .replace(\"{{#PYO3_CRATE_VERSION}}\", PYO3_CRATE_VERSION)\n    )\n\n    for sub_item in item[\"Chapter\"][\"sub_items\"]:\n        replace_item_content(sub_item)\n\n\nfor line in sys.stdin:\n    if line:\n        [context, book] = json.loads(line)\n        for item in book[\"items\"]:\n            replace_item_content(item)\n        json.dump(book, fp=sys.stdout)\n"
  },
  {
    "path": "guide/src/SUMMARY.md",
    "content": "# Summary\n\n[Introduction](index.md)\n\n---\n\n- [Getting started](getting-started.md)\n- [Using Rust from Python](rust-from-python.md)\n  - [Python modules](module.md)\n  - [Python functions](function.md)\n    - [Function signatures](function/signature.md)\n    - [Error handling](function/error-handling.md)\n  - [Python classes](class.md)\n    - [Class customizations](class/protocols.md)\n      - [Basic object customization](class/object.md)\n      - [Emulating numeric types](class/numeric.md)\n      - [Emulating callable objects](class/call.md)\n    - [Thread safety](class/thread-safety.md)\n- [Calling Python from Rust](python-from-rust.md)\n  - [Python object types](types.md)\n  - [Python exceptions](exception.md)\n  - [Calling Python functions](python-from-rust/function-calls.md)\n  - [Executing existing Python code](python-from-rust/calling-existing-code.md)\n- [Type conversions](conversions.md)\n  - [Mapping of Rust types to Python types](conversions/tables.md)\n  - [Conversion traits](conversions/traits.md)\n- [Using `async` and `await`](async-await.md)\n- [Parallelism](parallelism.md)\n- [Supporting Free-Threaded Python](free-threading.md)\n- [Debugging](debugging.md)\n- [Features reference](features.md)\n- [Performance](performance.md)\n- [Type stub generation and introspection](type-stub.md)\n- [Advanced topics](advanced.md)\n- [Building and distribution](building-and-distribution.md)\n  - [Supporting multiple Python versions](building-and-distribution/multiple-python-versions.md)\n- [Useful crates](ecosystem.md)\n  - [Logging](ecosystem/logging.md)\n  - [Tracing](ecosystem/tracing.md)\n  - [Using `async` and `await`](ecosystem/async-await.md)\n- [FAQ and troubleshooting](faq.md)\n\n---\n\n[Appendix A: Migration guide](migration.md)\n\n[Appendix B: Trait bounds](trait-bounds.md)\n\n[Appendix C: Python typing hints](python-typing-hints.md)\n\n[CHANGELOG](changelog.md)\n\n---\n\n[Contributing](contributing.md)\n"
  },
  {
    "path": "guide/src/advanced.md",
    "content": "# Advanced topics\n\n## FFI\n\nPyO3 exposes much of Python's C API through the `ffi` module.\n\nThe C API is naturally unsafe and requires you to manage reference counts, errors and specific invariants yourself.\nPlease refer to the [C API Reference Manual](https://docs.python.org/3/c-api/) and [The Rustonomicon](https://doc.rust-lang.org/nightly/nomicon/ffi.html) before using any function from that API.\n"
  },
  {
    "path": "guide/src/async-await.md",
    "content": "# Using `async` and `await`\n\n*This feature is still in active development.*\n*See [the related issue](https://github.com/PyO3/pyo3/issues/1632).*\n\n`#[pyfunction]` and `#[pymethods]` attributes also support `async fn`.\n\n```rust,no_run\n# #![allow(dead_code)]\n# #[cfg(feature = \"experimental-async\")] {\nuse std::{thread, time::Duration};\nuse futures::channel::oneshot;\nuse pyo3::prelude::*;\n\n#[pyfunction]\n#[pyo3(signature=(seconds, result=None))]\nasync fn sleep(seconds: f64, result: Option<Py<PyAny>>) -> Option<Py<PyAny>> {\n    let (tx, rx) = oneshot::channel();\n    thread::spawn(move || {\n        thread::sleep(Duration::from_secs_f64(seconds));\n        tx.send(()).unwrap();\n    });\n    rx.await.unwrap();\n    result\n}\n# }\n```\n\n*Python awaitables instantiated with this method can only be awaited in `asyncio` context.*\n*Other Python async runtime may be supported in the future.*\n\n## `Send + 'static` constraint\n\nResulting future of an `async fn` decorated by `#[pyfunction]` must be `Send + 'static` to be embedded in a Python object.\n\nAs a consequence, `async fn` parameters and return types must also be `Send + 'static`, so it is not possible to have a signature like `async fn does_not_compile<'py>(arg: Bound<'py, PyAny>) -> Bound<'py, PyAny>`.\n\nHowever, there is an exception for method receivers, so async methods can accept `&self`/ `&mut self`.\nNote that this means that the class instance is borrowed for as long as the returned future is not completed, even across yield points and while waiting for I/O operations to complete.\nHence, other methods cannot obtain exclusive borrows while the future is still being polled.\nThis is the same as how async methods in Rust generally work but it is more problematic for Rust code interfacing with Python code due to pervasive shared mutability.\nThis strongly suggests to prefer shared borrows `&self` over exclusive ones `&mut self` to avoid racy borrow check failures at runtime.\n\n## Implicitly attached to the interpreter\n\nEven if it is not possible to pass a `py: Python<'py>` token to an `async fn`, we're still attached to the interpreter during the execution of the future – the same as for a regular `fn` without `Python<'py>`/`Bound<'py, PyAny>` parameter\n\nIt is still possible to get a `Python` marker using [`Python::attach`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.attach); because `attach` is reentrant and optimized, the cost will be negligible.\n\n## Detaching from the interpreter across `.await`\n\nThere is currently no simple way to detach from the interpreter when awaiting a future, *but solutions are currently in development*.\n\nHere is the advised workaround for now:\n\n```rust,ignore\nuse std::{\n    future::Future,\n    pin::{Pin, pin},\n    task::{Context, Poll},\n};\nuse pyo3::prelude::*;\n\nstruct AllowThreads<F>(F);\n\nimpl<F> Future for AllowThreads<F>\nwhere\n    F: Future + Unpin + Send,\n    F::Output: Send,\n{\n    type Output = F::Output;\n\n    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {\n        let waker = cx.waker();\n        Python::attach(|py| {\n            py.detach(|| pin!(&mut self.0).poll(&mut Context::from_waker(waker)))\n        })\n    }\n}\n```\n\n## Cancellation\n\nCancellation on the Python side can be caught using [`CancelHandle`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html) type, by annotating a function parameter with `#[pyo3(cancel_handle)]`.\n\n```rust,no_run\n# #![allow(dead_code)]\n# #[cfg(feature = \"experimental-async\")] {\nuse futures::FutureExt;\nuse pyo3::prelude::*;\nuse pyo3::coroutine::CancelHandle;\n\n#[pyfunction]\nasync fn cancellable(#[pyo3(cancel_handle)] mut cancel: CancelHandle) {\n    futures::select! {\n        /* _ = ... => println!(\"done\"), */\n        _ = cancel.cancelled().fuse() => println!(\"cancelled\"),\n    }\n}\n# }\n```\n\n## The `Coroutine` type\n\nTo make a Rust future awaitable in Python, PyO3 defines a [`Coroutine`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.Coroutine.html) type, which implements the Python [coroutine protocol](https://docs.python.org/3/library/collections.abc.html#collections.abc.Coroutine).\n\nEach `coroutine.send` call is translated to a `Future::poll` call.\nIf a [`CancelHandle`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html) parameter is declared, the exception passed to `coroutine.throw` call is stored in it and can be retrieved with [`CancelHandle::cancelled`]({{#PYO3_DOCS_URL}}/pyo3/coroutine/struct.CancelHandle.html#method.cancelled); otherwise, it cancels the Rust future, and the exception is reraised;\n\n*The type does not yet have a public constructor until the design is finalized.*\n"
  },
  {
    "path": "guide/src/building-and-distribution/multiple-python-versions.md",
    "content": "# Supporting multiple Python versions\n\nPyO3 supports all actively-supported Python 3 and PyPy versions.\nAs much as possible, this is done internally to PyO3 so that your crate's code does not need to adapt to the differences between each version.\nHowever, as Python features grow and change between versions, PyO3 cannot offer a completely identical API for every Python version.\nThis may require you to add conditional compilation to your crate or runtime checks for the Python version.\n\nThis section of the guide first introduces the `pyo3-build-config` crate, which you can use as a `build-dependency` to add additional `#[cfg]` flags which allow you to support multiple Python versions at compile-time.\n\nSecond, we'll show how to check the Python version at runtime.\nThis can be useful when building for multiple versions with the `abi3` feature, where the Python API compiled against is not always the same as the one in use.\n\n## Conditional compilation for different Python versions\n\nThe `pyo3-build-config` exposes multiple [`#[cfg]` flags](https://doc.rust-lang.org/rust-by-example/attribute/cfg.html) which can be used to conditionally compile code for a given Python version.\nPyO3 itself depends on this crate, so by using it you can be sure that you are configured correctly for the Python version PyO3 is building against.\n\nThis allows us to write code like the following\n\n```rust,ignore\n#[cfg(Py_3_7)]\nfn function_only_supported_on_python_3_7_and_up() {}\n\n#[cfg(not(Py_3_8))]\nfn function_only_supported_before_python_3_8() {}\n\n#[cfg(not(Py_LIMITED_API))]\nfn function_incompatible_with_abi3_feature() {}\n```\n\nThe following sections first show how to add these `#[cfg]` flags to your build process, and then cover some common patterns flags in a little more detail.\n\nTo see a full reference of all the `#[cfg]` flags provided, see the [`pyo3-build-cfg` docs](https://docs.rs/pyo3-build-config).\n\n### Using `pyo3-build-config`\n\nYou can use the `#[cfg]` flags in just two steps:\n\n1. Add `pyo3-build-config` with the [`resolve-config`](../features.md#resolve-config) feature enabled to your crate's build dependencies in `Cargo.toml`:\n\n   ```toml\n   [build-dependencies]\n   pyo3-build-config = { {{#PYO3_CRATE_VERSION}}, features = [\"resolve-config\"] }\n   ```\n\n2. Add a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) file to your crate with the following contents:\n\n   ```rust,ignore\n   fn main() {\n       // If you have an existing build.rs file, just add this line to it.\n       pyo3_build_config::use_pyo3_cfgs();\n   }\n   ```\n\nAfter these steps you are ready to annotate your code!\n\n### Common usages of `pyo3-build-cfg` flags\n\nThe `#[cfg]` flags added by `pyo3-build-cfg` can be combined with all of Rust's logic in the `#[cfg]` attribute to create very precise conditional code generation.\nThe following are some common patterns implemented using these flags:\n\n```text\n#[cfg(Py_3_7)]\n```\n\nThis `#[cfg]` marks code that will only be present on Python 3.7 and upwards.\nThere are similar options `Py_3_8`, `Py_3_9`, `Py_3_10` and so on for each minor version.\n\n```text\n#[cfg(not(Py_3_7))]\n```\n\nThis `#[cfg]` marks code that will only be present on Python versions before (but not including) Python 3.7.\n\n```text\n#[cfg(not(Py_LIMITED_API))]\n```\n\nThis `#[cfg]` marks code that is only available when building for the unlimited Python API (i.e. PyO3's `abi3` feature is not enabled).\nThis might be useful if you want to ship your extension module as an `abi3` wheel and also allow users to compile it from source to make use of optimizations only possible with the unlimited API.\n\n```text\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\n```\n\nThis `#[cfg]` marks code which is available when running Python 3.9 or newer, or when using the unlimited API with an older Python version.\nPatterns like this are commonly seen on Python APIs which were added to the limited Python API in a specific minor version.\n\n```text\n#[cfg(PyPy)]\n```\n\nThis `#[cfg]` marks code which is running on PyPy.\n\n## Checking the Python version at runtime\n\nWhen building with PyO3's `abi3` feature, your extension module will be compiled against a specific [minimum version](../building-and-distribution.md#minimum-python-version-for-abi3) of Python, but may be running on newer Python versions.\n\nFor example with PyO3's `abi3-py38` feature, your extension will be compiled as if it were for Python 3.8.\nIf you were using `pyo3-build-config`, `#[cfg(Py_3_8)]` would be present.\nYour user could freely install and run your abi3 extension on Python 3.9.\n\nThere's no way to detect your user doing that at compile time, so instead you need to fall back to runtime checks.\n\nPyO3 provides the APIs [`Python::version()`] and [`Python::version_info()`] to query the running Python version.\nThis allows you to do the following, for example:\n\n```rust\nuse pyo3::Python;\n\nPython::attach(|py| {\n    // PyO3 supports Python 3.7 and up.\n    assert!(py.version_info() >= (3, 7));\n    assert!(py.version_info() >= (3, 7, 0));\n});\n```\n\n[`Python::version()`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.version\n[`Python::version_info()`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.version_info\n"
  },
  {
    "path": "guide/src/building-and-distribution.md",
    "content": "# Building and distribution\n\nThis chapter of the guide goes into detail on how to build and distribute projects using PyO3.\nThe way to achieve this is very different depending on whether the project is a Python module implemented in Rust, or a Rust binary embedding Python.\nFor both types of project there are also common problems such as the Python version to build for and the [linker](https://en.wikipedia.org/wiki/Linker_(computing)) arguments to use.\n\nThe material in this chapter is intended for users who have already read the PyO3 [README](./index.md).\nIt covers in turn the choices that can be made for Python modules and for Rust binaries.\nThere is also a section at the end about cross-compiling projects using PyO3.\n\nThere is an additional sub-chapter dedicated to [supporting multiple Python versions](./building-and-distribution/multiple-python-versions.md).\n\n## Configuring the Python version\n\nPyO3 uses a build script (backed by the [`pyo3-build-config`] crate) to determine the Python version and set the correct linker arguments.\nBy default it will attempt to use the following in order:\n\n- Any active Python virtualenv.\n- The `python` executable (if it's a Python 3 interpreter).\n- The `python3` executable.\n\nYou can override the Python interpreter by setting the `PYO3_PYTHON` environment variable, e.g. `PYO3_PYTHON=python3.7`, `PYO3_PYTHON=/usr/bin/python3.9`, or even a PyPy interpreter `PYO3_PYTHON=pypy3`.\n\nOnce the Python interpreter is located, `pyo3-build-config` executes it to query the information in the `sysconfig` module which is needed to configure the rest of the compilation.\n\nTo validate the configuration which PyO3 will use, you can run a compilation with the environment variable `PYO3_PRINT_CONFIG=1` set.\nAn example output of doing this is shown below:\n\n```console\n$ PYO3_PRINT_CONFIG=1 cargo build\n   Compiling pyo3 v0.14.1 (/home/david/dev/pyo3)\nerror: failed to run custom build command for `pyo3 v0.14.1 (/home/david/dev/pyo3)`\n\nCaused by:\n  process didn't exit successfully: `/home/david/dev/pyo3/target/debug/build/pyo3-7a8cf4fe22e959b7/build-script-build` (exit status: 101)\n  --- stdout\n  cargo:rerun-if-env-changed=PYO3_CROSS\n  cargo:rerun-if-env-changed=PYO3_CROSS_LIB_DIR\n  cargo:rerun-if-env-changed=PYO3_CROSS_PYTHON_VERSION\n  cargo:rerun-if-env-changed=PYO3_PRINT_CONFIG\n\n  -- PYO3_PRINT_CONFIG=1 is set, printing configuration and halting compile --\n  implementation=CPython\n  version=3.8\n  shared=true\n  abi3=false\n  lib_name=python3.8\n  lib_dir=/usr/lib\n  executable=/usr/bin/python\n  pointer_width=64\n  build_flags=\n  suppress_build_script_link_lines=false\n```\n\nThe `PYO3_ENVIRONMENT_SIGNATURE` environment variable can be used to trigger rebuilds when its value changes, it has no other effect.\n\n### Advanced: config files\n\nIf you save the above output config from `PYO3_PRINT_CONFIG` to a file, it is possible to manually override the contents and feed it back into PyO3 using the `PYO3_CONFIG_FILE` env var.\n\nIf your build environment is unusual enough that PyO3's regular configuration detection doesn't work, using a config file like this will give you the flexibility to make PyO3 work for you.\nTo see the full set of options supported, see the documentation for the [`InterpreterConfig` struct](https://docs.rs/pyo3-build-config/{{#PYO3_DOCS_VERSION}}/pyo3_build_config/struct.InterpreterConfig.html).\n\n## Building Python extension modules\n\nPython extension modules need to be compiled differently depending on the OS (and architecture) that they are being compiled for.\nAs well as multiple OSes (and architectures), there are also many different Python versions which are actively supported.\nPackages uploaded to [PyPI](https://pypi.org/) usually want to upload prebuilt \"wheels\" covering many OS/arch/version combinations so that users on all these different platforms don't have to compile the package themselves.\nPackage vendors can opt-in to the \"abi3\" limited Python API which allows their wheels to be used on multiple Python versions, reducing the number of wheels they need to compile, but restricts the functionality they can use.\n\nThere are many ways to go about this: it is possible to use `cargo` to build the extension module (along with some manual work, which varies with OS).\nThe PyO3 ecosystem has two packaging tools, [`maturin`] and [`setuptools-rust`], which abstract over the OS difference and also support building wheels for PyPI upload.\n\nPyO3 has some functionality for configuring projects when building Python extension modules:\n\n- The `PYO3_BUILD_EXTENSION_MODULE` environment variable, which must be set when building Python extension modules. `maturin` and `setuptools-rust` set this automatically.\n- The `abi3` Cargo feature and its version-specific `abi3-pyXY` companions, which are used to opt-in to the limited Python API in order to support multiple Python versions in a single wheel.\n\nThis section describes the packaging tools before describing how to build manually without them.\nIt then proceeds with an explanation of the `PYO3_BUILD_EXTENSION_MODULE` environment variable.\nFinally, there is a section describing PyO3's `abi3` features.\n\n### Packaging tools\n\nThe PyO3 ecosystem has two main choices to abstract the process of developing Python extension modules:\n\n- [`maturin`] is a command-line tool to build, package and upload Python modules.\n  It makes opinionated choices about project layout meaning it needs very little configuration.\n  This makes it a great choice for users who are building a Python extension from scratch and don't need flexibility.\n- [`setuptools-rust`] is an add-on for `setuptools` which adds extra keyword arguments to the `setup.py` configuration file.\n  It requires more configuration than `maturin`, however this gives additional flexibility for users adding Rust to an existing Python package that can't satisfy `maturin`'s constraints.\n\nConsult each project's documentation for full details on how to get started using them and how to upload wheels to PyPI.\nIt should be noted that while `maturin` is able to build [manylinux](https://github.com/pypa/manylinux)-compliant wheels out-of-the-box, `setuptools-rust` requires a bit more effort, [relying on Docker](https://setuptools-rust.readthedocs.io/en/latest/building_wheels.html) for this purpose.\n\nThere are also [`maturin-starter`] and [`setuptools-rust-starter`] examples in the PyO3 repository.\n\n### Manual builds\n\nTo build a PyO3-based Python extension manually, start by running `cargo build` as normal in a library project with the [`cdylib` crate type](https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-crate-type-field) while the `PYO3_BUILD_EXTENSION_MODULE` environment variable is set.\n\nOnce built, symlink (or copy) and rename the shared library from Cargo's `target/` directory to your desired output directory:\n\n- on macOS, rename `libyour_module.dylib` to `your_module.so`.\n- on Windows, rename `libyour_module.dll` to `your_module.pyd`.\n- on Linux, rename `libyour_module.so` to `your_module.so`.\n\nYou can then open a Python shell in the output directory and you'll be able to run `import your_module`.\n\nIf you're packaging your library for redistribution, you should indicate the Python interpreter your library is compiled for by including the [platform tag](#platform-tags) in its name.\nThis prevents incompatible interpreters from trying to import your library.\nIf you're compiling for PyPy you *must* include the platform tag, or PyPy will ignore the module.\n\n#### Bazel builds\n\nTo use PyO3 with bazel one needs to manually configure PyO3, PyO3-ffi and PyO3-macros.\nIn particular, one needs to make sure that it is compiled with the right python flags for the version you intend to use.\nFor example see:\n\n1. [github.com/abrisco/rules_pyo3](https://github.com/abrisco/rules_pyo3) -- General rules for building extension modules.\n2. [github.com/OliverFM/pytorch_with_gazelle](https://github.com/OliverFM/pytorch_with_gazelle) -- for a minimal example of a repo that can use PyO3, PyTorch and Gazelle to generate python Build files.\n3. [github.com/TheButlah/rules_pyo3](https://github.com/TheButlah/rules_pyo3) -- is somewhat dated.\n\n#### Platform tags\n\nRather than using just the `.so` or `.pyd` extension suggested above (depending on OS), you can prefix the shared library extension with a platform tag to indicate the interpreter it is compatible with.\nYou can query your interpreter's platform tag from the `sysconfig` module.\nSome example outputs of this are seen below:\n\n```bash\n# CPython 3.10 on macOS\n.cpython-310-darwin.so\n\n# PyPy 7.3 (Python 3.9) on Linux\n$ python -c 'import sysconfig; print(sysconfig.get_config_var(\"EXT_SUFFIX\"))'\n.pypy39-pp73-x86_64-linux-gnu.so\n```\n\nSo, for example, a valid module library name on CPython 3.10 for macOS is `your_module.cpython-310-darwin.so`, and its equivalent when compiled for PyPy 7.3 on Linux would be `your_module.pypy38-pp73-x86_64-linux-gnu.so`.\n\nSee [PEP 3149](https://peps.python.org/pep-3149/) for more background on platform tags.\n\n#### macOS\n\nOn macOS, because the `PYO3_BUILD_EXTENSION_MODULE` environment variable disables linking to `libpython` ([see the next section](#the-extension-module-feature)), some additional linker arguments need to be set. `maturin` and `setuptools-rust` both pass these arguments for PyO3 automatically, but projects using manual builds will need to set these directly in order to support macOS.\n\nThe easiest way to set the correct linker arguments is to add a [`build.rs`](https://doc.rust-lang.org/cargo/reference/build-scripts.html) with the following content:\n\n```rust,ignore\nfn main() {\n    pyo3_build_config::add_extension_module_link_args();\n}\n```\n\nRemember to also add `pyo3-build-config` to the `build-dependencies` section in `Cargo.toml`.\n\nAn alternative to using `pyo3-build-config` is add the following to a cargo configuration file (e.g. `.cargo/config.toml`):\n\n```toml\n[target.x86_64-apple-darwin]\nrustflags = [\n  \"-C\", \"link-arg=-undefined\",\n  \"-C\", \"link-arg=dynamic_lookup\",\n]\n\n[target.aarch64-apple-darwin]\nrustflags = [\n  \"-C\", \"link-arg=-undefined\",\n  \"-C\", \"link-arg=dynamic_lookup\",\n]\n```\n\nUsing the MacOS system python3 (`/usr/bin/python3`, as opposed to python installed via homebrew, pyenv, nix, etc.) may result in runtime errors such as `Library not loaded: @rpath/Python3.framework/Versions/3.8/Python3`.\n\nThe easiest way to set the correct linker arguments is to add a `build.rs` with the following content:\n\n```rust,ignore\nfn main() {\n    pyo3_build_config::add_python_framework_link_args();\n}\n```\n\nAlternatively it can be resolved with another addition to `.cargo/config.toml`:\n\n```toml\n[build]\nrustflags = [\n  \"-C\", \"link-args=-Wl,-rpath,/Library/Developer/CommandLineTools/Library/Frameworks\",\n]\n```\n\nFor more discussion on and workarounds for MacOS linking problems [see this issue](https://github.com/PyO3/pyo3/issues/1800#issuecomment-906786649).\n\nFinally, don't forget that on MacOS the `extension-module` feature will cause `cargo test` to fail without the `--no-default-features` flag (see [the FAQ](https://pyo3.rs/main/faq.html#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror)).\n\n### The `PYO3_BUILD_EXTENSION_MODULE` environment variable\n\n<a name=\"the-extension-module-feature\"></a> <!-- for backwards compatibility -->\n\nBy default PyO3 links to `libpython`.\nThis makes binaries, tests, and examples \"just work\".\nHowever, Python extensions on Unix must not link to libpython for [manylinux](https://www.python.org/dev/peps/pep-0513/) compliance.\n\nThe downside of not linking to `libpython` is that binaries, tests, and examples (which usually embed Python) will fail to build.\nAs a result, PyO3 uses an envionment variable `PYO3_BUILD_EXTENSION_MODULE` to disable linking to `libpython`.\nThis should only be set when building a library for distribution.\n`maturin >= 1.9.4` and `setuptools-rust >= 1.12` will set this for you automatically.\n\n> [!NOTE]\n> Historically PyO3 used an `extension-module` feature to perform the same function now done by the `PYO3_BUILD_EXTENSION_MODULE` env var.\n> This feature caused linking to be disabled for all compile targets, including Rust tests and benchmarks.\n>\n> Projects are encouraged to migrate off the feature, as it caused [major development pain](faq.md#i-cant-run-cargo-test-or-i-cant-build-in-a-cargo-workspace-im-having-linker-issues-like-symbol-not-found-or-undefined-reference-to-_pyexc_systemerror) due to the lack of linking.\n\n### `Py_LIMITED_API`/`abi3`\n\nBy default, Python extension modules can only be used with the same Python version they were compiled against.\nFor example, an extension module built for Python 3.5 can't be imported in Python 3.8.\n[PEP 384](https://www.python.org/dev/peps/pep-0384/) introduced the idea of the limited Python API, which would have a stable ABI enabling extension modules built with it to be used against multiple Python versions.\nThis is also known as `abi3`.\n\nThe advantage of building extension modules using the limited Python API is that package vendors only need to build and distribute a single copy (for each OS / architecture), and users can install it on all Python versions from the [minimum version](#minimum-python-version-for-abi3) and up.\nThe downside of this is that PyO3 can't use optimizations which rely on being compiled against a known exact Python version.\nIt's up to you to decide whether this matters for your extension module.\nIt's also possible to design your extension module such that you can distribute `abi3` wheels but allow users compiling from source to benefit from additional optimizations - see the [support for multiple python versions](./building-and-distribution/multiple-python-versions.md) section of this guide, in particular the `#[cfg(Py_LIMITED_API)]` flag.\n\nThere are three steps involved in making use of `abi3` when building Python packages as wheels:\n\n1. Enable the `abi3` feature in `pyo3`.\n   This ensures `pyo3` only calls Python C-API functions which are part of the stable API, and on Windows also ensures that the project links against the correct shared object (no special behavior is required on other platforms):\n\n   ```toml\n   [dependencies]\n   pyo3 = { {{#PYO3_CRATE_VERSION}}, features = [\"abi3\"] }\n   ```\n\n2. Ensure that the built shared objects are correctly marked as `abi3`.\n   This is accomplished by telling your build system that you're using the limited API.\n   [`maturin`] >= 0.9.0 and [`setuptools-rust`] >= 0.11.4 support `abi3` wheels.\n\n   See the [corresponding](https://github.com/PyO3/maturin/pull/353) [PRs](https://github.com/PyO3/setuptools-rust/pull/82) for more.\n\n3. Ensure that the `.whl` is correctly marked as `abi3`.\n   For projects using `setuptools`, this is accomplished by passing `--py-limited-api=cp3x` (where `x` is the minimum Python version supported by the wheel, e.g. `--py-limited-api=cp35` for Python 3.5) to `setup.py bdist_wheel`.\n\n#### Minimum Python version for `abi3`\n\nBecause a single `abi3` wheel can be used with many different Python versions, PyO3 has feature flags `abi3-py37`, `abi3-py38`, `abi3-py39` etc. to set the minimum required Python version for your `abi3` wheel.\nFor example, if you set the `abi3-py37` feature, your extension wheel can be used on all Python 3 versions from Python 3.7 and up.\n`maturin` and `setuptools-rust` will give the wheel a name like `my-extension-1.0-cp37-abi3-manylinux2020_x86_64.whl`.\n\nAs your extension module may be run with multiple different Python versions you may occasionally find you need to check the Python version at runtime to customize behavior.\nSee [the relevant section of this guide](./building-and-distribution/multiple-python-versions.md#checking-the-python-version-at-runtime) on supporting multiple Python versions at runtime.\n\nPyO3 is only able to link your extension module to abi3 version up to and including your host Python version.\nE.g., if you set `abi3-py38` and try to compile the crate with a host of Python 3.7, the build will fail.\n\n> [!NOTE]\n> If you set more that one of these `abi3` version feature flags the lowest version always wins. For example, with both `abi3-py37` and `abi3-py38` set, PyO3 would build a wheel which supports Python 3.7 and up.\n\n#### Building `abi3` extensions without a Python interpreter\n\nAs an advanced feature, you can build PyO3 wheel without calling Python interpreter with the environment variable `PYO3_NO_PYTHON` set.\nAlso, if the build host Python interpreter is not found or is too old or otherwise unusable, PyO3 will still attempt to compile `abi3` extension modules after displaying a warning message.\n\n#### Missing features\n\nDue to limitations in the Python API, there are a few `pyo3` features that do not work when compiling for `abi3`.\nThese are:\n\n- `#[pyo3(text_signature = \"...\")]` does not work on classes until Python 3.10 or greater.\n- The `dict` and `weakref` options on classes are not supported until Python 3.9 or greater.\n- The buffer API is not supported until Python 3.11 or greater.\n- Subclassing native types (e.g. `PyException`) is not supported until Python 3.12 or greater.\n- Optimizations which rely on knowledge of the exact Python version compiled against.\n\n## Embedding Python in Rust\n\nIf you want to embed the Python interpreter inside a Rust program, there are two modes in which this can be done: dynamically and statically.\nWe'll cover each of these modes in the following sections.\nEach of them affect how you must distribute your program.\nInstead of learning how to do this yourself, you might want to consider using a project like [PyOxidizer] to ship your application and all of its dependencies in a single file.\n\nPyO3 automatically switches between the two linking modes depending on whether the Python distribution you have configured PyO3 to use ([see above](#configuring-the-python-version)) contains a shared library or a static library.\nThe static library is most often seen in Python distributions compiled from source without the `--enable-shared` configuration option.\n\n### Dynamically embedding the Python interpreter\n\nEmbedding the Python interpreter dynamically is much easier than doing so statically.\nThis is done by linking your program against a Python shared library (such as `libpython.3.9.so` on UNIX, or `python39.dll` on Windows).\nThe implementation of the Python interpreter resides inside the shared library.\nThis means that when the OS runs your Rust program it also needs to be able to find the Python shared library.\n\nThis mode of embedding works well for Rust tests which need access to the Python interpreter.\nIt is also great for Rust software which is installed inside a Python virtualenv, because the virtualenv sets up appropriate environment variables to locate the correct Python shared library.\n\nFor distributing your program to non-technical users, you will have to consider including the Python shared library in your distribution as well as setting up wrapper scripts to set the right environment variables (such as `LD_LIBRARY_PATH` on UNIX, or `PATH` on Windows).\n\nNote that PyPy cannot be embedded in Rust (or any other software).\nSupport for this is tracked on the [PyPy issue tracker](https://github.com/pypy/pypy/issues/3836).\n\n### Statically embedding the Python interpreter\n\nEmbedding the Python interpreter statically means including the contents of a Python static library directly inside your Rust binary.\nThis means that to distribute your program you only need to ship your binary file: it contains the Python interpreter inside the binary!\n\nOn Windows static linking is almost never done, so Python distributions don't usually include a static library.\nThe information below applies only to UNIX.\n\nThe Python static library is usually called `libpython.a`.\n\nStatic linking has a lot of complications, listed below.\nFor these reasons PyO3 does not yet have first-class support for this embedding mode.\nSee [issue 416 on PyO3's GitHub](https://github.com/PyO3/pyo3/issues/416) for more information and to discuss any issues you encounter.\n\nThe [`auto-initialize`](features.md#auto-initialize) feature is deliberately disabled when embedding the interpreter statically because this is often unintentionally done by new users to PyO3 running test programs.\nTrying out PyO3 is much easier using dynamic embedding.\n\nThe known complications are:\n\n- To import compiled extension modules (such as other Rust extension modules, or those written in C), your binary must have the correct linker flags set during compilation to export the original contents of `libpython.a` so that extensions can use them (e.g. `-Wl,--export-dynamic`).\n- The C compiler and flags which were used to create `libpython.a` must be compatible with your Rust compiler and flags, else you will experience compilation failures.\n\n    Significantly different compiler versions may see errors like this:\n\n    ```text\n    lto1: fatal error: bytecode stream in file 'rust-numpy/target/release/deps/libpyo3-6a7fb2ed970dbf26.rlib' generated with LTO version 6.0 instead of the expected 6.2\n    ```\n\n    Mismatching flags may lead to errors like this:\n\n    ```text\n    /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libpython3.9.a(zlibmodule.o): relocation R_X86_64_32 against `.data' can not be used when making a PIE object; recompile with -fPIE\n    ```\n\nIf you encounter these or other complications when linking the interpreter statically, discuss them on [issue 416 on PyO3's GitHub](https://github.com/PyO3/pyo3/issues/416).\nIt is hoped that eventually that discussion will contain enough information and solutions that PyO3 can offer first-class support for static embedding.\n\n### Import your module when embedding the Python interpreter\n\nWhen you run your Rust binary with an embedded interpreter, any `#[pymodule]` created modules won't be accessible to import unless added to a table called `PyImport_Inittab` before the embedded interpreter is initialized.\nThis will cause Python statements in your embedded interpreter such as `import your_new_module` to fail.\nYou can call the macro [`append_to_inittab`]({{#PYO3_DOCS_URL}}/pyo3/macro.append_to_inittab.html) with your module before initializing the Python interpreter to add the module function into that table. (The Python interpreter will be initialized by calling `Python::initialize`, `with_embedded_python_interpreter`, or `Python::attach` with the [`auto-initialize`](features.md#auto-initialize) feature enabled.)\n\n## Cross Compiling\n\nThanks to Rust's great cross-compilation support, cross-compiling using PyO3 is relatively straightforward.\nTo get started, you'll need a few pieces of software:\n\n- A toolchain for your target.\n- The appropriate options in your Cargo `.config` for the platform you're targeting and the toolchain you are using.\n- A Python interpreter that's already been compiled for your target (optional when building \"abi3\" extension modules).\n- A Python interpreter that is built for your host and available through the `PATH` or setting the [`PYO3_PYTHON`](#configuring-the-python-version) variable (optional when building \"abi3\" extension modules).\n\nAfter you've obtained the above, you can build a cross-compiled PyO3 module by using Cargo's `--target` flag.\nPyO3's build script will detect that you are attempting a cross-compile based on your host machine and the desired target.\n\nWhen cross-compiling, PyO3's build script cannot execute the target Python interpreter to query the configuration, so there are a few additional environment variables you may need to set:\n\n- `PYO3_CROSS`: If present this variable forces PyO3 to configure as a cross-compilation.\n- `PYO3_CROSS_LIB_DIR`: This variable can be set to the directory containing the target's libpython DSO and the associated `_sysconfigdata*.py` file for Unix-like targets.\n  This variable is only needed when the output binary must link to libpython explicitly (e.g. when targeting Android or embedding a Python interpreter), or when it is absolutely required to get the interpreter configuration from `_sysconfigdata*.py`.\n  On Windows, this variable is not needed because PyO3 uses `raw-dylib` linking.\n- `PYO3_CROSS_PYTHON_VERSION`: Major and minor version (e.g. 3.9) of the target Python installation.\n  This variable is only needed if PyO3 cannot determine the version to target from `abi3-py3*` features, or if `PYO3_CROSS_LIB_DIR` is not set, or if there are multiple versions of Python present in `PYO3_CROSS_LIB_DIR`.\n- `PYO3_CROSS_PYTHON_IMPLEMENTATION`: Python implementation name (\"CPython\" or \"PyPy\") of the target Python installation.\n  CPython is assumed by default when this variable is not set, unless `PYO3_CROSS_LIB_DIR` is set for a Unix-like target and PyO3 can get the interpreter configuration from `_sysconfigdata*.py`.\n\nAn example might look like the following (assuming your target's sysroot is at `/home/pyo3/cross/sysroot` and that your target is `armv7`):\n\n```sh\nexport PYO3_CROSS_LIB_DIR=\"/home/pyo3/cross/sysroot/usr/lib\"\n\ncargo build --target armv7-unknown-linux-gnueabihf\n```\n\nIf there are multiple python versions at the cross lib directory and you cannot set a more precise location to include both the `libpython` DSO and `_sysconfigdata*.py` files, you can set the required version:\n\n```sh\nexport PYO3_CROSS_PYTHON_VERSION=3.8\nexport PYO3_CROSS_LIB_DIR=\"/home/pyo3/cross/sysroot/usr/lib\"\n\ncargo build --target armv7-unknown-linux-gnueabihf\n```\n\nOr another example building for Windows (no `PYO3_CROSS_LIB_DIR` needed thanks to `raw-dylib`):\n\n```sh\nexport PYO3_CROSS_PYTHON_VERSION=3.9\n\ncargo build --target x86_64-pc-windows-gnu\n```\n\nAny of the `abi3-py3*` features can be enabled instead of setting `PYO3_CROSS_PYTHON_VERSION` in the above examples.\n\n`PYO3_CROSS_LIB_DIR` can often be omitted when cross compiling extension modules for Unix, macOS, and Windows targets.\n\nThe following resources may also be useful for cross-compiling:\n\n- [github.com/japaric/rust-cross](https://github.com/japaric/rust-cross) is a primer on cross compiling Rust.\n- [github.com/rust-embedded/cross](https://github.com/rust-embedded/cross) uses Docker to make Rust cross-compilation easier.\n\n[`pyo3-build-config`]: https://github.com/PyO3/pyo3/tree/main/pyo3-build-config\n[`maturin-starter`]: https://github.com/PyO3/pyo3/tree/main/examples/maturin-starter\n[`setuptools-rust-starter`]: https://github.com/PyO3/pyo3/tree/main/examples/setuptools-rust-starter\n[`maturin`]: https://github.com/PyO3/maturin\n[`setuptools-rust`]: https://github.com/PyO3/setuptools-rust\n[PyOxidizer]: https://github.com/indygreg/PyOxidizer\n"
  },
  {
    "path": "guide/src/changelog.md",
    "content": "{{#include ../../CHANGELOG.md}}\n"
  },
  {
    "path": "guide/src/class/call.md",
    "content": "# Emulating callable objects\n\nClasses can be callable if they have a `#[pymethod]` named `__call__`.\nThis allows instances of a class to behave similar to functions.\n\nThis method's signature must look like `__call__(<self>, ...) -> object` - here, any argument list can be defined as for normal pymethods\n\n## Example: Implementing a call counter\n\nThe following pyclass is a basic decorator - its constructor takes a Python object as argument and calls that object when called.\nAn equivalent Python implementation is linked at the end.\n\nAn example crate containing this pyclass can be found [in the PyO3 GitHub repository](https://github.com/PyO3/pyo3/tree/main/examples/decorator)\n\n```rust,ignore\n{{#include ../../../examples/decorator/src/lib.rs}}\n```\n\nPython code:\n\n```python\n{{#include ../../../examples/decorator/tests/example.py}}\n```\n\nOutput:\n\n```text\nsay_hello has been called 1 time(s).\nhello\nsay_hello has been called 2 time(s).\nhello\nsay_hello has been called 3 time(s).\nhello\nsay_hello has been called 4 time(s).\nhello\n```\n\n### Pure Python implementation\n\nA Python implementation of this looks similar to the Rust version:\n\n```python\nclass Counter:\n    def __init__(self, wraps):\n        self.count = 0\n        self.wraps = wraps\n\n    def __call__(self, *args, **kwargs):\n        self.count += 1\n        print(f\"{self.wraps.__name__} has been called {self.count} time(s)\")\n        self.wraps(*args, **kwargs)\n```\n\nNote that it can also be implemented as a higher order function:\n\n```python\ndef Counter(wraps):\n    count = 0\n    def call(*args, **kwargs):\n        nonlocal count\n        count += 1\n        print(f\"{wraps.__name__} has been called {count} time(s)\")\n        return wraps(*args, **kwargs)\n    return call\n```\n\n### What is the `AtomicU64` for?\n\nA [previous implementation] used a normal `u64`, which meant it required a `&mut self` receiver to update the count:\n\n```rust,ignore\n#[pyo3(signature = (*args, **kwargs))]\nfn __call__(\n    &mut self,\n    py: Python<'_>,\n    args: &Bound<'_, PyTuple>,\n    kwargs: Option<&Bound<'_, PyDict>>,\n) -> PyResult<Py<PyAny>> {\n    self.count += 1;\n    let name = self.wraps.getattr(py, \"__name__\")?;\n\n    println!(\"{} has been called {} time(s).\", name, self.count);\n\n    // After doing something, we finally forward the call to the wrapped function\n    let ret = self.wraps.call(py, args, kwargs)?;\n\n    // We could do something with the return value of\n    // the function before returning it\n    Ok(ret)\n}\n```\n\nThe problem with this is that the `&mut self` receiver means PyO3 has to borrow it exclusively, and hold this borrow across the `self.wraps.call(py, args, kwargs)` call.\nThis call returns control to the user's Python code which is free to call arbitrary things, *including* the decorated function.\nIf that happens PyO3 is unable to create a second unique borrow and will be forced to raise an exception.\n\nAs a result, something innocent like this will raise an exception:\n\n```py\n@Counter\ndef say_hello():\n    if say_hello.count < 2:\n        print(f\"hello from decorator\")\n\nsay_hello()\n# RuntimeError: Already borrowed\n```\n\nThe implementation in this chapter fixes that by never borrowing exclusively; all the methods take `&self` as receivers, of which multiple may exist simultaneously.\nThis requires a shared counter and the most straightforward way to implement thread-safe interior mutability (e.g. the type does not need to accept `&mut self` to modify the \"interior\" state) for a `u64` is to use [`AtomicU64`], so that's what is used here.\n\nThis shows the dangers of running arbitrary Python code - note that \"running arbitrary Python code\" can be far more subtle than the example above:\n\n- Python's asynchronous executor may park the current thread in the middle of Python code, even in Python code that *you* control, and let other Python code run.\n- Dropping arbitrary Python objects may invoke destructors defined in Python (`__del__` methods).\n- Calling Python's C-api (most PyO3 apis call C-api functions internally) may raise exceptions, which may allow Python code in signal handlers to run.\n- On the free-threaded build, users might use Python's `threading` module to work with your types simultaneously from multiple OS threads.\n\nThis is especially important if you are writing unsafe code; Python code must never be able to cause undefined behavior.\nYou must ensure that your Rust code is in a consistent state before doing any of the above things.\n\n<!-- rumdl-disable MD057 -->\n<!-- TODO: investigate why this lint is being triggered -->\n[previous implementation]: <https://github.com/PyO3/pyo3/discussions/2598> \"Thread Safe Decorator <Help Wanted> · Discussion #2598 · PyO3/pyo3\"\n[`AtomicU64`]: <https://doc.rust-lang.org/std/sync/atomic/struct.AtomicU64.html> \"AtomicU64 in std::sync::atomic - Rust\"\n<!-- rumdl-enable MD057 -->\n"
  },
  {
    "path": "guide/src/class/numeric.md",
    "content": "# Emulating numeric types\n\nAt this point we have a `Number` class that we can't actually do any math on!\n\nBefore proceeding, we should think about how we want to handle overflows.\nThere are three obvious solutions:\n\n- We can have infinite precision just like Python's `int`.\n  However that would be quite boring - we'd be reinventing the wheel.\n- We can raise exceptions whenever `Number` overflows, but that makes the API painful to use.\n- We can wrap around the boundary of `i32`.\n  This is the approach we'll take here.\n  To do that we'll just forward to `i32`'s `wrapping_*` methods.\n\n## Fixing our constructor\n\nLet's address the first overflow, in `Number`'s constructor:\n\n```python\nfrom my_module import Number\n\nn = Number(1 << 1337)\n```\n\n```text\nTraceback (most recent call last):\n  File \"example.py\", line 3, in <module>\n    n = Number(1 << 1337)\nOverflowError: Python int too large to convert to C long\n```\n\nInstead of relying on the default [`FromPyObject`] extraction to parse arguments, we can specify our own extraction function, using the `#[pyo3(from_py_with = ...)]` attribute.\nUnfortunately PyO3 doesn't provide a way to wrap Python integers out of the box, but we can do a Python call to mask it and cast it to an `i32`.\n\n```rust,no_run\n# #![allow(dead_code)]\nuse pyo3::prelude::*;\n\nfn wrap(obj: &Bound<'_, PyAny>) -> PyResult<i32> {\n    let val = obj.call_method1(\"__and__\", (0xFFFFFFFF_u32,))?;\n    let val: u32 = val.extract()?;\n    //     👇 This intentionally overflows!\n    Ok(val as i32)\n}\n```\n\nWe also add documentation, via `///` comments, which are visible to Python users.\n\n```rust,no_run\n# #![allow(dead_code)]\nuse pyo3::prelude::*;\n\nfn wrap(obj: &Bound<'_, PyAny>) -> PyResult<i32> {\n    let val = obj.call_method1(\"__and__\", (0xFFFFFFFF_u32,))?;\n    let val: u32 = val.extract()?;\n    Ok(val as i32)\n}\n\n/// Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not.\n/// It's not a story C would tell you. It's a Rust legend.\n#[pyclass(module = \"my_module\")]\nstruct Number(i32);\n\n#[pymethods]\nimpl Number {\n    #[new]\n    fn new(#[pyo3(from_py_with = wrap)] value: i32) -> Self {\n        Self(value)\n    }\n}\n```\n\nWith that out of the way, let's implement some operators:\n\n```rust,no_run\nuse pyo3::exceptions::{PyZeroDivisionError, PyValueError};\n\n# use pyo3::prelude::*;\n#\n# #[pyclass]\n# struct Number(i32);\n#\n#[pymethods]\nimpl Number {\n    fn __add__(&self, other: &Self) -> Self {\n        Self(self.0.wrapping_add(other.0))\n    }\n\n    fn __sub__(&self, other: &Self) -> Self {\n        Self(self.0.wrapping_sub(other.0))\n    }\n\n    fn __mul__(&self, other: &Self) -> Self {\n        Self(self.0.wrapping_mul(other.0))\n    }\n\n    fn __truediv__(&self, other: &Self) -> PyResult<Self> {\n        match self.0.checked_div(other.0) {\n            Some(i) => Ok(Self(i)),\n            None => Err(PyZeroDivisionError::new_err(\"division by zero\")),\n        }\n    }\n\n    fn __floordiv__(&self, other: &Self) -> PyResult<Self> {\n        match self.0.checked_div(other.0) {\n            Some(i) => Ok(Self(i)),\n            None => Err(PyZeroDivisionError::new_err(\"division by zero\")),\n        }\n    }\n\n    fn __rshift__(&self, other: &Self) -> PyResult<Self> {\n        match other.0.try_into() {\n            Ok(rhs) => Ok(Self(self.0.wrapping_shr(rhs))),\n            Err(_) => Err(PyValueError::new_err(\"negative shift count\")),\n        }\n    }\n\n    fn __lshift__(&self, other: &Self) -> PyResult<Self> {\n        match other.0.try_into() {\n            Ok(rhs) => Ok(Self(self.0.wrapping_shl(rhs))),\n            Err(_) => Err(PyValueError::new_err(\"negative shift count\")),\n        }\n    }\n}\n```\n\n### Unary arithmetic operations\n\n```rust,no_run\n# use pyo3::prelude::*;\n#\n# #[pyclass]\n# struct Number(i32);\n#\n#[pymethods]\nimpl Number {\n    fn __pos__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {\n        slf\n    }\n\n    fn __neg__(&self) -> Self {\n        Self(-self.0)\n    }\n\n    fn __abs__(&self) -> Self {\n        Self(self.0.abs())\n    }\n\n    fn __invert__(&self) -> Self {\n        Self(!self.0)\n    }\n}\n```\n\n### Support for the `complex()`, `int()` and `float()` built-in functions\n\n```rust,no_run\n# use pyo3::prelude::*;\n#\n# #[pyclass]\n# struct Number(i32);\n#\nuse pyo3::types::PyComplex;\n\n#[pymethods]\nimpl Number {\n    fn __int__(&self) -> i32 {\n        self.0\n    }\n\n    fn __float__(&self) -> f64 {\n        self.0 as f64\n    }\n\n    fn __complex__<'py>(&self, py: Python<'py>) -> Bound<'py, PyComplex> {\n        PyComplex::from_doubles(py, self.0 as f64, 0.0)\n    }\n}\n```\n\nWe do not implement the in-place operations like `__iadd__` because we do not wish to mutate `Number`.\nSimilarly we're not interested in supporting operations with different types, so we do not implement the reflected operations like `__radd__` either.\n\nNow Python can use our `Number` class:\n\n```python\nfrom my_module import Number\n\ndef hash_djb2(s: str):\n\t'''\n\tA version of Daniel J. Bernstein's djb2 string hashing algorithm\n\tLike many hashing algorithms, it relies on integer wrapping.\n\t'''\n\n\tn = Number(0)\n\tfive = Number(5)\n\n\tfor x in s:\n\t\tn = Number(ord(x)) + ((n << five) - n)\n\treturn n\n\nassert hash_djb2('l50_50') == Number(-1152549421)\n```\n\n### Final code\n\n```rust\nuse std::collections::hash_map::DefaultHasher;\nuse std::hash::{Hash, Hasher};\n\nuse pyo3::exceptions::{PyValueError, PyZeroDivisionError};\nuse pyo3::prelude::*;\nuse pyo3::class::basic::CompareOp;\nuse pyo3::types::{PyComplex, PyString};\n\nfn wrap(obj: &Bound<'_, PyAny>) -> PyResult<i32> {\n    let val = obj.call_method1(\"__and__\", (0xFFFFFFFF_u32,))?;\n    let val: u32 = val.extract()?;\n    Ok(val as i32)\n}\n/// Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not.\n/// It's not a story C would tell you. It's a Rust legend.\n#[pyclass(module = \"my_module\")]\nstruct Number(i32);\n\n#[pymethods]\nimpl Number {\n    #[new]\n    fn new(#[pyo3(from_py_with = wrap)] value: i32) -> Self {\n        Self(value)\n    }\n\n    fn __repr__(slf: &Bound<'_, Self>) -> PyResult<String> {\n       // Get the class name dynamically in case `Number` is subclassed\n       let class_name: Bound<'_, PyString> = slf.get_type().qualname()?;\n        Ok(format!(\"{}({})\", class_name, slf.borrow().0))\n    }\n\n    fn __str__(&self) -> String {\n        self.0.to_string()\n    }\n\n    fn __hash__(&self) -> u64 {\n        let mut hasher = DefaultHasher::new();\n        self.0.hash(&mut hasher);\n        hasher.finish()\n    }\n\n    fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult<bool> {\n        match op {\n            CompareOp::Lt => Ok(self.0 < other.0),\n            CompareOp::Le => Ok(self.0 <= other.0),\n            CompareOp::Eq => Ok(self.0 == other.0),\n            CompareOp::Ne => Ok(self.0 != other.0),\n            CompareOp::Gt => Ok(self.0 > other.0),\n            CompareOp::Ge => Ok(self.0 >= other.0),\n        }\n    }\n\n    fn __bool__(&self) -> bool {\n        self.0 != 0\n    }\n\n    fn __add__(&self, other: &Self) -> Self {\n        Self(self.0.wrapping_add(other.0))\n    }\n\n    fn __sub__(&self, other: &Self) -> Self {\n        Self(self.0.wrapping_sub(other.0))\n    }\n\n    fn __mul__(&self, other: &Self) -> Self {\n        Self(self.0.wrapping_mul(other.0))\n    }\n\n    fn __truediv__(&self, other: &Self) -> PyResult<Self> {\n        match self.0.checked_div(other.0) {\n            Some(i) => Ok(Self(i)),\n            None => Err(PyZeroDivisionError::new_err(\"division by zero\")),\n        }\n    }\n\n    fn __floordiv__(&self, other: &Self) -> PyResult<Self> {\n        match self.0.checked_div(other.0) {\n            Some(i) => Ok(Self(i)),\n            None => Err(PyZeroDivisionError::new_err(\"division by zero\")),\n        }\n    }\n\n    fn __rshift__(&self, other: &Self) -> PyResult<Self> {\n        match other.0.try_into() {\n            Ok(rhs) => Ok(Self(self.0.wrapping_shr(rhs))),\n            Err(_) => Err(PyValueError::new_err(\"negative shift count\")),\n        }\n    }\n\n    fn __lshift__(&self, other: &Self) -> PyResult<Self> {\n        match other.0.try_into() {\n            Ok(rhs) => Ok(Self(self.0.wrapping_shl(rhs))),\n            Err(_) => Err(PyValueError::new_err(\"negative shift count\")),\n        }\n    }\n\n    fn __xor__(&self, other: &Self) -> Self {\n        Self(self.0 ^ other.0)\n    }\n\n    fn __or__(&self, other: &Self) -> Self {\n        Self(self.0 | other.0)\n    }\n\n    fn __and__(&self, other: &Self) -> Self {\n        Self(self.0 & other.0)\n    }\n\n    fn __int__(&self) -> i32 {\n        self.0\n    }\n\n    fn __float__(&self) -> f64 {\n        self.0 as f64\n    }\n\n    fn __complex__<'py>(&self, py: Python<'py>) -> Bound<'py, PyComplex> {\n        PyComplex::from_doubles(py, self.0 as f64, 0.0)\n    }\n}\n\n#[pymodule]\nmod my_module {\n    #[pymodule_export]\n    use super::Number;\n}\n# const SCRIPT: &'static std::ffi::CStr = cr#\"\n# def hash_djb2(s: str):\n#     n = Number(0)\n#     five = Number(5)\n#\n#     for x in s:\n#         n = Number(ord(x)) + ((n << five) - n)\n#     return n\n#\n# assert hash_djb2('l50_50') == Number(-1152549421)\n# assert hash_djb2('logo') == Number(3327403)\n# assert hash_djb2('horizon') == Number(1097468315)\n#\n#\n# assert Number(2) + Number(2) == Number(4)\n# assert Number(2) + Number(2) != Number(5)\n#\n# assert Number(13) - Number(7) == Number(6)\n# assert Number(13) - Number(-7) == Number(20)\n#\n# assert Number(13) / Number(7) == Number(1)\n# assert Number(13) // Number(7) == Number(1)\n#\n# assert Number(13) * Number(7) == Number(13*7)\n#\n# assert Number(13) > Number(7)\n# assert Number(13) < Number(20)\n# assert Number(13) == Number(13)\n# assert Number(13) >= Number(7)\n# assert Number(13) <= Number(20)\n# assert Number(13) == Number(13)\n#\n#\n# assert (True if Number(1) else False)\n# assert (False if Number(0) else True)\n#\n#\n# assert int(Number(13)) == 13\n# assert float(Number(13)) == 13\n# assert Number.__doc__ == \"Did you ever hear the tragedy of Darth Signed The Overfloweth? I thought not.\\nIt's not a story C would tell you. It's a Rust legend.\"\n# assert Number(12345234523452) == Number(1498514748)\n# try:\n#     import inspect\n#     assert inspect.signature(Number).__str__() == '(value)'\n# except ValueError:\n#     # Not supported with `abi3` before Python 3.10\n#     pass\n# assert Number(1337).__str__() == '1337'\n# assert Number(1337).__repr__() == 'Number(1337)'\n\"#;\n\n#\n# use pyo3::PyTypeInfo;\n#\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| -> PyResult<()> {\n#         let globals = PyModule::import(py, \"__main__\")?.dict();\n#         globals.set_item(\"Number\", Number::type_object(py))?;\n#\n#         py.run(SCRIPT, Some(&globals), None)?;\n#         Ok(())\n#     })\n# }\n```\n\n## Appendix: Writing some unsafe code\n\nAt the beginning of this chapter we said that PyO3 doesn't provide a way to wrap Python integers out of the box but that's a half truth.\nThere's not a PyO3 API for it, but there's a Python C API function that does:\n\n```c\nunsigned long PyLong_AsUnsignedLongMask(PyObject *obj)\n```\n\nWe can call this function from Rust by using [`pyo3::ffi::PyLong_AsUnsignedLongMask`].\nThis is an *unsafe* function, which means we have to use an unsafe block to call it and take responsibility for upholding the contracts of this function.\nLet's review those contracts:\n\n- We must be attached to the interpreter.\n  If we're not, calling this function causes a data race.\n- The pointer must be valid, i.e. it must be properly aligned and point to a valid Python object.\n\nLet's create that helper function.\nThe signature has to be `fn(&Bound<'_, PyAny>) -> PyResult<T>`.\n\n- `&Bound<'_, PyAny>` represents a checked bound reference, so the pointer derived from it is valid (and not null).\n- Whenever we have bound references to Python objects in scope, it is guaranteed that we're attached to the interpreter.\n  This reference is also where we can get a [`Python`] token to use in our call to [`PyErr::take`].\n\n```rust,no_run\n# #![allow(dead_code)]\nuse std::ffi::c_ulong;\nuse pyo3::prelude::*;\nuse pyo3::ffi;\n\nfn wrap(obj: &Bound<'_, PyAny>) -> Result<i32, PyErr> {\n    let py: Python<'_> = obj.py();\n\n    unsafe {\n        let ptr = obj.as_ptr();\n\n        let ret: c_ulong = ffi::PyLong_AsUnsignedLongMask(ptr);\n        if ret == c_ulong::MAX {\n            if let Some(err) = PyErr::take(py) {\n                return Err(err);\n            }\n        }\n\n        Ok(ret as i32)\n    }\n}\n```\n\n[`PyErr::take`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/struct.PyErr.html#method.take\n[`Python`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html\n[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html\n[`pyo3::ffi::PyLong_AsUnsignedLongMask`]: {{#PYO3_DOCS_URL}}/pyo3/ffi/fn.PyLong_AsUnsignedLongMask.html\n"
  },
  {
    "path": "guide/src/class/object.md",
    "content": "# Basic object customization\n\nRecall the `Number` class from the previous chapter:\n\n```rust,no_run\n# #![allow(dead_code)]\n# fn main() {}\nuse pyo3::prelude::*;\n\n#[pyclass]\nstruct Number(i32);\n\n#[pymethods]\nimpl Number {\n    #[new]\n    fn new(value: i32) -> Self {\n        Self(value)\n    }\n}\n\n#[pymodule]\nmod my_module {\n    #[pymodule_export]\n    use super::Number;\n}\n```\n\nAt this point Python code can import the module, access the class and create class instances - but nothing else.\n\n```python\nfrom my_module import Number\n\nn = Number(5)\nprint(n)\n```\n\n```text\n<builtins.Number object at 0x000002B4D185D7D0>\n```\n\n## String representations\n\nIt can't even print an user-readable representation of itself!\nWe can fix that by defining the `__repr__` and `__str__` methods inside a `#[pymethods]` block.\nWe do this by accessing the value contained inside `Number`.\n\n```rust,no_run\n# use pyo3::prelude::*;\n#\n# #[pyclass]\n# struct Number(i32);\n#\n#[pymethods]\nimpl Number {\n    // For `__repr__` we want to return a string that Python code could use to recreate\n    // the `Number`, like `Number(5)` for example.\n    fn __repr__(&self) -> String {\n        // We use the `format!` macro to create a string. Its first argument is a\n        // format string, followed by any number of parameters which replace the\n        // `{}`'s in the format string.\n        //\n        //                       👇 Tuple field access in Rust uses a dot\n        format!(\"Number({})\", self.0)\n    }\n    // `__str__` is generally used to create an \"informal\" representation, so we\n    // just forward to `i32`'s `ToString` trait implementation to print a bare number.\n    fn __str__(&self) -> String {\n        self.0.to_string()\n    }\n}\n```\n\nTo automatically generate the `__str__` implementation using a `Display` trait implementation, pass the `str` argument to `pyclass`.\n\n```rust,no_run\n# use std::fmt::{Display, Formatter};\n# use pyo3::prelude::*;\n#\n# #[allow(dead_code)]\n#[pyclass(str)]\nstruct Coordinate {\n    x: i32,\n    y: i32,\n    z: i32,\n}\n\nimpl Display for Coordinate {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"({}, {}, {})\", self.x, self.y, self.z)\n    }\n}\n```\n\nFor convenience, a shorthand format string can be passed to `str` as `str=\"<format string>\"` for **structs only**.\nIt expands and is passed into the `format!` macro in the following ways:\n\n- `\"{x}\"` -> `\"{}\", self.x`\n- `\"{0}\"` -> `\"{}\", self.0`\n- `\"{x:?}\"` -> `\"{:?}\", self.x`\n\n*Note: Depending upon the format string you use, this may require implementation of the `Display` or `Debug` traits for the given Rust types.*\n*Note: the pyclass args `name` and `rename_all` are incompatible with the shorthand format string and will raise a compile time error.*\n\n```rust,no_run\n# use pyo3::prelude::*;\n#\n# #[allow(dead_code)]\n#[pyclass(str=\"({x}, {y}, {z})\")]\nstruct Coordinate {\n    x: i32,\n    y: i32,\n    z: i32,\n}\n```\n\n### Accessing the class name\n\nIn the `__repr__`, we used a hard-coded class name.\nThis is sometimes not ideal, because if the class is subclassed in Python, we would like the repr to reflect the subclass name.\nThis is typically done in Python code by accessing `self.__class__.__name__`.\nIn order to be able to access the Python type information *and* the Rust struct, we need to use a `Bound` as the `self` argument.\n\n```rust,no_run\n# use pyo3::prelude::*;\n# use pyo3::types::PyString;\n#\n# #[allow(dead_code)]\n# #[pyclass]\n# struct Number(i32);\n#\n#[pymethods]\nimpl Number {\n    fn __repr__(slf: &Bound<'_, Self>) -> PyResult<String> {\n        // This is the equivalent of `self.__class__.__name__` in Python.\n        let class_name: Bound<'_, PyString> = slf.get_type().qualname()?;\n        // To access fields of the Rust struct, we need to borrow from the Bound object.\n        Ok(format!(\"{}({})\", class_name, slf.borrow().0))\n    }\n}\n```\n\n### Hashing\n\nLet's also implement hashing.\nWe'll just hash the `i32`.\nFor that we need a [`Hasher`].\nThe one provided by `std` is [`DefaultHasher`], which uses the [SipHash] algorithm.\n\n```rust,no_run\nuse std::collections::hash_map::DefaultHasher;\n\n// Required to call the `.hash` and `.finish` methods, which are defined on traits.\nuse std::hash::{Hash, Hasher};\n\n# use pyo3::prelude::*;\n#\n# #[allow(dead_code)]\n# #[pyclass]\n# struct Number(i32);\n#\n#[pymethods]\nimpl Number {\n    fn __hash__(&self) -> u64 {\n        let mut hasher = DefaultHasher::new();\n        self.0.hash(&mut hasher);\n        hasher.finish()\n    }\n}\n```\n\nTo implement `__hash__` using the Rust [`Hash`] trait implementation, the `hash` option can be used.\nThis option is only available for `frozen` classes to prevent accidental hash changes from mutating the object.\nIf you need an `__hash__` implementation for a mutable class, use the manual method from above.\nThis option also requires `eq`: According to the [Python docs](https://docs.python.org/3/reference/datamodel.html#object.__hash__) \"If a class does not define an `__eq__()` method it should not define a `__hash__()` operation either\"\n\n```rust,no_run\n# use pyo3::prelude::*;\n#\n# #[allow(dead_code)]\n#[pyclass(frozen, eq, hash)]\n#[derive(PartialEq, Hash)]\nstruct Number(i32);\n```\n\n> [!NOTE]\n> When implementing `__hash__` and comparisons, it is important that the following property holds:\n>\n> ```text\n> k1 == k2 -> hash(k1) == hash(k2)\n> ```\n>\n> In other words, if two keys are equal, their hashes must also be equal. In addition you must take\n> care that your classes' hash doesn't change during its lifetime. In this tutorial we do that by not\n> letting Python code change our `Number` class. In other words, it is immutable.\n>\n> By default, all `#[pyclass]` types have a default hash implementation from Python.\n> Types which should not be hashable can override this by setting `__hash__` to None.\n> This is the same mechanism as for a pure-Python class. This is done like so:\n>\n> ```rust,no_run\n> # use pyo3::prelude::*;\n> #[pyclass]\n> struct NotHashable {}\n>\n> #[pymethods]\n> impl NotHashable {\n>     #[classattr]\n>     const __hash__: Option<Py<PyAny>> = None;\n> }\n> ```\n\n### Comparisons\n\nPyO3 supports the usual magic comparison methods available in Python such as `__eq__`, `__lt__` and so on.\nIt is also possible to support all six operations at once with `__richcmp__`.\nThis method will be called with a value of `CompareOp` depending on the operation.\n\n```rust,no_run\nuse pyo3::class::basic::CompareOp;\n\n# use pyo3::prelude::*;\n#\n# #[allow(dead_code)]\n# #[pyclass]\n# struct Number(i32);\n#\n#[pymethods]\nimpl Number {\n    fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult<bool> {\n        match op {\n            CompareOp::Lt => Ok(self.0 < other.0),\n            CompareOp::Le => Ok(self.0 <= other.0),\n            CompareOp::Eq => Ok(self.0 == other.0),\n            CompareOp::Ne => Ok(self.0 != other.0),\n            CompareOp::Gt => Ok(self.0 > other.0),\n            CompareOp::Ge => Ok(self.0 >= other.0),\n        }\n    }\n}\n```\n\nIf you obtain the result by comparing two Rust values, as in this example, you can take a shortcut using `CompareOp::matches`:\n\n```rust,no_run\nuse pyo3::class::basic::CompareOp;\n\n# use pyo3::prelude::*;\n#\n# #[allow(dead_code)]\n# #[pyclass]\n# struct Number(i32);\n#\n#[pymethods]\nimpl Number {\n    fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool {\n        op.matches(self.0.cmp(&other.0))\n    }\n}\n```\n\nIt checks that the `std::cmp::Ordering` obtained from Rust's `Ord` matches the given `CompareOp`.\n\nAlternatively, you can implement just equality using `__eq__`:\n\n```rust\n# use pyo3::prelude::*;\n#\n# #[pyclass]\n# struct Number(i32);\n#\n#[pymethods]\nimpl Number {\n    fn __eq__(&self, other: &Self) -> bool {\n        self.0 == other.0\n    }\n}\n\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| {\n#         let x = &Bound::new(py, Number(4))?;\n#         let y = &Bound::new(py, Number(4))?;\n#         assert!(x.eq(y)?);\n#         assert!(!x.ne(y)?);\n#         Ok(())\n#     })\n# }\n```\n\nTo implement `__eq__` using the Rust [`PartialEq`] trait implementation, the `eq` option can be used.\n\n```rust,no_run\n# use pyo3::prelude::*;\n#\n# #[allow(dead_code)]\n#[pyclass(eq)]\n#[derive(PartialEq)]\nstruct Number(i32);\n```\n\nTo implement `__lt__`, `__le__`, `__gt__`, & `__ge__` using the Rust `PartialOrd` trait implementation, the `ord` option can be used.\n*Note: Requires `eq`.*\n\n```rust,no_run\n# use pyo3::prelude::*;\n#\n# #[allow(dead_code)]\n#[pyclass(eq, ord)]\n#[derive(PartialEq, PartialOrd)]\nstruct Number(i32);\n```\n\n### Truthyness\n\nWe'll consider `Number` to be `True` if it is nonzero:\n\n```rust,no_run\n# use pyo3::prelude::*;\n#\n# #[allow(dead_code)]\n# #[pyclass]\n# struct Number(i32);\n#\n#[pymethods]\nimpl Number {\n    fn __bool__(&self) -> bool {\n        self.0 != 0\n    }\n}\n```\n\n### Final code\n\n```rust,no_run\n# fn main() {}\nuse std::collections::hash_map::DefaultHasher;\nuse std::hash::{Hash, Hasher};\n\nuse pyo3::prelude::*;\nuse pyo3::class::basic::CompareOp;\nuse pyo3::types::PyString;\n\n#[pyclass]\nstruct Number(i32);\n\n#[pymethods]\nimpl Number {\n    #[new]\n    fn new(value: i32) -> Self {\n        Self(value)\n    }\n\n    fn __repr__(slf: &Bound<'_, Self>) -> PyResult<String> {\n        let class_name: Bound<'_, PyString> = slf.get_type().qualname()?;\n        Ok(format!(\"{}({})\", class_name, slf.borrow().0))\n    }\n\n    fn __str__(&self) -> String {\n        self.0.to_string()\n    }\n\n    fn __hash__(&self) -> u64 {\n        let mut hasher = DefaultHasher::new();\n        self.0.hash(&mut hasher);\n        hasher.finish()\n    }\n\n    fn __richcmp__(&self, other: &Self, op: CompareOp) -> PyResult<bool> {\n        match op {\n            CompareOp::Lt => Ok(self.0 < other.0),\n            CompareOp::Le => Ok(self.0 <= other.0),\n            CompareOp::Eq => Ok(self.0 == other.0),\n            CompareOp::Ne => Ok(self.0 != other.0),\n            CompareOp::Gt => Ok(self.0 > other.0),\n            CompareOp::Ge => Ok(self.0 >= other.0),\n        }\n    }\n\n    fn __bool__(&self) -> bool {\n        self.0 != 0\n    }\n}\n\n#[pymodule]\nmod my_module {\n    #[pymodule_export]\n    use super::Number;\n}\n```\n\n[`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html\n[`Hasher`]: https://doc.rust-lang.org/std/hash/trait.Hasher.html\n[`DefaultHasher`]: https://doc.rust-lang.org/std/collections/hash_map/struct.DefaultHasher.html\n[SipHash]: https://en.wikipedia.org/wiki/SipHash\n[`PartialEq`]: https://doc.rust-lang.org/stable/std/cmp/trait.PartialEq.html\n"
  },
  {
    "path": "guide/src/class/protocols.md",
    "content": "# Class customizations\n\nPython's object model defines several protocols for different object behavior, such as the sequence, mapping, and number protocols.\nPython classes support these protocols by implementing \"magic\" methods, such as `__str__` or `__repr__`.\nBecause of the double-underscores surrounding their name, these are also known as \"dunder\" methods.\n\nPyO3 makes it possible for every magic method to be implemented in `#[pymethods]` just as they would be done in a regular Python class, with a few notable differences:\n\n- `__new__` is replaced by the [`#[new]` attribute](../class.md#constructor).\n- `__del__` is not yet supported, but may be in the future.\n- `__buffer__` and `__release_buffer__` are currently not supported and instead PyO3 supports [`__getbuffer__` and `__releasebuffer__`](#buffer-objects) methods (these predate [PEP 688](https://peps.python.org/pep-0688/#python-level-buffer-protocol)), again this may change in the future.\n- PyO3 adds [`__traverse__` and `__clear__`](#garbage-collector-integration) methods for controlling garbage collection.\n- The Python C-API which PyO3 is implemented upon requires many magic methods to have a specific function signature in C and be placed into special \"slots\" on the class type object.\n  This limits the allowed argument and return types for these methods.\n  They are listed in detail in the section below.\n\nIf a magic method is not on the list above (for example `__init_subclass__`), then it should just work in PyO3.\nIf this is not the case, please file a bug report.\n\n## Magic Methods handled by PyO3\n\nIf a function name in `#[pymethods]` is a magic method which is known to need special handling, it will be automatically placed into the correct slot in the Python type object.\nThe function name is taken from the usual rules for naming `#[pymethods]`: the `#[pyo3(name = \"...\")]` attribute is used if present, otherwise the Rust function name is used.\n\nThe magic methods handled by PyO3 are very similar to the standard Python ones on [this page](https://docs.python.org/3/reference/datamodel.html#special-method-names) - in particular they are the subset which have slots as [defined here](https://docs.python.org/3/c-api/typeobj.html).\n\nWhen PyO3 handles a magic method, a couple of changes apply compared to other `#[pymethods]`:\n\n- The Rust function signature is restricted to match the magic method.\n- The `#[pyo3(signature = (...)]` and `#[pyo3(text_signature = \"...\")]` attributes are not allowed.\n\nThe following sections list all magic methods for which PyO3 implements the necessary special handling.\nThe given signatures should be interpreted as follows:\n\n- All methods take a receiver as first argument, shown as `<self>`.\n   It can be `&self`, `&mut self` or a `Bound` reference like `self_: PyRef<'_, Self>` and `self_: PyRefMut<'_, Self>`, as described [in the parent section](../class.md#inheritance).\n- An optional `Python<'py>` argument is always allowed as the first argument.\n- Return values can be optionally wrapped in `PyResult`.\n- `object` means that any type is allowed that can be extracted from a Python\n   object (if argument) or converted to a Python object (if return value).\n- Other types must match what's given, e.g. `pyo3::basic::CompareOp` for\n   `__richcmp__`'s second argument.\n- For the comparison and arithmetic methods, extraction errors are not\n   propagated as exceptions, but lead to a return of `NotImplemented`.\n- For some magic methods, the return values are not restricted by PyO3, but checked by the Python interpreter.\n   For example, `__str__` needs to return a string object.\n   This is indicated by `object (Python type)`.\n\n### Basic object customization\n\n- `__str__(<self>) -> object (str)`\n- `__repr__(<self>) -> object (str)`\n\n<!-- rumdl-disable MD013 -->\n<!-- TODO: report false positive -->\n- `__hash__(<self>) -> isize`\n\n  Objects that compare equal must have the same hash value.\n  Any type up to 64 bits may be returned instead of `isize`, PyO3 will convert to an isize automatically (wrapping unsigned types like `u64` and `usize`).\n\n  <details>\n  <summary>Disabling Python's default hash</summary>\n\n  By default, all `#[pyclass]` types have a default hash implementation from Python.\n  Types which should not be hashable can override this by setting `__hash__` to `None`.\n  This is the same mechanism as for a pure-Python class.\n  This is done like so:\n\n  ```rust,no_run\n  # use pyo3::prelude::*;\n  #\n  #[pyclass]\n  struct NotHashable {}\n\n  #[pymethods]\n  impl NotHashable {\n      #[classattr]\n      const __hash__: Option<Py<PyAny>> = None;\n  }\n  ```\n\n  </details>\n\n<!-- rumdl-enable MD013 -->\n\n- `__lt__(<self>, object) -> object`\n- `__le__(<self>, object) -> object`\n- `__eq__(<self>, object) -> object`\n- `__ne__(<self>, object) -> object`\n- `__gt__(<self>, object) -> object`\n- `__ge__(<self>, object) -> object`\n\n    The implementations of Python's \"rich comparison\" operators `<`, `<=`, `==`, `!=`, `>` and `>=` respectively.\n\n    *Note that implementing any of these methods will cause Python not to generate a default `__hash__` implementation, so consider also implementing `__hash__`.*\n\n    <details>\n    <summary>Return type</summary>\n\n    The return type will normally be `bool` or `PyResult<bool>`, however any Python object can be returned.\n    </details>\n\n<!-- rumdl-disable MD013 -->\n<!-- TODO: report false positive -->\n\n- `__richcmp__(<self>, object, pyo3::basic::CompareOp) -> object`\n\n    Implements Python comparison operations (`==`, `!=`, `<`, `<=`, `>`, and `>=`) in a single method.\n    The `CompareOp` argument indicates the comparison operation being performed.\n    You can use [`CompareOp::matches`] to adapt a Rust `std::cmp::Ordering` result to the requested comparison.\n\n    *This method cannot be implemented in combination with any of `__lt__`, `__le__`, `__eq__`, `__ne__`, `__gt__`, or `__ge__`.*\n\n    *Note that implementing `__richcmp__` will cause Python not to generate a default `__hash__` implementation, so consider implementing `__hash__` when implementing `__richcmp__`.*\n\n    <details>\n    <summary>Return type</summary>\n\n    The return type will normally be `PyResult<bool>`, but any Python object can be returned.\n\n    If you want to leave some operations unimplemented, you can return `py.NotImplemented()`\n    for some of the operations:\n\n    ```rust,no_run\n    use pyo3::class::basic::CompareOp;\n    use pyo3::types::PyNotImplemented;\n\n    # use pyo3::prelude::*;\n    # use pyo3::BoundObject;\n    #\n    # #[pyclass]\n    # struct Number(i32);\n    #\n    #[pymethods]\n    impl Number {\n        fn __richcmp__<'py>(&self, other: &Self, op: CompareOp, py: Python<'py>) -> PyResult<Borrowed<'py, 'py, PyAny>> {\n            match op {\n                CompareOp::Eq => Ok((self.0 == other.0).into_pyobject(py)?.into_any()),\n                CompareOp::Ne => Ok((self.0 != other.0).into_pyobject(py)?.into_any()),\n                _ => Ok(PyNotImplemented::get(py).into_any()),\n            }\n        }\n    }\n    ```\n\n    If the second argument `object` is not of the type specified in the signature, the generated code will automatically `return NotImplemented`.\n    </details>\n\n<!-- rumdl-enable MD013 -->\n\n- `__getattr__(<self>, object) -> object`\n- `__getattribute__(<self>, object) -> object`\n\n    <details>\n    <summary>Differences between <code>__getattr__</code> and <code>__getattribute__</code></summary>\n\n    As in Python, `__getattr__` is only called if the attribute is not found\n    by normal attribute lookup. `__getattribute__`, on the other hand, is\n    called for *every* attribute access. If it wants to access existing\n    attributes on `self`, it needs to be very careful not to introduce\n    infinite recursion, and use `baseclass.__getattribute__()`.\n    </details>\n\n- `__setattr__(<self>, value: object) -> ()`\n- `__delattr__(<self>, object) -> ()`\n\n    Overrides attribute access.\n\n- `__bool__(<self>) -> bool`\n\n    Determines the \"truthyness\" of an object.\n\n- `__call__(<self>, ...) -> object` - here, any argument list can be defined\n    as for normal `pymethods`\n\n### Iterable objects\n\nIterators can be defined using these methods:\n\n- `__iter__(<self>) -> object`\n- `__next__(<self>) -> Option<object> or IterNextOutput` ([see details](#returning-a-value-from-iteration))\n\nReturning `None` from `__next__` indicates that that there are no further items.\n\nExample:\n\n```rust,no_run\nuse pyo3::prelude::*;\n\nuse std::sync::Mutex;\n\n#[pyclass]\nstruct MyIterator {\n    iter: Mutex<Box<dyn Iterator<Item = Py<PyAny>> + Send>>,\n}\n\n#[pymethods]\nimpl MyIterator {\n    fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {\n        slf\n    }\n    fn __next__(slf: PyRefMut<'_, Self>) -> Option<Py<PyAny>> {\n        slf.iter.lock().unwrap().next()\n    }\n}\n```\n\nIn many cases you'll have a distinction between the type being iterated over (i.e. the *iterable*) and the iterator it provides.\nIn this case, the iterable only needs to implement `__iter__()` while the iterator must implement both `__iter__()` and `__next__()`.\nFor example:\n\n```rust,no_run\n# use pyo3::prelude::*;\n\n#[pyclass]\nstruct Iter {\n    inner: std::vec::IntoIter<usize>,\n}\n\n#[pymethods]\nimpl Iter {\n    fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {\n        slf\n    }\n\n    fn __next__(mut slf: PyRefMut<'_, Self>) -> Option<usize> {\n        slf.inner.next()\n    }\n}\n\n#[pyclass]\nstruct Container {\n    iter: Vec<usize>,\n}\n\n#[pymethods]\nimpl Container {\n    fn __iter__(slf: PyRef<'_, Self>) -> PyResult<Py<Iter>> {\n        let iter = Iter {\n            inner: slf.iter.clone().into_iter(),\n        };\n        Py::new(slf.py(), iter)\n    }\n}\n\n# Python::attach(|py| {\n#     let container = Container { iter: vec![1, 2, 3, 4] };\n#     let inst = pyo3::Py::new(py, container).unwrap();\n#     pyo3::py_run!(py, inst, \"assert list(inst) == [1, 2, 3, 4]\");\n#     pyo3::py_run!(py, inst, \"assert list(iter(iter(inst))) == [1, 2, 3, 4]\");\n# });\n```\n\nFor more details on Python's iteration protocols, check out [the \"Iterator Types\" section of the library documentation](https://docs.python.org/library/stdtypes.html#iterator-types).\n\n#### Returning a value from iteration\n\nThis guide has so far shown how to use `Option<T>` to implement yielding values during iteration.\nIn Python a generator can also return a value.\nThis is done by raising a `StopIteration` exception.\nTo express this in Rust, return `PyResult::Err` with a `PyStopIteration` as the error.\n\n### Awaitable objects\n\n- `__await__(<self>) -> object`\n- `__aiter__(<self>) -> object`\n- `__anext__(<self>) -> Option<object>`\n\n### Mapping & Sequence types\n\nThe magic methods in this section can be used to implement Python container types.\nThey are two main categories of container in Python: \"mappings\" such as `dict`, with arbitrary keys, and \"sequences\" such as `list` and `tuple`, with integer keys.\n\nThe Python C-API which PyO3 is built upon has separate \"slots\" for sequences and mappings.\nWhen writing a `class` in pure Python, there is no such distinction in the implementation - a `__getitem__` implementation will fill the slots for both the mapping and sequence forms, for example.\n\nBy default PyO3 reproduces the Python behaviour of filling both mapping and sequence slots.\nThis makes sense for the \"simple\" case which matches Python, and also for sequences, where the mapping slot is used anyway to implement slice indexing.\n\nMapping types usually will not want the sequence slots filled.\nHaving them filled will lead to outcomes which may be unwanted, such as:\n\n- The mapping type will successfully cast to [`PySequence`].\n  This may lead to consumers of the type handling it incorrectly.\n- Python provides a default implementation of `__iter__` for sequences, which calls `__getitem__` with consecutive positive integers starting from 0 until an `IndexError` is returned.\n  Unless the mapping only contains consecutive positive integer keys, this `__iter__` implementation will likely not be the intended behavior.\n\nUse the `#[pyclass(mapping)]` annotation to instruct PyO3 to only fill the mapping slots, leaving the sequence ones empty.\nThis will apply to `__getitem__`, `__setitem__`, and `__delitem__`.\n\nUse the `#[pyclass(sequence)]` annotation to instruct PyO3 to fill the `sq_length` slot instead of the `mp_length` slot for `__len__`.\nThis will help libraries such as `numpy` recognise the class as a sequence, however will also cause CPython to automatically add the sequence length to any negative indices before passing them to `__getitem__`. (`__getitem__`, `__setitem__` and `__delitem__` mapping slots are still used for sequences, for slice operations.)\n\n- `__len__(<self>) -> usize`\n\n    Implements the built-in function `len()`.\n\n<!-- rumdl-disable MD013 -->\n<!-- TODO: report false positive -->\n\n- `__contains__(<self>, object) -> bool`\n\n    Implements membership test operators.\n    Should return true if `item` is in `self`, false otherwise.\n    For objects that don’t define `__contains__()`, the membership test simply traverses the sequence until it finds a match.\n\n    <details>\n    <summary>Disabling Python's default contains</summary>\n\n    By default, all `#[pyclass]` types with an `__iter__` method support a\n    default implementation of the `in` operator. Types which do not want this\n    can override this by setting `__contains__` to `None`. This is the same\n    mechanism as for a pure-Python class. This is done like so:\n\n    ```rust,no_run\n    # use pyo3::prelude::*;\n    #\n    #[pyclass]\n    struct NoContains {}\n\n    #[pymethods]\n    impl NoContains {\n        #[classattr]\n        const __contains__: Option<Py<PyAny>> = None;\n    }\n    ```\n\n    </details>\n\n<!-- rumdl-enable MD013 -->\n\n- `__getitem__(<self>, object) -> object`\n\n    Implements retrieval of the `self[a]` element.\n\n    *Note:* Negative integer indexes are not handled specially by PyO3.\n    However, for classes with `#[pyclass(sequence)]`, when a negative index is accessed via `PySequence::get_item`, the underlying C API already adjusts the index to be positive.\n\n- `__setitem__(<self>, object, object) -> ()`\n\n    Implements assignment to the `self[a]` element.\n    Should only be implemented if elements can be replaced.\n\n    Same behavior regarding negative indices as for `__getitem__`.\n\n- `__delitem__(<self>, object) -> ()`\n\n    Implements deletion of the `self[a]` element.\n    Should only be implemented if elements can be deleted.\n\n    Same behavior regarding negative indices as for `__getitem__`.\n\n- `fn __concat__(&self, other: impl FromPyObject) -> PyResult<impl ToPyObject>`\n\n    Concatenates two sequences.\n    Used by the `+` operator, after trying the numeric addition via the `__add__` and `__radd__` methods.\n\n- `fn __repeat__(&self, count: isize) -> PyResult<impl ToPyObject>`\n\n    Repeats the sequence `count` times.\n    Used by the `*` operator, after trying the numeric multiplication via the `__mul__` and `__rmul__` methods.\n\n- `fn __inplace_concat__(&self, other: impl FromPyObject) -> PyResult<impl ToPyObject>`\n\n    Concatenates two sequences.\n    Used by the `+=` operator, after trying the numeric addition via the `__iadd__` method.\n\n- `fn __inplace_repeat__(&self, count: isize) -> PyResult<impl ToPyObject>`\n\n    Concatenates two sequences.\n    Used by the `*=` operator, after trying the numeric multiplication via the `__imul__` method.\n\n### Descriptors\n\n- `__get__(<self>, object, object) -> object`\n- `__set__(<self>, object, object) -> ()`\n- `__delete__(<self>, object) -> ()`\n\n### Numeric types\n\nBinary arithmetic operations (`+`, `-`, `*`, `@`, `/`, `//`, `%`, `divmod()`, `pow()` and `**`, `<<`, `>>`, `&`, `^`, and `|`) and their reflected versions:\n\n(If the `object` is not of the type specified in the signature, the generated code will automatically `return NotImplemented`.)\n\n- `__add__(<self>, object) -> object`\n- `__radd__(<self>, object) -> object`\n- `__sub__(<self>, object) -> object`\n- `__rsub__(<self>, object) -> object`\n- `__mul__(<self>, object) -> object`\n- `__rmul__(<self>, object) -> object`\n- `__matmul__(<self>, object) -> object`\n- `__rmatmul__(<self>, object) -> object`\n- `__floordiv__(<self>, object) -> object`\n- `__rfloordiv__(<self>, object) -> object`\n- `__truediv__(<self>, object) -> object`\n- `__rtruediv__(<self>, object) -> object`\n- `__divmod__(<self>, object) -> object`\n- `__rdivmod__(<self>, object) -> object`\n- `__mod__(<self>, object) -> object`\n- `__rmod__(<self>, object) -> object`\n- `__lshift__(<self>, object) -> object`\n- `__rlshift__(<self>, object) -> object`\n- `__rshift__(<self>, object) -> object`\n- `__rrshift__(<self>, object) -> object`\n- `__and__(<self>, object) -> object`\n- `__rand__(<self>, object) -> object`\n- `__xor__(<self>, object) -> object`\n- `__rxor__(<self>, object) -> object`\n- `__or__(<self>, object) -> object`\n- `__ror__(<self>, object) -> object`\n- `__pow__(<self>, object, object) -> object`\n- `__rpow__(<self>, object, object) -> object`\n\nIn-place assignment operations (`+=`, `-=`, `*=`, `@=`, `/=`, `//=`, `%=`, `**=`, `<<=`, `>>=`, `&=`, `^=`, `|=`):\n\n- `__iadd__(<self>, object) -> ()`\n- `__isub__(<self>, object) -> ()`\n- `__imul__(<self>, object) -> ()`\n- `__imatmul__(<self>, object) -> ()`\n- `__itruediv__(<self>, object) -> ()`\n- `__ifloordiv__(<self>, object) -> ()`\n- `__imod__(<self>, object) -> ()`\n- `__ipow__(<self>, object, object) -> ()`\n- `__ilshift__(<self>, object) -> ()`\n- `__irshift__(<self>, object) -> ()`\n- `__iand__(<self>, object) -> ()`\n- `__ixor__(<self>, object) -> ()`\n- `__ior__(<self>, object) -> ()`\n\nUnary operations (`-`, `+`, `abs()` and `~`):\n\n- `__pos__(<self>) -> object`\n- `__neg__(<self>) -> object`\n- `__abs__(<self>) -> object`\n- `__invert__(<self>) -> object`\n\nCoercions:\n\n- `__index__(<self>) -> object (int)`\n- `__int__(<self>) -> object (int)`\n- `__float__(<self>) -> object (float)`\n\n### Buffer objects\n\n- `__getbuffer__(<self>, *mut ffi::Py_buffer, flags) -> ()`\n- `__releasebuffer__(<self>, *mut ffi::Py_buffer) -> ()` Errors returned from `__releasebuffer__` will be sent to `sys.unraiseablehook`.\n    It is strongly advised to never return an error from `__releasebuffer__`, and if it really is necessary, to make best effort to perform any required freeing operations before returning.\n    `__releasebuffer__` will not be called a second time; anything not freed will be leaked.\n\n### Garbage Collector Integration\n\nIf your type owns references to other Python objects, you will need to integrate with Python's garbage collector so that the GC is aware of those references.\nTo do this, implement the two methods `__traverse__` and `__clear__`.\nThese correspond to the slots `tp_traverse` and `tp_clear` in the Python C API.\n`__traverse__` must call `visit.call()` for each reference to another Python object.\n`__clear__` must clear out any mutable references to other Python objects (thus breaking reference cycles).\nImmutable references do not have to be cleared, as every cycle must contain at least one mutable reference.\n\n- `__traverse__(<self>, pyo3::class::gc::PyVisit<'_>) -> Result<(), pyo3::class::gc::PyTraverseError>`\n- `__clear__(<self>) -> ()`\n\n> [!NOTE]\n> `__traverse__` does not work with [`#[pyo3(warn(...))]`](../function.md#warn).\n\nExample:\n\n```rust,no_run\nuse pyo3::prelude::*;\nuse pyo3::PyTraverseError;\nuse pyo3::gc::PyVisit;\n\n#[pyclass]\nstruct ClassWithGCSupport {\n    obj: Option<Py<PyAny>>,\n}\n\n#[pymethods]\nimpl ClassWithGCSupport {\n    fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n        visit.call(&self.obj)?;\n        Ok(())\n    }\n\n    fn __clear__(&mut self) {\n        // Clear reference, this decrements ref counter.\n        self.obj = None;\n    }\n}\n```\n\n> [!NOTE]\n> When a class inherits from either a Python builtins type or another type declared in Rust and implement either or both `__traverse__` and `__clear__`, the parent class `__traverse__` and `__clear__` is called automatically.\n> There is no need to explicitly call it from inside the class implementation.\n\nUsually, an implementation of `__traverse__` should do nothing but calls to `visit.call`.\nMost importantly, safe access to the interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic.\n\n> [!NOTE]\n> These methods are part of the C API, PyPy does not necessarily honor them. If you are building for PyPy you should measure memory consumption to make sure you do not have runaway memory growth. See [this issue on the PyPy bug tracker](https://github.com/pypy/pypy/issues/3848).\n\n[`PySequence`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PySequence.html\n[`CompareOp::matches`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass/enum.CompareOp.html#method.matches\n"
  },
  {
    "path": "guide/src/class/thread-safety.md",
    "content": "# `#[pyclass]` thread safety\n\nPython objects are freely shared between threads by the Python interpreter.\nThis means that:\n\n- there is no control which thread might eventually drop the `#[pyclass]` object, meaning `Send` is required.\n- multiple threads can potentially be reading the `#[pyclass]` data simultaneously, meaning `Sync` is required.\n\nThis section of the guide discusses various data structures which can be used to make types satisfy these requirements.\n\nIn special cases where it is known that your Python application is never going to use threads (this is rare!), these thread-safety requirements can be opted-out with [`#[pyclass(unsendable)]`](../class.md#customizing-the-class), at the cost of making concurrent access to the Rust data be runtime errors.\nThis is only for very specific use cases; it is almost always better to make proper thread-safe types.\n\n## Making `#[pyclass]` types thread-safe\n\nThe general challenge with thread-safety is to make sure that two threads cannot produce a data race, i.e. unsynchronized writes to the same data at the same time.\nA data race produces an unpredictable result and is forbidden by Rust.\n\nBy default, `#[pyclass]` employs an [\"interior mutability\" pattern](../class.md#bound-and-interior-mutability) to allow for either multiple `&T` references or a single exclusive `&mut T` reference to access the data.\nThis allows for simple `#[pyclass]` types to be thread-safe automatically, at the cost of runtime checking for concurrent access.\nErrors will be raised if the usage overlaps.\n\nFor example, the below simple class is thread-safe:\n\n```rust,no_run\n# use pyo3::prelude::*;\n\n#[pyclass]\nstruct MyClass {\n    x: i32,\n    y: i32,\n}\n\n#[pymethods]\nimpl MyClass {\n    fn get_x(&self) -> i32 {\n        self.x\n    }\n\n    fn set_y(&mut self, value: i32) {\n        self.y = value;\n    }\n}\n```\n\nIn the above example, if calls to `get_x` and `set_y` overlap (from two different threads) then at least one of those threads will experience a runtime error indicating that the data was \"already borrowed\".\n\nTo avoid these errors, you can take control of the interior mutability yourself in one of the following ways.\n\n### Using atomic data structures\n\nTo remove the possibility of having overlapping `&self` and `&mut self` references produce runtime errors, consider using `#[pyclass(frozen)]` and use [atomic data structures](https://doc.rust-lang.org/std/sync/atomic/) to control modifications directly.\n\nFor example, a thread-safe version of the above `MyClass` using atomic integers would be as follows:\n\n```rust,no_run\n# use pyo3::prelude::*;\nuse std::sync::atomic::{AtomicI32, Ordering};\n\n#[pyclass(frozen)]\nstruct MyClass {\n    x: AtomicI32,\n    y: AtomicI32,\n}\n\n#[pymethods]\nimpl MyClass {\n    fn get_x(&self) -> i32 {\n        self.x.load(Ordering::Relaxed)\n    }\n\n    fn set_y(&self, value: i32) {\n        self.y.store(value, Ordering::Relaxed)\n    }\n}\n```\n\n### Using locks\n\nAn alternative to atomic data structures is to use [locks](https://doc.rust-lang.org/std/sync/struct.Mutex.html) to make threads wait for access to shared data.\n\nFor example, a thread-safe version of the above `MyClass` using locks would be as follows:\n\n```rust,no_run\n# use pyo3::prelude::*;\nuse std::sync::Mutex;\n\nstruct MyClassInner {\n    x: i32,\n    y: i32,\n}\n\n#[pyclass(frozen)]\nstruct MyClass {\n    inner: Mutex<MyClassInner>\n}\n\n#[pymethods]\nimpl MyClass {\n    fn get_x(&self) -> i32 {\n        self.inner.lock().expect(\"lock not poisoned\").x\n    }\n\n    fn set_y(&self, value: i32) {\n        self.inner.lock().expect(\"lock not poisoned\").y = value;\n    }\n}\n```\n\nIf you need to lock around state stored in the Python interpreter or otherwise call into the Python C API while a lock is held, you might find the `MutexExt` trait useful.\nIt provides a `lock_py_attached` method for `std::sync::Mutex` that avoids deadlocks with the GIL or other global synchronization events in the interpreter.\nAdditionally, support for the `parking_lot` and `lock_api` synchronization libraries is gated behind the `parking_lot` and `lock_api` features.\nYou can also enable the `arc_lock` feature if you need the `arc_lock` features of either library.\n\n### Wrapping unsynchronized data\n\nIn some cases, the data structures stored within a `#[pyclass]` may themselves not be thread-safe.\nRust will therefore not implement `Send` and `Sync` on the `#[pyclass]` type.\n\nTo achieve thread-safety, a manual `Send` and `Sync` implementation is required which is `unsafe` and should only be done following careful review of the soundness of the implementation.\nDoing this for PyO3 types is no different than for any other Rust code, [the Rustonomicon](https://doc.rust-lang.org/nomicon/send-and-sync.html) has a great discussion on this.\n"
  },
  {
    "path": "guide/src/class.md",
    "content": "# Python classes\n\nPyO3 exposes a group of attributes powered by Rust's proc macro system for defining Python classes as Rust structs.\n\nThe main attribute is `#[pyclass]`, which is placed upon a Rust `struct` or `enum` to generate a Python type for it.\nThey will usually also have *one* `#[pymethods]`-annotated `impl` block for the struct, which is used to define Python methods and constants for the generated Python type. (If the [`multiple-pymethods`] feature is enabled, each `#[pyclass]` is allowed to have multiple `#[pymethods]` blocks.) `#[pymethods]` may also have implementations for Python magic methods such as `__str__`.\n\nThis chapter will discuss the functionality and configuration these attributes offer.\nBelow is a list of links to the relevant section of this chapter for each:\n\n- [`#[pyclass]`](#defining-a-new-class)\n  - [`#[pyo3(get, set)]`](#object-properties-using-pyo3get-set)\n- [`#[pymethods]`](#instance-methods)\n  - [`#[new]`](#constructor)\n  - [`#[getter]`](#object-properties-using-getter-and-setter)\n  - [`#[setter]`](#object-properties-using-getter-and-setter)\n  - [`#[deleter]`](#object-properties-using-getter-and-setter)\n  - [`#[staticmethod]`](#static-methods)\n  - [`#[classmethod]`](#class-methods)\n  - [`#[classattr]`](#class-attributes)\n  - [`#[args]`](#method-arguments)\n- [Magic methods and slots](class/protocols.md)\n- [Classes as function arguments](#classes-as-function-arguments)\n\n## Defining a new class\n\nTo define a custom Python class, add the `#[pyclass]` attribute to a Rust struct or enum.\n\n```rust\n# #![allow(dead_code)]\nuse pyo3::prelude::*;\n\n#[pyclass]\nstruct MyClass {\n    inner: i32,\n}\n\n// A \"tuple\" struct\n#[pyclass]\nstruct Number(i32);\n\n// PyO3 supports unit-only enums (which contain only unit variants)\n// These simple enums behave similarly to Python's enumerations (enum.Enum)\n#[pyclass(eq, eq_int)]\n#[derive(PartialEq)]\nenum MyEnum {\n    Variant,\n    OtherVariant = 30, // PyO3 supports custom discriminants.\n}\n\n// PyO3 supports custom discriminants in unit-only enums\n#[pyclass(eq, eq_int)]\n#[derive(PartialEq)]\nenum HttpResponse {\n    Ok = 200,\n    NotFound = 404,\n    Teapot = 418,\n    // ...\n}\n\n// PyO3 also supports enums with Struct and Tuple variants\n// These complex enums have slightly different behavior from the simple enums above\n// They are meant to work with instance checks and match statement patterns\n// The variants can be mixed and matched\n// Struct variants have named fields while tuple enums generate generic names for fields in order _0, _1, _2, ...\n// Apart from this both types are functionally identical\n#[pyclass]\nenum Shape {\n    Circle { radius: f64 },\n    Rectangle { width: f64, height: f64 },\n    RegularPolygon(u32, f64),\n    Nothing(),\n}\n```\n\nThe above example generates implementations for [`PyTypeInfo`] and [`PyClass`] for `MyClass`, `Number`, `MyEnum`, `HttpResponse`, and `Shape`.\nTo see these generated implementations, refer to the [implementation details](#implementation-details) at the end of this chapter.\n\n### Restrictions\n\nTo integrate Rust types with Python, PyO3 needs to place some restrictions on the types which can be annotated with `#[pyclass]`.\nIn particular, they must have no lifetime parameters, no generic parameters, and must be thread-safe.\nThe reason for each of these is explained below.\n\n#### No lifetime parameters\n\nRust lifetimes are used by the Rust compiler to reason about a program's memory safety.\nThey are a compile-time only concept; there is no way to access Rust lifetimes at runtime from a dynamic language like Python.\n\nAs soon as Rust data is exposed to Python, there is no guarantee that the Rust compiler can make on how long the data will live.\nPython is a reference-counted language and those references can be held for an arbitrarily long time which is untraceable by the Rust compiler.\nThe only possible way to express this correctly is to require that any `#[pyclass]` does not borrow data for any lifetime shorter than the `'static` lifetime, i.e. the `#[pyclass]` cannot have any lifetime parameters.\n\nWhen you need to share ownership of data between Python and Rust, instead of using borrowed references with lifetimes consider using reference-counted smart pointers such as [`Arc`] or [`Py`][`Py<T>`].\n\n#### No generic parameters\n\nA Rust `struct Foo<T>` with a generic parameter `T` generates new compiled implementations each time it is used with a different concrete type for `T`.\nThese new implementations are generated by the compiler at each usage site.\nThis is incompatible with wrapping `Foo` in Python, where there needs to be a single compiled implementation of `Foo` which is integrated with the Python interpreter.\n\nCurrently, the best alternative is to write a macro which expands to a new `#[pyclass]` for each instantiation you want:\n\n```rust\n# #![allow(dead_code)]\nuse pyo3::prelude::*;\n\nstruct GenericClass<T> {\n    data: T,\n}\n\nmacro_rules! create_interface {\n    ($name: ident, $type: ident) => {\n        #[pyclass]\n        pub struct $name {\n            inner: GenericClass<$type>,\n        }\n        #[pymethods]\n        impl $name {\n            #[new]\n            pub fn new(data: $type) -> Self {\n                Self {\n                    inner: GenericClass { data: data },\n                }\n            }\n        }\n    };\n}\n\ncreate_interface!(IntClass, i64);\ncreate_interface!(FloatClass, String);\n```\n\n#### Must be thread-safe\n\nPython objects are freely shared between threads by the Python interpreter.\nThis means that:\n\n- Python objects may be created and destroyed by different Python threads; therefore `#[pyclass]` objects must be `Send`.\n- Python objects may be accessed by multiple Python threads simultaneously; therefore `#[pyclass]` objects must be `Sync`.\n\nFor now, don't worry about these requirements; simple classes will already be thread-safe.\nThere is a [detailed discussion on thread-safety](./class/thread-safety.md) later in the guide.\n\n## Constructor\n\nBy default, it is not possible to create an instance of a custom class from Python code.\nTo declare a constructor, you need to define a method and annotate it with the `#[new]` attribute.\nA constructor is accessible as Python's `__new__` method.\n\n```rust\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# #[pyclass]\n# struct Number(i32);\n#\n#[pymethods]\nimpl Number {\n    #[new]\n    fn new(value: i32) -> Self {\n        Number(value)\n    }\n}\n```\n\nAlternatively, if your `new` method may fail you can return `PyResult<Self>`.\n\n```rust\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use pyo3::exceptions::PyValueError;\n# #[pyclass]\n# struct Nonzero(i32);\n#\n#[pymethods]\nimpl Nonzero {\n    #[new]\n    fn py_new(value: i32) -> PyResult<Self> {\n        if value == 0 {\n            Err(PyValueError::new_err(\"cannot be zero\"))\n        } else {\n            Ok(Nonzero(value))\n        }\n    }\n}\n```\n\nIf you want to return an existing object (for example, because your `new` method caches the values it returns), `new` can return `pyo3::Py<Self>`.\n\nAs you can see, the Rust method name is not important here; this way you can still, use `new()` for a Rust-level constructor.\n\nIf no method marked with `#[new]` is declared, object instances can only be created from Rust, but not from Python.\n\nFor arguments, see the [`Method arguments`](#method-arguments) section below.\n\n## Initializer\n\nAn initializer implements Python's `__init__` method.\n\nIt may be required when it's needed to control an object initalization flow on the Rust code.\nIf possible handling this in `__new__` should be preferred, but in some cases, like subclassing native types, overwriting `__init__` might be necessary.\nFor example, you define a class that extends `PyDict` and don't want that the original `__init__` method of `PyDict` been called.\nIn this case by defining an own `__init__` method it's possible to stop initialization flow.\n\nIf you declare an `__init__` method you may need to call a super class' `__init__` method explicitly like in Python code.\n\nTo declare an initializer, you need to define the `__init__` method.\nLike in Python `__init__` must have the `self` receiver as the first argument, followed by the same arguments as the constructor.\nIt can either return `()` or `PyResult<()>`.\n\n```rust\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\nuse pyo3::types::{PyDict, PyTuple, PySuper};\n# #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\nuse crate::pyo3::PyTypeInfo;\n\n# #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\n#[pyclass(extends = PyDict)]\nstruct MyDict;\n\n# #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\n#[pymethods]\nimpl MyDict {\n#   #[allow(unused_variables)]\n    #[new]\n    #[pyo3(signature = (*args, **kwargs))]\n    fn __new__(\n        args: &Bound<'_, PyTuple>,\n        kwargs: Option<&Bound<'_, PyDict>>,\n    ) -> PyResult<Self> {\n        Ok(Self)\n    }\n\n    #[pyo3(signature = (*args, **kwargs))]\n    fn __init__(\n        slf: &Bound<'_, Self>,\n        args: &Bound<'_, PyTuple>,\n        kwargs: Option<&Bound<'_, PyDict>>,\n    ) -> PyResult<()> {\n        // call the super types __init__\n        PySuper::new(&PyDict::type_object(slf.py()), slf)?\n            .call_method(\"__init__\", args.to_owned(), kwargs)?;\n        // Note: if `MyDict` allows further subclassing, and this is called from such a subclass,\n        // then this will not that any overrides into account that such a subclass may have defined.\n        // In such a case it may be preferred to just call `slf.set_item` and let Python figure it out.\n        slf.as_super().set_item(\"my_key\", \"always insert this key\")?;\n        Ok(())\n    }\n}\n\n# #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\n# fn main() {\n#     Python::attach(|py| {\n#         let typeobj = py.get_type::<MyDict>();\n#         let obj = typeobj.call((), None).unwrap().cast_into::<MyDict>().unwrap();\n#         // check __init__ was called\n#         assert_eq!(obj.get_item(\"my_key\").unwrap().extract::<&str>().unwrap(), \"always insert this key\");\n#     });\n# }\n# #[cfg(any(Py_LIMITED_API, GraalPy))]\n# fn main() {}\n```\n\n## Adding the class to a module\n\nThe next step is to create the Python module and add our class to it:\n\n```rust\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# fn main() {}\n# #[pyclass]\n# struct Number(i32);\n#\n#[pymodule]\nmod my_module {\n    #[pymodule_export]\n    use super::Number;\n}\n```\n\n## `Bound<T>` and interior mutability { #bound-and-interior-mutability }\n\nIt is often useful to turn a `#[pyclass]` type `T` into a Python object and access it from Rust code.\nThe [`Py<T>`] and [`Bound<'py, T>`] smart pointers are the ways to represent a Python object in PyO3's API.\nMore detail can be found about them [in the Python objects](./types.md#pyo3s-smart-pointers) section of the guide.\n\nMost Python objects do not offer exclusive (`&mut`) access (see the [section on Python's memory model](./python-from-rust.md#pythons-memory-model)).\nHowever, Rust structs wrapped as Python objects (called `pyclass` types) often *do* need `&mut` access.\nHowever, the Rust borrow checker cannot reason about `&mut` references once an object's ownership has been passed to the Python interpreter.\n\nTo solve this, PyO3 does borrow checking at runtime using a scheme very similar to `std::cell::RefCell<T>`.\nThis is known as [interior mutability](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html).\n\nUsers who are familiar with `RefCell<T>` can use `Py<T>` and `Bound<'py, T>` just like `RefCell<T>`.\n\nFor users who are not very familiar with `RefCell<T>`, here is a reminder of Rust's rules of borrowing:\n\n- At any given time, you can have either (but not both of) one mutable reference or any number of immutable references.\n- References can never outlast the data they refer to.\n\n`Py<T>` and `Bound<'py, T>`, like `RefCell<T>`, ensure these borrowing rules by tracking references at runtime.\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass]\nstruct MyClass {\n    #[pyo3(get)]\n    num: i32,\n}\nPython::attach(|py| {\n    let obj = Bound::new(py, MyClass { num: 3 }).unwrap();\n    {\n        let obj_ref = obj.borrow(); // Get PyRef\n        assert_eq!(obj_ref.num, 3);\n        // You cannot get PyRefMut unless all PyRefs are dropped\n        assert!(obj.try_borrow_mut().is_err());\n    }\n    {\n        let mut obj_mut = obj.borrow_mut(); // Get PyRefMut\n        obj_mut.num = 5;\n        // You cannot get any other refs until the PyRefMut is dropped\n        assert!(obj.try_borrow().is_err());\n        assert!(obj.try_borrow_mut().is_err());\n    }\n\n    // You can convert `Bound` to a Python object\n    pyo3::py_run!(py, obj, \"assert obj.num == 5\");\n});\n```\n\nA `Bound<'py, T>` is restricted to the Python lifetime `'py`.\nTo make the object longer lived (for example, to store it in a struct on the Rust side), use `Py<T>`.\n`Py<T>` needs a `Python<'_>` token to allow access:\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass]\nstruct MyClass {\n    num: i32,\n}\n\nfn return_myclass() -> Py<MyClass> {\n    Python::attach(|py| Py::new(py, MyClass { num: 1 }).unwrap())\n}\n\nlet obj = return_myclass();\n\nPython::attach(move |py| {\n    let bound = obj.bind(py); // Py<MyClass>::bind returns &Bound<'py, MyClass>\n    let obj_ref = bound.borrow(); // Get PyRef<T>\n    assert_eq!(obj_ref.num, 1);\n});\n```\n\n### frozen classes: Opting out of interior mutability\n\nAs detailed above, runtime borrow checking is currently enabled by default.\nBut a class can opt of out it by declaring itself `frozen`.\nIt can still use interior mutability via standard Rust types like `RefCell` or `Mutex`, but it is not bound to the implementation provided by PyO3 and can choose the most appropriate strategy on field-by-field basis.\n\nClasses which are `frozen` and also `Sync`, e.g. they do use `Mutex` but not `RefCell`, can be accessed without needing a `Python` token via the `Bound::get` and `Py::get` methods:\n\n```rust\nuse std::sync::atomic::{AtomicUsize, Ordering};\n# use pyo3::prelude::*;\n\n#[pyclass(frozen)]\nstruct FrozenCounter {\n    value: AtomicUsize,\n}\n\nlet py_counter: Py<FrozenCounter> = Python::attach(|py| {\n    let counter = FrozenCounter {\n        value: AtomicUsize::new(0),\n    };\n\n    Py::new(py, counter).unwrap()\n});\n\npy_counter.get().value.fetch_add(1, Ordering::Relaxed);\n\nPython::attach(move |_py| drop(py_counter));\n```\n\nFrozen classes are likely to become the default thereby guiding the PyO3 ecosystem towards a more deliberate application of interior mutability.\nEventually, this should enable further optimizations of PyO3's internals and avoid downstream code paying the cost of interior mutability when it is not actually required.\n\n## Customizing the class\n\n{{#include ../pyclass-parameters.md}}\n\nThese parameters are covered in various sections of this guide.\n\n### Return type\n\nGenerally, `#[new]` methods have to return `T: Into<PyClassInitializer<Self>>` or `PyResult<T> where T: Into<PyClassInitializer<Self>>`.\n\nFor constructors that may fail, you should wrap the return type in a PyResult as well.\nConsult the table below to determine which type your constructor should return:\n\n|                             | **Cannot fail**           | **May fail**                      |\n|-----------------------------|---------------------------|-----------------------------------|\n|**No inheritance**           | `T`                       | `PyResult<T>`                     |\n|**Inheritance(T Inherits U)**| `(T, U)`                  | `PyResult<(T, U)>`                |\n|**Inheritance(General Case)**| [`PyClassInitializer<T>`] | `PyResult<PyClassInitializer<T>>` |\n\n## Inheritance\n\nBy default, `object`, i.e. `PyAny` is used as the base class.\nTo override this default, use the `extends` parameter for `pyclass` with the full path to the base class.\nCurrently, only classes defined in Rust and builtins provided by PyO3 can be inherited from; inheriting from other classes defined in Python is not yet supported ([#991](https://github.com/PyO3/pyo3/issues/991)).\n\nFor convenience, `(T, U)` implements `Into<PyClassInitializer<T>>` where `U` is the base class of `T`.\nBut for a more deeply nested inheritance, you have to return `PyClassInitializer<T>` explicitly.\n\nTo get a parent class from a child, use [`PyRef`] instead of `&self` for methods, or [`PyRefMut`] instead of `&mut self`.\nThen you can access a parent class by `self_.as_super()` as `&PyRef<Self::BaseClass>`, or by `self_.into_super()` as `PyRef<Self::BaseClass>` (and similar for the `PyRefMut` case).\nFor convenience, `self_.as_ref()` can also be used to get `&Self::BaseClass` directly; however, this approach does not let you access base classes higher in the inheritance hierarchy, for which you would need to chain multiple `as_super` or `into_super` calls.\n\n```rust\n# use pyo3::prelude::*;\n\n#[pyclass(subclass)]\nstruct BaseClass {\n    val1: usize,\n}\n\n#[pymethods]\nimpl BaseClass {\n    #[new]\n    fn new() -> Self {\n        BaseClass { val1: 10 }\n    }\n\n    pub fn method1(&self) -> PyResult<usize> {\n        Ok(self.val1)\n    }\n}\n\n#[pyclass(extends=BaseClass, subclass)]\nstruct SubClass {\n    val2: usize,\n}\n\n#[pymethods]\nimpl SubClass {\n    #[new]\n    fn new() -> (Self, BaseClass) {\n        (SubClass { val2: 15 }, BaseClass::new())\n    }\n\n    fn method2(self_: PyRef<'_, Self>) -> PyResult<usize> {\n        let super_ = self_.as_super(); // Get &PyRef<BaseClass>\n        super_.method1().map(|x| x * self_.val2)\n    }\n}\n\n#[pyclass(extends=SubClass)]\nstruct SubSubClass {\n    val3: usize,\n}\n\n#[pymethods]\nimpl SubSubClass {\n    #[new]\n    fn new() -> PyClassInitializer<Self> {\n        PyClassInitializer::from(SubClass::new()).add_subclass(SubSubClass { val3: 20 })\n    }\n\n    fn method3(self_: PyRef<'_, Self>) -> PyResult<usize> {\n        let base = self_.as_super().as_super(); // Get &PyRef<'_, BaseClass>\n        base.method1().map(|x| x * self_.val3)\n    }\n\n    fn method4(self_: PyRef<'_, Self>) -> PyResult<usize> {\n        let v = self_.val3;\n        let super_ = self_.into_super(); // Get PyRef<'_, SubClass>\n        SubClass::method2(super_).map(|x| x * v)\n    }\n\n      fn get_values(self_: PyRef<'_, Self>) -> (usize, usize, usize) {\n          let val1 = self_.as_super().as_super().val1;\n          let val2 = self_.as_super().val2;\n          (val1, val2, self_.val3)\n      }\n\n    fn double_values(mut self_: PyRefMut<'_, Self>) {\n        self_.as_super().as_super().val1 *= 2;\n        self_.as_super().val2 *= 2;\n        self_.val3 *= 2;\n    }\n\n    #[staticmethod]\n    fn factory_method(py: Python<'_>, val: usize) -> PyResult<Py<PyAny>> {\n        let base = PyClassInitializer::from(BaseClass::new());\n        let sub = base.add_subclass(SubClass { val2: val });\n        if val % 2 == 0 {\n            Ok(Py::new(py, sub)?.into_any())\n        } else {\n            let sub_sub = sub.add_subclass(SubSubClass { val3: val });\n            Ok(Py::new(py, sub_sub)?.into_any())\n        }\n    }\n}\n# Python::attach(|py| {\n#     let subsub = pyo3::Py::new(py, SubSubClass::new()).unwrap();\n#     pyo3::py_run!(py, subsub, \"assert subsub.method1() == 10\");\n#     pyo3::py_run!(py, subsub, \"assert subsub.method2() == 150\");\n#     pyo3::py_run!(py, subsub, \"assert subsub.method3() == 200\");\n#     pyo3::py_run!(py, subsub, \"assert subsub.method4() == 3000\");\n#     pyo3::py_run!(py, subsub, \"assert subsub.get_values() == (10, 15, 20)\");\n#     pyo3::py_run!(py, subsub, \"assert subsub.double_values() == None\");\n#     pyo3::py_run!(py, subsub, \"assert subsub.get_values() == (20, 30, 40)\");\n#     let subsub = SubSubClass::factory_method(py, 2).unwrap();\n#     let subsubsub = SubSubClass::factory_method(py, 3).unwrap();\n#     let cls = py.get_type::<SubSubClass>();\n#     pyo3::py_run!(py, subsub cls, \"assert not isinstance(subsub, cls)\");\n#     pyo3::py_run!(py, subsubsub cls, \"assert isinstance(subsubsub, cls)\");\n# });\n```\n\nYou can inherit native types such as `PyDict`, if they implement [`PySizedLayout`]({{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PySizedLayout.html).\nThis is not supported when building for the Python limited API (aka the `abi3` feature of PyO3).\n\nTo convert between the Rust type and its native base class, you can take `slf` as a Python object.\nTo access the Rust fields use `slf.borrow()` or `slf.borrow_mut()`, and to access the base class use `slf.cast::<BaseClass>()`.\n\n```rust\n# #[cfg(any(not(Py_LIMITED_API), Py_3_12))] {\n# use pyo3::prelude::*;\nuse pyo3::types::PyDict;\nuse std::collections::HashMap;\n\n#[pyclass(extends=PyDict)]\n#[derive(Default)]\nstruct DictWithCounter {\n    counter: HashMap<String, usize>,\n}\n\n#[pymethods]\nimpl DictWithCounter {\n    #[new]\n    fn new() -> Self {\n        Self::default()\n    }\n\n    fn set(slf: &Bound<'_, Self>, key: String, value: Bound<'_, PyAny>) -> PyResult<()> {\n        slf.borrow_mut().counter.entry(key.clone()).or_insert(0);\n        let dict = slf.cast::<PyDict>()?;\n        dict.set_item(key, value)\n    }\n}\n# Python::attach(|py| {\n#     let cnt = pyo3::Py::new(py, DictWithCounter::new()).unwrap();\n#     pyo3::py_run!(py, cnt, \"cnt.set('abc', 10); assert cnt['abc'] == 10\")\n# });\n# }\n```\n\nIf `SubClass` does not provide a base class initialization, the compilation fails.\n\n```rust,compile_fail\n# use pyo3::prelude::*;\n\n#[pyclass]\nstruct BaseClass {\n    val1: usize,\n}\n\n#[pyclass(extends=BaseClass)]\nstruct SubClass {\n    val2: usize,\n}\n\n#[pymethods]\nimpl SubClass {\n    #[new]\n    fn new() -> Self {\n        SubClass { val2: 15 }\n    }\n}\n```\n\nThe `__new__` constructor of a native base class is called implicitly when creating a new instance from Python.\nBe sure to accept arguments in the `#[new]` method that you want the base class to get, even if they are not used in that `fn`:\n\n```rust\n# #[allow(dead_code)]\n# #[cfg(any(not(Py_LIMITED_API), Py_3_12))] {\n# use pyo3::prelude::*;\nuse pyo3::types::PyDict;\n\n#[pyclass(extends=PyDict)]\nstruct MyDict {\n    private: i32,\n}\n\n#[pymethods]\nimpl MyDict {\n    #[new]\n    #[pyo3(signature = (*args, **kwargs))]\n    fn new(args: &Bound<'_, PyAny>, kwargs: Option<&Bound<'_, PyAny>>) -> Self {\n        Self { private: 0 }\n    }\n\n    // some custom methods that use `private` here...\n}\n# Python::attach(|py| {\n#     let cls = py.get_type::<MyDict>();\n#     pyo3::py_run!(py, cls, \"cls(a=1, b=2)\")\n# });\n# }\n```\n\nHere, the `args` and `kwargs` allow creating instances of the subclass passing initial items, such as `MyDict(item_sequence)` or `MyDict(a=1, b=2)`.\n\n## Object properties\n\nPyO3 supports two ways to add properties to your `#[pyclass]`:\n\n- For simple struct fields with no side effects, a `#[pyo3(get, set)]` attribute can be added directly to the field definition in the `#[pyclass]`.\n- For properties which require computation you can define `#[getter]`, `#[setter]` and `#[deleter]` functions in the [`#[pymethods]`](#instance-methods) block.\n\nWe'll cover each of these in the following sections.\n\n### Object properties using `#[pyo3(get, set)]`\n\nFor simple cases where a member variable is just read and written with no side effects, you can declare getters and setters in your `#[pyclass]` field definition using the `pyo3` attribute, like in the example below:\n\n```rust\n# use pyo3::prelude::*;\n# #[allow(dead_code)]\n#[pyclass]\nstruct MyClass {\n    #[pyo3(get, set)]\n    num: i32,\n}\n```\n\nThe above would make the `num` field available for reading and writing as a `self.num` Python property.\nTo expose the property with a different name to the field, specify this alongside the rest of the options, e.g. `#[pyo3(get, set, name = \"custom_name\")]`.\n\nProperties can be readonly or writeonly by using just `#[pyo3(get)]` or `#[pyo3(set)]` respectively.\n\nTo use these annotations, your field type must implement some conversion traits:\n\n- For `get` the field type `T` must implement either `&T: IntoPyObject` or `T: IntoPyObject + Clone`.\n- For `set` the field type must implement `FromPyObject`.\n\nFor example, implementations of those traits are provided for the `Cell` type, if the inner type also implements the trait.\nThis means you can use `#[pyo3(get, set)]` on fields wrapped in a `Cell`.\n\n### Object properties using `#[getter]` and `#[setter]`\n\nFor cases which don't satisfy the `#[pyo3(get, set)]` trait requirements, or need side effects, descriptor methods can be defined in a `#[pymethods]` `impl` block.\n\nThis is done using the `#[getter]` and `#[setter]` attributes, like in the example below:\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass]\nstruct MyClass {\n    num: i32,\n}\n\n#[pymethods]\nimpl MyClass {\n    #[getter]\n    fn num(&self) -> PyResult<i32> {\n        Ok(self.num)\n    }\n\n    #[setter]\n    fn set_num(&mut self, num: i32) {\n        self.num = num;\n    }\n}\n```\n\nThe `#[deleter]` attribute is also available to delete the property.\nThis corresponds to the `del my_object.my_property` python operation.\n\n```rust\n# use pyo3::prelude::*;\n# use pyo3::exceptions::PyAttributeError;\n#[pyclass]\nstruct MyClass {\n    num: Option<i32>,\n}\n\n#[pymethods]\nimpl MyClass {\n    #[getter]\n    fn num(&self) -> PyResult<i32> {\n        self.num.ok_or_else(|| PyAttributeError::new_err(\"num has been deleted\"))\n    }\n\n    #[deleter]\n    fn delete_num(&mut self) {\n        self.num = None;\n    }\n}\n```\n\nA getter, setter or deleters's function name is used as the property name by default.\nThere are several ways how to override the name.\n\nIf a function name starts with `get_`, `set_` or `delete_` for getter, setter or deleter, respectively, the descriptor name becomes the function name with this prefix removed.\nThis is also useful in case of Rust keywords like `type` ([raw identifiers](https://doc.rust-lang.org/edition-guide/rust-2018/module-system/raw-identifiers.html) can be used since Rust 2018).\n\n```rust\n# use pyo3::prelude::*;\n# #[pyclass]\n# struct MyClass {\n#     num: i32,\n# }\n#[pymethods]\nimpl MyClass {\n    #[getter]\n    fn get_num(&self) -> PyResult<i32> {\n        Ok(self.num)\n    }\n\n    #[setter]\n    fn set_num(&mut self, value: i32) -> PyResult<()> {\n        self.num = value;\n        Ok(())\n    }\n}\n```\n\nIn this case, a property `num` is defined and available from Python code as `self.num`.\n\nThe `#[getter]`, `#[setter]` and `#[deleter]` attributes accept one parameter.\nIf this parameter is specified, it is used as the property name, i.e.\n\n```rust\n# use pyo3::prelude::*;\n# #[pyclass]\n# struct MyClass {\n#    num: i32,\n# }\n#[pymethods]\nimpl MyClass {\n    #[getter(number)]\n    fn num(&self) -> PyResult<i32> {\n        Ok(self.num)\n    }\n\n    #[setter(number)]\n    fn set_num(&mut self, value: i32) -> PyResult<()> {\n        self.num = value;\n        Ok(())\n    }\n}\n```\n\nIn this case, the property `number` is defined and available from Python code as `self.number`.\n\n## Instance methods\n\nTo define a Python compatible method, an `impl` block for your struct has to be annotated with the `#[pymethods]` attribute.\nPyO3 generates Python compatible wrappers for all functions in this block with some variations, like descriptors, class method static methods, etc.\n\nSince Rust allows any number of `impl` blocks, you can easily split methods between those accessible to Python (and Rust) and those accessible only to Rust.\nHowever to have multiple `#[pymethods]`-annotated `impl` blocks for the same struct you must enable the [`multiple-pymethods`] feature of PyO3.\n\n```rust\n# use pyo3::prelude::*;\n# #[pyclass]\n# struct MyClass {\n#     num: i32,\n# }\n#[pymethods]\nimpl MyClass {\n    fn method1(&self) -> PyResult<i32> {\n        Ok(10)\n    }\n\n    fn set_method(&mut self, value: i32) -> PyResult<()> {\n        self.num = value;\n        Ok(())\n    }\n}\n```\n\nBoth `&self` and `&mut self` can be used, due to the use of [runtime borrow checking](#bound-and-interior-mutability).\n\nThe return type must be `PyResult<T>` or `T` for some `T` that implements `IntoPyObject`; the latter is allowed if the method cannot raise Python exceptions.\n\nA `Python` parameter can be specified as part of method signature, in this case the `py` argument gets injected by the method wrapper, e.g.\n\n```rust\n# use pyo3::prelude::*;\n# #[pyclass]\n# struct MyClass {\n# #[allow(dead_code)]\n#     num: i32,\n# }\n#[pymethods]\nimpl MyClass {\n    fn method2(&self, py: Python<'_>) -> PyResult<i32> {\n        Ok(10)\n    }\n}\n```\n\nFrom the Python perspective, the `method2` in this example does not accept any arguments.\n\n## Class methods\n\nTo create a class method for a custom class, the method needs to be annotated with the `#[classmethod]` attribute.\nThis is the equivalent of the Python decorator `@classmethod`.\n\n```rust\n# use pyo3::prelude::*;\n# use pyo3::types::PyType;\n# #[pyclass]\n# struct MyClass {\n#     #[allow(dead_code)]\n#     num: i32,\n# }\n#[pymethods]\nimpl MyClass {\n    #[classmethod]\n    fn cls_method(cls: &Bound<'_, PyType>) -> PyResult<i32> {\n        Ok(10)\n    }\n}\n```\n\nDeclares a class method callable from Python.\n\n- The first parameter is the type object of the class on which the method is called.\n  This may be the type object of a derived class.\n- The first parameter implicitly has type `&Bound<'_, PyType>`.\n- For details on `parameter-list`, see the documentation of `Method arguments` section.\n- The return type must be `PyResult<T>` or `T` for some `T` that implements `IntoPyObject`.\n\n### Constructors which accept a class argument\n\nTo create a constructor which takes a positional class argument, you can combine the `#[classmethod]` and `#[new]` modifiers:\n\n```rust\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use pyo3::types::PyType;\n# #[pyclass]\n# struct BaseClass(Py<PyAny>);\n#\n#[pymethods]\nimpl BaseClass {\n    #[new]\n    #[classmethod]\n    fn py_new(cls: &Bound<'_, PyType>) -> PyResult<Self> {\n        // Get an abstract attribute (presumably) declared on a subclass of this class.\n        let subclass_attr: Bound<'_, PyAny> = cls.getattr(\"a_class_attr\")?;\n        Ok(Self(subclass_attr.unbind()))\n    }\n}\n```\n\n## Static methods\n\nTo create a static method for a custom class, the method needs to be annotated with the `#[staticmethod]` attribute.\nThe return type must be `T` or `PyResult<T>` for some `T` that implements `IntoPyObject`.\n\n```rust\n# use pyo3::prelude::*;\n# #[pyclass]\n# struct MyClass {\n#     #[allow(dead_code)]\n#     num: i32,\n# }\n#[pymethods]\nimpl MyClass {\n    #[staticmethod]\n    fn static_method(param1: i32, param2: &str) -> PyResult<i32> {\n        Ok(10)\n    }\n}\n```\n\n## Class attributes\n\nTo create a class attribute (also called [class variable][classattr]), a method without any arguments can be annotated with the `#[classattr]` attribute.\n\n```rust,no_run\n# use pyo3::prelude::*;\n# #[pyclass]\n# struct MyClass {}\n#[pymethods]\nimpl MyClass {\n    #[classattr]\n    fn my_attribute() -> String {\n        \"hello\".to_string()\n    }\n}\n\nPython::attach(|py| {\n    let my_class = py.get_type::<MyClass>();\n    pyo3::py_run!(py, my_class, \"assert my_class.my_attribute == 'hello'\")\n});\n```\n\n> [!NOTE]\n> If the method has a `Result` return type and returns an `Err`, PyO3 will panic during\nclass creation.\n\n> [!NOTE]\n> `#[classattr]` does not work with [`#[pyo3(warn(...))]`](./function.md#warn) attribute.\n\nIf the class attribute is defined with `const` code only, one can also annotate associated constants:\n\n```rust,no_run\n# use pyo3::prelude::*;\n# #[pyclass]\n# struct MyClass {}\n#[pymethods]\nimpl MyClass {\n    #[classattr]\n    const MY_CONST_ATTRIBUTE: &'static str = \"foobar\";\n}\n```\n\n## Classes as function arguments\n\nClass objects can be used as arguments to `#[pyfunction]`s and `#[pymethods]` in the same way as the self parameters of instance methods, i.e. they can be passed as:\n\n- `Py<T>` or `Bound<'py, T>` smart pointers to the class Python object,\n- `&T` or `&mut T` references to the Rust data contained in the Python object, or\n- `PyRef<T>` and `PyRefMut<T>` reference wrappers.\n\nExamples of each of these below:\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n#[pyclass]\nstruct MyClass {\n    my_field: i32,\n}\n\n// Take a reference to Rust data when the Python object is irrelevant.\n#[pyfunction]\nfn increment_field(my_class: &mut MyClass) {\n    my_class.my_field += 1;\n}\n\n// Take a reference wrapper when borrowing should be automatic,\n// but access to the Python object is still needed\n#[pyfunction]\nfn print_field_and_return_me(my_class: PyRef<'_, MyClass>) -> PyRef<'_, MyClass> {\n    println!(\"{}\", my_class.my_field);\n    my_class\n}\n\n// Take (a reference to) a Python object smart pointer when borrowing needs to be managed manually.\n#[pyfunction]\nfn increment_then_print_field(my_class: &Bound<'_, MyClass>) {\n    my_class.borrow_mut().my_field += 1;\n\n    println!(\"{}\", my_class.borrow().my_field);\n}\n\n// When the Python object smart pointer needs to be stored elsewhere prefer `Py<T>` over `Bound<'py, T>`\n// to avoid the lifetime restrictions.\n#[pyfunction]\nfn print_is_none(my_class: Py<MyClass>, py: Python<'_>) {\n    println!(\"{}\", my_class.is_none(py));\n}\n```\n\nClasses can also be passed by value if they can be cloned, i.e. they automatically implement `FromPyObject` if they implement `Clone`, e.g. via `#[derive(Clone)]`:\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n#[pyclass(from_py_object)]\n#[derive(Clone)]\nstruct MyClass {\n    my_field: Box<i32>,\n}\n\n#[pyfunction]\nfn disassemble_clone(my_class: MyClass) {\n    let MyClass { mut my_field } = my_class;\n    *my_field += 1;\n}\n```\n\nNote that `#[derive(FromPyObject)]` on a class is usually not useful as it tries to construct a new Rust value by filling in the fields by looking up attributes of any given Python value.\n\n## Method arguments\n\nSimilar to `#[pyfunction]`, the `#[pyo3(signature = (...))]` attribute can be used to specify the way that `#[pymethods]` accept arguments.\nConsult the documentation for [`function signatures`](./function/signature.md) to see the parameters this attribute accepts.\n\nThe following example defines a class `MyClass` with a method `method`.\nThis method has a signature that sets default values for `num` and `name`, and indicates that `py_args` should collect all extra positional arguments and `py_kwargs` all extra keyword arguments:\n\n```rust,no_run\n# use pyo3::prelude::*;\nuse pyo3::types::{PyDict, PyTuple};\n#\n# #[pyclass]\n# struct MyClass {\n#     num: i32,\n# }\n#[pymethods]\nimpl MyClass {\n    #[new]\n    #[pyo3(signature = (num=-1))]\n    fn new(num: i32) -> Self {\n        MyClass { num }\n    }\n\n    #[pyo3(signature = (num=10, *py_args, name=\"Hello\", **py_kwargs))]\n    fn method(\n        &mut self,\n        num: i32,\n        py_args: &Bound<'_, PyTuple>,\n        name: &str,\n        py_kwargs: Option<&Bound<'_, PyDict>>,\n    ) -> String {\n        let num_before = self.num;\n        self.num = num;\n        format!(\n            \"num={} (was previously={}), py_args={:?}, name={}, py_kwargs={:?} \",\n            num, num_before, py_args, name, py_kwargs,\n        )\n    }\n}\n```\n\nIn Python, this might be used like:\n\n```python\n>>> import mymodule\n>>> mc = mymodule.MyClass()\n>>> print(mc.method(44, False, \"World\", 666, x=44, y=55))\npy_args=('World', 666), py_kwargs=Some({'x': 44, 'y': 55}), name=Hello, num=44, num_before=-1\n>>> print(mc.method(num=-1, name=\"World\"))\npy_args=(), py_kwargs=None, name=World, num=-1, num_before=44\n```\n\nThe [`#[pyo3(text_signature = \"...\")`](./function/signature.md#overriding-the-generated-signature) option for `#[pyfunction]` also works for `#[pymethods]`.\n\n```rust\n# #![allow(dead_code)]\nuse pyo3::prelude::*;\nuse pyo3::types::PyType;\n\n#[pyclass]\nstruct MyClass {}\n\n#[pymethods]\nimpl MyClass {\n    #[new]\n    #[pyo3(text_signature = \"(c, d)\")]\n    fn new(c: i32, d: &str) -> Self {\n        Self {}\n    }\n    // the self argument should be written $self\n    #[pyo3(text_signature = \"($self, e, f)\")]\n    fn my_method(&self, e: i32, f: i32) -> i32 {\n        e + f\n    }\n    // similarly for classmethod arguments, use $cls\n    #[classmethod]\n    #[pyo3(text_signature = \"($cls, e, f)\")]\n    fn my_class_method(cls: &Bound<'_, PyType>, e: i32, f: i32) -> i32 {\n        e + f\n    }\n    #[staticmethod]\n    #[pyo3(text_signature = \"(e, f)\")]\n    fn my_static_method(e: i32, f: i32) -> i32 {\n        e + f\n    }\n}\n#\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| {\n#         let inspect = PyModule::import(py, \"inspect\")?.getattr(\"signature\")?;\n#         let module = PyModule::new(py, \"my_module\")?;\n#         module.add_class::<MyClass>()?;\n#         let class = module.getattr(\"MyClass\")?;\n#\n#         if cfg!(not(Py_LIMITED_API)) || py.version_info() >= (3, 10)  {\n#             let doc: String = class.getattr(\"__doc__\")?.extract()?;\n#             assert_eq!(doc, \"\");\n#\n#             let sig: String = inspect\n#                 .call1((&class,))?\n#                 .call_method0(\"__str__\")?\n#                 .extract()?;\n#             assert_eq!(sig, \"(c, d)\");\n#         } else {\n#             let doc: String = class.getattr(\"__doc__\")?.extract()?;\n#             assert_eq!(doc, \"\");\n#\n#             inspect.call1((&class,)).expect_err(\"`text_signature` on classes is not compatible with compilation in `abi3` mode until Python 3.10 or greater\");\n#          }\n#\n#         {\n#             let method = class.getattr(\"my_method\")?;\n#\n#             assert!(method.getattr(\"__doc__\")?.is_none());\n#\n#             let sig: String = inspect\n#                 .call1((method,))?\n#                 .call_method0(\"__str__\")?\n#                 .extract()?;\n#             assert_eq!(sig, \"(self, /, e, f)\");\n#         }\n#\n#         {\n#             let method = class.getattr(\"my_class_method\")?;\n#\n#             assert!(method.getattr(\"__doc__\")?.is_none());\n#\n#             let sig: String = inspect\n#                 .call1((method,))?\n#                 .call_method0(\"__str__\")?\n#                 .extract()?;\n#             assert_eq!(sig, \"(e, f)\");  // inspect.signature skips the $cls arg\n#         }\n#\n#         {\n#             let method = class.getattr(\"my_static_method\")?;\n#\n#             assert!(method.getattr(\"__doc__\")?.is_none());\n#\n#             let sig: String = inspect\n#                 .call1((method,))?\n#                 .call_method0(\"__str__\")?\n#                 .extract()?;\n#             assert_eq!(sig, \"(e, f)\");\n#         }\n#\n#         Ok(())\n#     })\n# }\n```\n\nNote that `text_signature` on `#[new]` is not compatible with compilation in `abi3` mode until Python 3.10 or greater.\n\n### Method receivers and lifetime elision\n\nPyO3 supports writing instance methods using the normal method receivers for shared `&self` and unique `&mut self` references.\nThis interacts with [lifetime elision][lifetime-elision] insofar as the lifetime of a such a receiver is assigned to all elided output lifetime parameters.\n\nThis is a good default for general Rust code where return values are more likely to borrow from the receiver than from the other arguments, if they contain any lifetimes at all.\nHowever, when returning bound references `Bound<'py, T>` in PyO3-based code, the Python lifetime `'py` should usually be derived from a `py: Python<'py>` token passed as an argument instead of the receiver.\n\nSpecifically, signatures like\n\n```rust,ignore\nfn frobnicate(&self, py: Python) -> Bound<Foo>;\n```\n\nwill not work as they are inferred as\n\n```rust,ignore\nfn frobnicate<'a, 'py>(&'a self, py: Python<'py>) -> Bound<'a, Foo>;\n```\n\ninstead of the intended\n\n```rust,ignore\nfn frobnicate<'a, 'py>(&'a self, py: Python<'py>) -> Bound<'py, Foo>;\n```\n\nand should usually be written as\n\n```rust,ignore\nfn frobnicate<'py>(&self, py: Python<'py>) -> Bound<'py, Foo>;\n```\n\nThe same problem does not exist for `#[pyfunction]`s as the special case for receiver lifetimes does not apply and indeed a signature like\n\n```rust,ignore\nfn frobnicate(bar: &Bar, py: Python) -> Bound<Foo>;\n```\n\nwill yield compiler error [E0106 \"missing lifetime specifier\"][compiler-error-e0106].\n\n## `#[pyclass]` enums\n\nEnum support in PyO3 comes in two flavors, depending on what kind of variants the enum has: simple and complex.\n\n### Simple enums\n\nA simple enum (a.k.a.\nC-like enum) has only unit variants.\n\nPyO3 adds a class attribute for each variant, so you can access them in Python without defining `#[new]`.\nPyO3 also provides default implementations of `__richcmp__` and `__int__`, so they can be compared using `==`:\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass(eq, eq_int)]\n#[derive(PartialEq)]\nenum MyEnum {\n    Variant,\n    OtherVariant,\n}\n\nPython::attach(|py| {\n    let x = Py::new(py, MyEnum::Variant).unwrap();\n    let y = Py::new(py, MyEnum::OtherVariant).unwrap();\n    let cls = py.get_type::<MyEnum>();\n    pyo3::py_run!(py, x y cls, r#\"\n        assert x == cls.Variant\n        assert y == cls.OtherVariant\n        assert x != y\n    \"#)\n})\n```\n\nYou can also convert your simple enums into `int`:\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass(eq, eq_int)]\n#[derive(PartialEq)]\nenum MyEnum {\n    Variant,\n    OtherVariant = 10,\n}\n\nPython::attach(|py| {\n    let cls = py.get_type::<MyEnum>();\n    let x = MyEnum::Variant as i32; // The exact value is assigned by the compiler.\n    pyo3::py_run!(py, cls x, r#\"\n        assert int(cls.Variant) == x\n        assert int(cls.OtherVariant) == 10\n    \"#)\n})\n```\n\nPyO3 also provides `__repr__` for enums:\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass(eq, eq_int)]\n#[derive(PartialEq)]\nenum MyEnum{\n    Variant,\n    OtherVariant,\n}\n\nPython::attach(|py| {\n    let cls = py.get_type::<MyEnum>();\n    let x = Py::new(py, MyEnum::Variant).unwrap();\n    pyo3::py_run!(py, cls x, r#\"\n        assert repr(x) == 'MyEnum.Variant'\n        assert repr(cls.OtherVariant) == 'MyEnum.OtherVariant'\n    \"#)\n})\n```\n\nAll methods defined by PyO3 can be overridden.\nFor example here's how you override `__repr__`:\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass(eq, eq_int)]\n#[derive(PartialEq)]\nenum MyEnum {\n    Answer = 42,\n}\n\n#[pymethods]\nimpl MyEnum {\n    fn __repr__(&self) -> &'static str {\n        \"42\"\n    }\n}\n\nPython::attach(|py| {\n    let cls = py.get_type::<MyEnum>();\n    pyo3::py_run!(py, cls, \"assert repr(cls.Answer) == '42'\")\n})\n```\n\nEnums and their variants can also be renamed using `#[pyo3(name)]`.\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass(eq, eq_int, name = \"RenamedEnum\")]\n#[derive(PartialEq)]\nenum MyEnum {\n    #[pyo3(name = \"UPPERCASE\")]\n    Variant,\n}\n\nPython::attach(|py| {\n    let x = Py::new(py, MyEnum::Variant).unwrap();\n    let cls = py.get_type::<MyEnum>();\n    pyo3::py_run!(py, x cls, r#\"\n        assert repr(x) == 'RenamedEnum.UPPERCASE'\n        assert x == cls.UPPERCASE\n    \"#)\n})\n```\n\nOrdering of enum variants is optionally added using `#[pyo3(ord)]`.\n*Note: Implementation of the `PartialOrd` trait is required when passing the `ord` argument.*\n*If not implemented, a compile time error is raised.*\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass(eq, ord)]\n#[derive(PartialEq, PartialOrd)]\nenum MyEnum{\n    A,\n    B,\n    C,\n}\n\nPython::attach(|py| {\n    let cls = py.get_type::<MyEnum>();\n    let a = Py::new(py, MyEnum::A).unwrap();\n    let b = Py::new(py, MyEnum::B).unwrap();\n    let c = Py::new(py, MyEnum::C).unwrap();\n    pyo3::py_run!(py, cls a b c, r#\"\n        assert (a < b) == True\n        assert (c <= b) == False\n        assert (c > a) == True\n    \"#)\n})\n```\n\nYou may not use enums as a base class or let enums inherit from other classes.\n\n```rust,compile_fail\n# use pyo3::prelude::*;\n#[pyclass(subclass)]\nenum BadBase {\n    Var1,\n}\n```\n\n```rust,compile_fail\n# use pyo3::prelude::*;\n\n#[pyclass(subclass)]\nstruct Base;\n\n#[pyclass(extends=Base)]\nenum BadSubclass {\n    Var1,\n}\n```\n\n`#[pyclass]` enums are currently not interoperable with `IntEnum` in Python.\n\n### Complex enums\n\nAn enum is complex if it has any non-unit (struct or tuple) variants.\n\nPyO3 supports only struct and tuple variants in a complex enum.\nUnit variants aren't supported at present (the recommendation is to use an empty tuple enum instead).\n\nPyO3 adds a class attribute for each variant, which may be used to construct values and in match patterns.\nPyO3 also provides getter methods for all fields of each variant.\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass]\nenum Shape {\n    Circle { radius: f64 },\n    Rectangle { width: f64, height: f64 },\n    RegularPolygon(u32, f64),\n    Nothing { },\n}\n\n# #[cfg(Py_3_10)]\nPython::attach(|py| {\n    let circle = Shape::Circle { radius: 10.0 }.into_pyobject(py)?;\n    let square = Shape::RegularPolygon(4, 10.0).into_pyobject(py)?;\n    let cls = py.get_type::<Shape>();\n    pyo3::py_run!(py, circle square cls, r#\"\n        assert isinstance(circle, cls)\n        assert isinstance(circle, cls.Circle)\n        assert circle.radius == 10.0\n\n        assert isinstance(square, cls)\n        assert isinstance(square, cls.RegularPolygon)\n        assert square[0] == 4 # Gets _0 field\n        assert square[1] == 10.0 # Gets _1 field\n\n        def count_vertices(cls, shape):\n            match shape:\n                case cls.Circle():\n                    return 0\n                case cls.Rectangle():\n                    return 4\n                case cls.RegularPolygon(n):\n                    return n\n                case cls.Nothing():\n                    return 0\n\n        assert count_vertices(cls, circle) == 0\n        assert count_vertices(cls, square) == 4\n    \"#);\n#   Ok::<_, PyErr>(())\n})\n# .unwrap();\n```\n\nWARNING: `Py::new` and `.into_pyobject` are currently inconsistent.\nNote how the constructed value is *not* an instance of the specific variant.\nFor this reason, constructing values is only recommended using `.into_pyobject`.\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass]\nenum MyEnum {\n    Variant { i: i32 },\n}\n\nPython::attach(|py| {\n    let x = Py::new(py, MyEnum::Variant { i: 42 }).unwrap();\n    let cls = py.get_type::<MyEnum>();\n    pyo3::py_run!(py, x cls, r#\"\n        assert isinstance(x, cls)\n        assert not isinstance(x, cls.Variant)\n    \"#)\n})\n```\n\nThe constructor of each generated class can be customized using the `#[pyo3(constructor = (...))]` attribute.\nThis uses the same syntax as the [`#[pyo3(signature = (...))]`](function/signature.md) attribute on function and methods and supports the same options.\nTo apply this attribute simply place it on top of a variant in a `#[pyclass]` complex enum as shown below:\n\n```rust\n# use pyo3::prelude::*;\n#[pyclass]\nenum Shape {\n    #[pyo3(constructor = (radius=1.0))]\n    Circle { radius: f64 },\n    #[pyo3(constructor = (*, width, height))]\n    Rectangle { width: f64, height: f64 },\n    #[pyo3(constructor = (side_count, radius=1.0))]\n    RegularPolygon { side_count: u32, radius: f64 },\n    Nothing { },\n}\n\n# #[cfg(Py_3_10)]\nPython::attach(|py| {\n    let cls = py.get_type::<Shape>();\n    pyo3::py_run!(py, cls, r#\"\n        circle = cls.Circle()\n        assert isinstance(circle, cls)\n        assert isinstance(circle, cls.Circle)\n        assert circle.radius == 1.0\n\n        square = cls.Rectangle(width = 1, height = 1)\n        assert isinstance(square, cls)\n        assert isinstance(square, cls.Rectangle)\n        assert square.width == 1\n        assert square.height == 1\n\n        hexagon = cls.RegularPolygon(6)\n        assert isinstance(hexagon, cls)\n        assert isinstance(hexagon, cls.RegularPolygon)\n        assert hexagon.side_count == 6\n        assert hexagon.radius == 1\n    \"#)\n})\n```\n\n## Implementation details\n\nThe `#[pyclass]` macros rely on a lot of conditional code generation: each `#[pyclass]` can optionally have a `#[pymethods]` block.\n\nTo support this flexibility the `#[pyclass]` macro expands to a blob of boilerplate code which sets up the structure for [\"dtolnay specialization\"](https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md).\nThis implementation pattern enables the Rust compiler to use `#[pymethods]` implementations when they are present, and fall back to default (empty) definitions when they are not.\n\nThis simple technique works for the case when there is zero or one implementations.\nTo support multiple `#[pymethods]` for a `#[pyclass]` (in the [`multiple-pymethods`] feature), a registry mechanism provided by the [`inventory`](https://github.com/dtolnay/inventory) crate is used instead.\nThis collects `impl`s at library load time, but isn't supported on all platforms.\nSee [inventory: how it works](https://github.com/dtolnay/inventory#how-it-works) for more details.\n\nThe `#[pyclass]` macro expands to roughly the code seen below.\nThe `PyClassImplCollector` is the type used internally by PyO3 for dtolnay specialization:\n\n```rust\n# #[cfg(not(feature = \"multiple-pymethods\"))] {\n# use pyo3::prelude::*;\n// Note: the implementation differs slightly with the `multiple-pymethods` feature enabled.\n# #[allow(dead_code)]\nstruct MyClass {\n    # #[allow(dead_code)]\n    num: i32,\n}\n\nimpl pyo3::types::DerefToPyAny for MyClass {}\n\nunsafe impl pyo3::type_object::PyTypeInfo for MyClass {\n    const NAME: &'static str = \"MyClass\";\n    const MODULE: ::std::option::Option<&'static str> = ::std::option::Option::None;\n\n    #[inline]\n    fn type_object_raw(py: pyo3::Python<'_>) -> *mut pyo3::ffi::PyTypeObject {\n        <Self as pyo3::impl_::pyclass::PyClassImpl>::lazy_type_object()\n            .get_or_try_init(py)\n            .unwrap_or_else(|e| pyo3::impl_::pyclass::type_object_init_failed(\n                py,\n                e,\n                <Self as pyo3::PyClass>::NAME\n            ))\n            .as_type_ptr()\n    }\n}\n\nimpl pyo3::PyClass for MyClass {\n    const NAME: &str = \"MyClass\";\n    type Frozen = pyo3::pyclass::boolean_struct::False;\n}\n\nimpl pyo3::impl_::pyclass::PyClassImpl for MyClass {\n    const MODULE: Option<&str> = None;\n    const IS_BASETYPE: bool = false;\n    const IS_SUBCLASS: bool = false;\n    const IS_MAPPING: bool = false;\n    const IS_SEQUENCE: bool = false;\n    type Layout = <Self::BaseNativeType as pyo3::impl_::pyclass::PyClassBaseType>::Layout<Self>;\n    type BaseType = PyAny;\n    type ThreadChecker = pyo3::impl_::pyclass::NoopThreadChecker;\n    type PyClassMutability = <<pyo3::PyAny as pyo3::impl_::pyclass::PyClassBaseType>::PyClassMutability as pyo3::impl_::pycell::PyClassMutability>::MutableChild;\n    type Dict = pyo3::impl_::pyclass::PyClassDummySlot;\n    type WeakRef = pyo3::impl_::pyclass::PyClassDummySlot;\n    type BaseNativeType = pyo3::PyAny;\n\n    const RAW_DOC: &'static std::ffi::CStr = c\"...\";\n    const DOC: &'static std::ffi::CStr = c\"...\";\n\n    fn items_iter() -> pyo3::impl_::pyclass::PyClassItemsIter {\n        use pyo3::impl_::pyclass::*;\n        let collector = PyClassImplCollector::<MyClass>::new();\n        static INTRINSIC_ITEMS: PyClassItems = PyClassItems { slots: &[], methods: &[] };\n        PyClassItemsIter::new(&INTRINSIC_ITEMS, collector.py_methods())\n    }\n\n    fn lazy_type_object() -> &'static pyo3::impl_::pyclass::LazyTypeObject<MyClass> {\n        use pyo3::impl_::pyclass::LazyTypeObject;\n        static TYPE_OBJECT: LazyTypeObject<MyClass> = LazyTypeObject::new();\n        &TYPE_OBJECT\n    }\n}\n\n# Python::attach(|py| {\n#     let cls = py.get_type::<MyClass>();\n#     pyo3::py_run!(py, cls, \"assert cls.__name__ == 'MyClass'\")\n# });\n# }\n```\n\n[`PyTypeInfo`]: {{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PyTypeInfo.html\n\n[`Py<T>`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html\n[`Bound<'py, T>`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html\n[`PyClass`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass/trait.PyClass.html\n[`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html\n[`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRefMut.html\n[`PyClassInitializer<T>`]: {{#PYO3_DOCS_URL}}/pyo3/pyclass_init/struct.PyClassInitializer.html\n\n[`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html\n\n[classattr]: https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables\n\n[`multiple-pymethods`]: features.md#multiple-pymethods\n\n[lifetime-elision]: https://doc.rust-lang.org/reference/lifetime-elision.html\n[compiler-error-e0106]: https://doc.rust-lang.org/error_codes/E0106.html\n"
  },
  {
    "path": "guide/src/contributing.md",
    "content": "{{#include ../../Contributing.md}}\n"
  },
  {
    "path": "guide/src/conversions/tables.md",
    "content": "# Mapping of Rust types to Python types\n\nWhen writing functions callable from Python (such as a `#[pyfunction]` or in a `#[pymethods]` block), the trait `FromPyObject` is required for function arguments, and `IntoPyObject` is required for function return values.\n\nConsult the tables in the following section to find the Rust types provided by PyO3 which implement these traits.\n\n## Argument Types\n\nWhen accepting a function argument, it is possible to either use Rust library types or PyO3's Python-native types. (See the next section for discussion on when to use each.)\n\nThe table below contains the Python type and the corresponding function argument types that will accept them:\n\n| Python        | Rust                            | Rust (Python-native) |\n| ------------- |:-------------------------------:|:--------------------:|\n| `object`      | -                               | `PyAny`             |\n| `str`         | `String`, `Cow<str>`, `&str`, `char`, `OsString`, `PathBuf`, `Path` | `PyString` |\n| `bytes`       | `Vec<u8>`, `&[u8]`, `Cow<[u8]>` | `PyBytes`           |\n| `bool`        | `bool`                          | `PyBool`            |\n| `int`         | `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize`, `num_bigint::BigInt`[^1], `num_bigint::BigUint`[^1] | `PyInt` |\n| `float`       | `f32`, `f64`, `ordered_float::NotNan`[^2], `ordered_float::OrderedFloat`[^2]                    | `PyFloat`           |\n| `complex`     | `num_complex::Complex`[^3]      | `PyComplex`         |\n| `fractions.Fraction`| `num_rational::Ratio`[^4] | -         |\n| `list[T]`     | `Vec<T>`                        | `PyList`            |\n| `dict[K, V]`  | `HashMap<K, V>`, `BTreeMap<K, V>`, `hashbrown::HashMap<K, V>`[^5], `indexmap::IndexMap<K, V>`[^6] | `PyDict` |\n| `tuple[T, U]` | `(T, U)`, `Vec<T>`              | `PyTuple`           |\n| `set[T]`      | `HashSet<T>`, `BTreeSet<T>`, `hashbrown::HashSet<T>`[^5] | `PySet` |\n| `frozenset[T]` | `HashSet<T>`, `BTreeSet<T>`, `hashbrown::HashSet<T>`[^5] | `PyFrozenSet` |\n| `bytearray`   | `Vec<u8>`, `Cow<[u8]>`          | `PyByteArray`       |\n| `slice`       | -                               | `PySlice`           |\n| `type`        | -                               | `PyType`            |\n| `module`      | -                               | `PyModule`          |\n| `collections.abc.Buffer` | -                    | `PyBuffer<T>`        |\n| `datetime.datetime` | `SystemTime`, `chrono::DateTime<Tz>`[^7], `chrono::NaiveDateTime`[^7] | `PyDateTime`        |\n| `datetime.date` | `chrono::NaiveDate`[^7]       | `PyDate`            |\n| `datetime.time` | `chrono::NaiveTime`[^7]       | `PyTime`            |\n| `datetime.tzinfo` | `chrono::FixedOffset`[^7], `chrono::Utc`[^7], `chrono_tz::TimeZone`[^8] | `PyTzInfo`          |\n| `datetime.timedelta` | `Duration`, `chrono::Duration`[^7] | `PyDelta`           |\n| `decimal.Decimal` | `rust_decimal::Decimal`[^9] | -                    |\n| `decimal.Decimal` | `bigdecimal::BigDecimal`[^10] | -                   |\n| `ipaddress.IPv4Address` | `std::net::IpAddr`, `std::net::Ipv4Addr` | - |\n| `ipaddress.IPv6Address` | `std::net::IpAddr`, `std::net::Ipv6Addr` | - |\n| `os.PathLike` | `PathBuf`, `Path`              | `PyString` |\n| `pathlib.Path` | `PathBuf`, `Path`              | `PyString` |\n| `typing.Optional[T]` | `Option<T>`              | -                    |\n| `typing.Sequence[T]` | `Vec<T>`                 | `PySequence`        |\n| `typing.Mapping[K, V]` | `HashMap<K, V>`, `BTreeMap<K, V>`, `hashbrown::HashMap<K, V>`[^5], `indexmap::IndexMap<K, V>`[^6] | `&PyMapping` |\n| `typing.Iterator[Any]` | -                      | `PyIterator`        |\n| `typing.Union[...]` | See [`#[derive(FromPyObject)]`](traits.md#deriving-frompyobject-for-enums) | - |\n\nIt is also worth remembering the following special types:\n\n| What             | Description                           |\n| ---------------- | ------------------------------------- |\n| `Python<'py>`    | A token used to prove attachment to the Python interpreter. |\n| `Bound<'py, T>`  | A Python object with a lifetime which binds it to the attachment to the Python interpreter. This provides access to most of PyO3's APIs. |\n| `Py<T>`          | A Python object not connected to any lifetime of attachment to the Python interpreter. This can be sent to other threads. |\n| `PyRef<T>`       | A `#[pyclass]` borrowed immutably.    |\n| `PyRefMut<T>`    | A `#[pyclass]` borrowed mutably.      |\n\nFor more detail on accepting `#[pyclass]` values as function arguments, see [the section of this guide on Python Classes](../class.md).\n\n### Using Rust library types vs Python-native types\n\nUsing Rust library types as function arguments will incur a conversion cost compared to using the Python-native types.\nUsing the Python-native types is almost zero-cost (they just require a type check similar to the Python builtin function `isinstance()`).\n\nHowever, once that conversion cost has been paid, the Rust standard library types offer a number of benefits:\n\n- You can write functionality in native-speed Rust code (free of Python's runtime costs).\n- You get better interoperability with the rest of the Rust ecosystem.\n- You can use `Python::detach` to detach from the interpreter and let other Python threads make progress while your Rust code is executing.\n- You also benefit from stricter type checking.\n  For example you can specify `Vec<i32>`, which will only accept a Python `list` containing integers.\n  The Python-native equivalent, `&PyList`, would accept a Python `list` containing Python objects of any type.\n\nFor most PyO3 usage the conversion cost is worth paying to get these benefits.\nAs always, if you're not sure it's worth it in your case, benchmark it!\n\n## Returning Rust values to Python\n\nWhen returning values from functions callable from Python, [PyO3's smart pointers](../types.md#pyo3s-smart-pointers) (`Py<T>`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`) can be used with zero cost.\n\nBecause `Bound<'py, T>` and `Borrowed<'a, 'py, T>` have lifetime parameters, the Rust compiler may ask for lifetime annotations to be added to your function.\nSee the [section of the guide dedicated to this](../types.md#function-argument-lifetimes).\n\nIf your function is fallible, it should return `PyResult<T>` or `Result<T, E>` where `E` implements `From<E> for PyErr`.\nThis will raise a `Python` exception if the `Err` variant is returned.\n\nFinally, the following Rust types are also able to convert to Python as return values:\n\n| Rust type     | Resulting Python Type           |\n| ------------- |:-------------------------------:|\n| `String`      | `str`                           |\n| `&str`        | `str`                           |\n| `bool`        | `bool`                          |\n| Any integer type (`i32`, `u32`, `usize`, etc) | `int` |\n| `f32`, `f64`  | `float`                         |\n| `Option<T>`   | `Optional[T]`                   |\n| `(T, U)`      | `Tuple[T, U]`                   |\n| `Vec<T>`      | `List[T]`                       |\n| `Cow<[u8]>`   | `bytes`                         |\n| `HashMap<K, V>` | `Dict[K, V]`                  |\n| `BTreeMap<K, V>` | `Dict[K, V]`                 |\n| `HashSet<T>`  | `Set[T]`                        |\n| `BTreeSet<T>` | `Set[T]`                        |\n| `Py<T>` | `T`                                   |\n| `Bound<T>` | `T`                                |\n| `PyRef<T: PyClass>` | `T`                       |\n| `PyRefMut<T: PyClass>` | `T`                    |\n\n[^1]: Requires the `num-bigint` optional feature.\n\n[^2]: Requires the `ordered-float` optional feature.\n\n[^3]: Requires the `num-complex` optional feature.\n\n[^4]: Requires the `num-rational` optional feature.\n\n[^5]: Requires the `hashbrown` optional feature.\n\n[^6]: Requires the `indexmap` optional feature.\n\n[^7]: Requires the `chrono` (and maybe `chrono-local`) optional feature(s).\n\n[^8]: Requires the `chrono-tz` optional feature.\n\n[^9]: Requires the `rust_decimal` optional feature.\n\n[^10]: Requires the `bigdecimal` optional feature.\n"
  },
  {
    "path": "guide/src/conversions/traits.md",
    "content": "# Conversion traits\n\nPyO3 provides some handy traits to convert between Python types and Rust types.\n\n## `.extract()` and the `FromPyObject` trait\n\nThe easiest way to convert a Python object to a Rust value is using `.extract()`.\nIt returns a `PyResult` with a type error if the conversion fails, so usually you will use something like\n\n```rust\n# use pyo3::prelude::*;\n# use pyo3::types::PyList;\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| {\n#         let list = PyList::new(py, b\"foo\")?;\nlet v: Vec<i32> = list.extract()?;\n#         assert_eq!(&v, &[102, 111, 111]);\n#         Ok(())\n#     })\n# }\n```\n\nThis method is available for many Python object types, and can produce a wide variety of Rust types, which you can check out in the implementor list of [`FromPyObject`].\n\n[`FromPyObject`] is also implemented for your own Rust types wrapped as Python objects (see [the chapter about classes](../class.md)).\nThere, in order to both be able to operate on mutable references *and* satisfy Rust's rules of non-aliasing mutable references, you have to extract the PyO3 reference wrappers [`PyRef`] and [`PyRefMut`].\nThey work like the reference wrappers of `std::cell::RefCell` and ensure (at runtime) that Rust borrows are allowed.\n\n### Deriving [`FromPyObject`]\n\n[`FromPyObject`] can be automatically derived for many kinds of structs and enums if the member types themselves implement `FromPyObject`.\nThis even includes members with a generic type `T: FromPyObject`.\nDerivation for empty enums, enum variants and structs is not supported.\n\n### Deriving [`FromPyObject`] for structs\n\nThe derivation generates code that will attempt to access the attribute `my_string` on the Python object, i.e. `obj.getattr(\"my_string\")`, and call `extract()` on the attribute.\n\n```rust\nuse pyo3::prelude::*;\n\n#[derive(FromPyObject)]\nstruct RustyStruct {\n    my_string: String,\n}\n#\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| -> PyResult<()> {\n#         let module = PyModule::from_code(\n#             py,\n#             c\"class Foo:\n#             def __init__(self):\n#                 self.my_string = 'test'\",\n#             c\"<string>\",\n#             c\"\",\n#         )?;\n#\n#         let class = module.getattr(\"Foo\")?;\n#         let instance = class.call0()?;\n#         let rustystruct: RustyStruct = instance.extract()?;\n#         assert_eq!(rustystruct.my_string, \"test\");\n#         Ok(())\n#     })\n# }\n```\n\nBy setting the `#[pyo3(item)]` attribute on the field, PyO3 will attempt to extract the value by calling the `get_item` method on the Python object.\n\n```rust\nuse pyo3::prelude::*;\n\n#[derive(FromPyObject)]\nstruct RustyStruct {\n    #[pyo3(item)]\n    my_string: String,\n}\n#\n# use pyo3::types::PyDict;\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| -> PyResult<()> {\n#         let dict = PyDict::new(py);\n#         dict.set_item(\"my_string\", \"test\")?;\n#\n#         let rustystruct: RustyStruct = dict.extract()?;\n#         assert_eq!(rustystruct.my_string, \"test\");\n#         Ok(())\n#     })\n# }\n```\n\nThe argument passed to `getattr` and `get_item` can also be configured:\n\n```rust\nuse pyo3::prelude::*;\n\n#[derive(FromPyObject)]\nstruct RustyStruct {\n    #[pyo3(item(\"key\"))]\n    string_in_mapping: String,\n    #[pyo3(attribute(\"name\"))]\n    string_attr: String,\n}\n#\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| -> PyResult<()> {\n#         let module = PyModule::from_code(\n#             py,\n#             c\"class Foo(dict):\n#             def __init__(self):\n#                 self.name = 'test'\n#                 self['key'] = 'test2'\",\n#             c\"<string>\",\n#             c\"\",\n#         )?;\n#\n#         let class = module.getattr(\"Foo\")?;\n#         let instance = class.call0()?;\n#         let rustystruct: RustyStruct = instance.extract()?;\n# \t\tassert_eq!(rustystruct.string_attr, \"test\");\n#         assert_eq!(rustystruct.string_in_mapping, \"test2\");\n#\n#         Ok(())\n#     })\n# }\n```\n\nThis tries to extract `string_attr` from the attribute `name` and `string_in_mapping` from a mapping with the key `\"key\"`.\nThe arguments for `attribute` are restricted to non-empty string literals while `item` can take any valid literal that implements `ToBorrowedObject`.\n\nYou can use `#[pyo3(from_item_all)]` on a struct to extract every field with `get_item` method.\nIn this case, you can't use `#[pyo3(attribute)]` or barely use `#[pyo3(item)]` on any field.\nHowever, using `#[pyo3(item(\"key\"))]` to specify the key for a field is still allowed.\n\n```rust\nuse pyo3::prelude::*;\n\n#[derive(FromPyObject)]\n#[pyo3(from_item_all)]\nstruct RustyStruct {\n    foo: String,\n    bar: String,\n    #[pyo3(item(\"foobar\"))]\n    baz: String,\n}\n#\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| -> PyResult<()> {\n#         let py_dict = py.eval(c\"{'foo': 'foo', 'bar': 'bar', 'foobar': 'foobar'}\", None, None)?;\n#         let rustystruct: RustyStruct = py_dict.extract()?;\n# \t\t  assert_eq!(rustystruct.foo, \"foo\");\n#         assert_eq!(rustystruct.bar, \"bar\");\n#         assert_eq!(rustystruct.baz, \"foobar\");\n#\n#         Ok(())\n#     })\n# }\n```\n\n### Deriving [`FromPyObject`] for tuple structs\n\nTuple structs are also supported but do not allow customizing the extraction.\nThe input is always assumed to be a Python tuple with the same length as the Rust type, the `n`th field is extracted from the `n`th item in the Python tuple.\n\n```rust\nuse pyo3::prelude::*;\n\n#[derive(FromPyObject)]\nstruct RustyTuple(String, String);\n\n# use pyo3::types::PyTuple;\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| -> PyResult<()> {\n#         let tuple = PyTuple::new(py, vec![\"test\", \"test2\"])?;\n#\n#         let rustytuple: RustyTuple = tuple.extract()?;\n#         assert_eq!(rustytuple.0, \"test\");\n#         assert_eq!(rustytuple.1, \"test2\");\n#\n#         Ok(())\n#     })\n# }\n```\n\nTuple structs with a single field are treated as wrapper types which are described in the following section.\nTo override this behaviour and ensure that the input is in fact a tuple, specify the struct as\n\n```rust\nuse pyo3::prelude::*;\n\n#[derive(FromPyObject)]\nstruct RustyTuple((String,));\n\n# use pyo3::types::PyTuple;\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| -> PyResult<()> {\n#         let tuple = PyTuple::new(py, vec![\"test\"])?;\n#\n#         let rustytuple: RustyTuple = tuple.extract()?;\n#         assert_eq!((rustytuple.0).0, \"test\");\n#\n#         Ok(())\n#     })\n# }\n```\n\n### Deriving [`FromPyObject`] for wrapper types\n\nThe `pyo3(transparent)` attribute can be used on structs with exactly one field.\nThis results in extracting directly from the input object, i.e. `obj.extract()`, rather than trying to access an item or attribute.\nThis behaviour is enabled per default for newtype structs and tuple-variants with a single field.\n\n```rust\nuse pyo3::prelude::*;\n\n#[derive(FromPyObject)]\nstruct RustyTransparentTupleStruct(String);\n\n#[derive(FromPyObject)]\n#[pyo3(transparent)]\nstruct RustyTransparentStruct {\n    inner: String,\n}\n\n# use pyo3::types::PyString;\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| -> PyResult<()> {\n#         let s = PyString::new(py, \"test\");\n#\n#         let tup: RustyTransparentTupleStruct = s.extract()?;\n#         assert_eq!(tup.0, \"test\");\n#\n#         let stru: RustyTransparentStruct = s.extract()?;\n#         assert_eq!(stru.inner, \"test\");\n#\n#         Ok(())\n#     })\n# }\n```\n\n### Deriving [`FromPyObject`] for enums\n\nThe `FromPyObject` derivation for enums generates code that tries to extract the variants in the order of the fields.\nAs soon as a variant can be extracted successfully, that variant is returned.\nThis makes it possible to extract Python union types like `str | int`.\n\nThe same customizations and restrictions described for struct derivations apply to enum variants, i.e. a tuple variant assumes that the input is a Python tuple, and a struct variant defaults to extracting fields as attributes but can be configured in the same manner.\nThe `transparent` attribute can be applied to single-field-variants.\n\n```rust\nuse pyo3::prelude::*;\n\n#[derive(FromPyObject)]\n# #[derive(Debug)]\nenum RustyEnum<'py> {\n    Int(usize),                    // input is a positive int\n    String(String),                // input is a string\n    IntTuple(usize, usize),        // input is a 2-tuple with positive ints\n    StringIntTuple(String, usize), // input is a 2-tuple with String and int\n    Coordinates3d {\n        // needs to be in front of 2d\n        x: usize,\n        y: usize,\n        z: usize,\n    },\n    Coordinates2d {\n        // only gets checked if the input did not have `z`\n        #[pyo3(attribute(\"x\"))]\n        a: usize,\n        #[pyo3(attribute(\"y\"))]\n        b: usize,\n    },\n    #[pyo3(transparent)]\n    CatchAll(Bound<'py, PyAny>), // This extraction never fails\n}\n#\n# use pyo3::types::{PyBytes, PyString};\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| -> PyResult<()> {\n#         {\n#             let thing = 42_u8.into_pyobject(py)?;\n#             let rust_thing: RustyEnum<'_> = thing.extract()?;\n#\n#             assert_eq!(\n#                 42,\n#                 match rust_thing {\n#                     RustyEnum::Int(i) => i,\n#                     other => unreachable!(\"Error extracting: {:?}\", other),\n#                 }\n#             );\n#         }\n#         {\n#             let thing = PyString::new(py, \"text\");\n#             let rust_thing: RustyEnum<'_> = thing.extract()?;\n#\n#             assert_eq!(\n#                 \"text\",\n#                 match rust_thing {\n#                     RustyEnum::String(i) => i,\n#                     other => unreachable!(\"Error extracting: {:?}\", other),\n#                 }\n#             );\n#         }\n#         {\n#             let thing = (32_u8, 73_u8).into_pyobject(py)?;\n#             let rust_thing: RustyEnum<'_> = thing.extract()?;\n#\n#             assert_eq!(\n#                 (32, 73),\n#                 match rust_thing {\n#                     RustyEnum::IntTuple(i, j) => (i, j),\n#                     other => unreachable!(\"Error extracting: {:?}\", other),\n#                 }\n#             );\n#         }\n#         {\n#             let thing = (\"foo\", 73_u8).into_pyobject(py)?;\n#             let rust_thing: RustyEnum<'_> = thing.extract()?;\n#\n#             assert_eq!(\n#                 (String::from(\"foo\"), 73),\n#                 match rust_thing {\n#                     RustyEnum::StringIntTuple(i, j) => (i, j),\n#                     other => unreachable!(\"Error extracting: {:?}\", other),\n#                 }\n#             );\n#         }\n#         {\n#             let module = PyModule::from_code(\n#                 py,\n#                 c\"class Foo(dict):\n#             def __init__(self):\n#                 self.x = 0\n#                 self.y = 1\n#                 self.z = 2\",\n#                 c\"<string>\",\n#                 c\"\",\n#             )?;\n#\n#             let class = module.getattr(\"Foo\")?;\n#             let instance = class.call0()?;\n#             let rust_thing: RustyEnum<'_> = instance.extract()?;\n#\n#             assert_eq!(\n#                 (0, 1, 2),\n#                 match rust_thing {\n#                     RustyEnum::Coordinates3d { x, y, z } => (x, y, z),\n#                     other => unreachable!(\"Error extracting: {:?}\", other),\n#                 }\n#             );\n#         }\n#\n#         {\n#             let module = PyModule::from_code(\n#                 py,\n#                 c\"class Foo(dict):\n#             def __init__(self):\n#                 self.x = 3\n#                 self.y = 4\",\n#                 c\"<string>\",\n#                 c\"\",\n#             )?;\n#\n#             let class = module.getattr(\"Foo\")?;\n#             let instance = class.call0()?;\n#             let rust_thing: RustyEnum<'_> = instance.extract()?;\n#\n#             assert_eq!(\n#                 (3, 4),\n#                 match rust_thing {\n#                     RustyEnum::Coordinates2d { a, b } => (a, b),\n#                     other => unreachable!(\"Error extracting: {:?}\", other),\n#                 }\n#             );\n#         }\n#\n#         {\n#             let thing = PyBytes::new(py, b\"text\");\n#             let rust_thing: RustyEnum<'_> = thing.extract()?;\n#\n#             assert_eq!(\n#                 b\"text\",\n#                 match rust_thing {\n#                     RustyEnum::CatchAll(ref i) => i.cast::<PyBytes>()?.as_bytes(),\n#                     other => unreachable!(\"Error extracting: {:?}\", other),\n#                 }\n#             );\n#         }\n#         Ok(())\n#     })\n# }\n```\n\nIf none of the enum variants match, a `PyTypeError` containing the names of the tested variants is returned.\nThe names reported in the error message can be customized through the `#[pyo3(annotation = \"name\")]` attribute, e.g. to use conventional Python type names:\n\n```rust\nuse pyo3::prelude::*;\n\n#[derive(FromPyObject)]\n# #[derive(Debug)]\nenum RustyEnum {\n    #[pyo3(transparent, annotation = \"str\")]\n    String(String),\n    #[pyo3(transparent, annotation = \"int\")]\n    Int(isize),\n}\n#\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| -> PyResult<()> {\n#         {\n#             let thing = 42_u8.into_pyobject(py)?;\n#             let rust_thing: RustyEnum = thing.extract()?;\n#\n#             assert_eq!(\n#                 42,\n#                 match rust_thing {\n#                     RustyEnum::Int(i) => i,\n#                     other => unreachable!(\"Error extracting: {:?}\", other),\n#                 }\n#             );\n#         }\n#\n#         {\n#             let thing = \"foo\".into_pyobject(py)?;\n#             let rust_thing: RustyEnum = thing.extract()?;\n#\n#             assert_eq!(\n#                 \"foo\",\n#                 match rust_thing {\n#                     RustyEnum::String(i) => i,\n#                     other => unreachable!(\"Error extracting: {:?}\", other),\n#                 }\n#             );\n#         }\n#\n#         {\n#             let thing = b\"foo\".into_pyobject(py)?;\n#             let error = thing.extract::<RustyEnum>().unwrap_err();\n#             assert!(error.is_instance_of::<pyo3::exceptions::PyTypeError>(py));\n#         }\n#\n#         Ok(())\n#     })\n# }\n```\n\nIf the input is neither a string nor an integer, the error message will be: `\"'<INPUT_TYPE>' is not an instance of 'str | int'\"`.\n\n### `#[derive(FromPyObject)]` Container Attributes\n\n- `pyo3(transparent)`\n  - extract the field directly from the object as `obj.extract()` instead of `get_item()` or\n      `getattr()`\n  - Newtype structs and tuple-variants are treated as transparent per default.\n  - only supported for single-field structs and enum variants\n- `pyo3(annotation = \"name\")`\n  - changes the name of the failed variant in the generated error message in case of failure.\n  - e.g. `pyo3(\"int\")` reports the variant's type as `int`.\n  - only supported for enum variants\n- `pyo3(rename_all = \"...\")`\n  - renames all attributes/item keys according to the specified renaming rule\n  - Possible values are: \"camelCase\", \"kebab-case\", \"lowercase\", \"PascalCase\", \"SCREAMING-KEBAB-CASE\", \"SCREAMING_SNAKE_CASE\", \"snake_case\", \"UPPERCASE\".\n  - fields with an explicit renaming via `attribute(...)`/`item(...)` are not affected\n\n### `#[derive(FromPyObject)]` Field Attributes\n\n- `pyo3(attribute)`, `pyo3(attribute(\"name\"))`\n  - retrieve the field from an attribute, possibly with a custom name specified as an argument\n  - argument must be a string-literal.\n- `pyo3(item)`, `pyo3(item(\"key\"))`\n  - retrieve the field from a mapping, possibly with the custom key specified as an argument.\n  - can be any literal that implements `ToBorrowedObject`\n- `pyo3(from_py_with = ...)`\n  - apply a custom function to convert the field from Python the desired Rust type.\n  - the argument must be the path to the function.\n  - the function signature must be `fn(&Bound<PyAny>) -> PyResult<T>` where `T` is the Rust type of the argument.\n- `pyo3(default)`, `pyo3(default = ...)`\n  - if the argument is set, uses the given default value.\n  - in this case, the argument must be a Rust expression returning a value of the desired Rust type.\n  - if the argument is not set, [`Default::default`](https://doc.rust-lang.org/std/default/trait.Default.html#tymethod.default) is used.\n  - note that the default value is only used if the field is not set.\n    If the field is set and the conversion function from Python to Rust fails, an exception is raised and the default value is not used.\n  - this attribute is only supported on named fields.\n\nFor example, the code below applies the given conversion function on the `\"value\"` dict item to compute its length or fall back to the type default value (0):\n\n```rust\nuse pyo3::prelude::*;\n\n#[derive(FromPyObject)]\nstruct RustyStruct {\n    #[pyo3(item(\"value\"), default, from_py_with = Bound::<'_, PyAny>::len)]\n    len: usize,\n    #[pyo3(item)]\n    other: usize,\n}\n#\n# use pyo3::types::PyDict;\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| -> PyResult<()> {\n#         // Filled case\n#         let dict = PyDict::new(py);\n#         dict.set_item(\"value\", (1,)).unwrap();\n#         dict.set_item(\"other\", 1).unwrap();\n#         let result = dict.extract::<RustyStruct>()?;\n#         assert_eq!(result.len, 1);\n#         assert_eq!(result.other, 1);\n#\n#         // Empty case\n#         let dict = PyDict::new(py);\n#         dict.set_item(\"other\", 1).unwrap();\n#         let result = dict.extract::<RustyStruct>()?;\n#         assert_eq!(result.len, 0);\n#         assert_eq!(result.other, 1);\n#         Ok(())\n#     })\n# }\n```\n\n### ⚠ Phase-Out of `FromPyObject` blanket implementation for cloneable PyClasses ⚠\n\nHistorically PyO3 has provided a blanket implementation for `#[pyclass]` types that also implement `Clone`, to allow extraction of such types by value.\nOver time this has turned out problematic for a few reasons, the major one being the prevention of custom conversions by downstream crates if their type is `Clone`.\nOver the next few releases the blanket implementation is gradually phased out, and eventually replaced by an opt-in option.\nAs a first step of this migration a new `skip_from_py_object` option for `#[pyclass]` was introduced, to opt-out of the blanket implementation and allow downstream users to provide their own implementation:\n\n```rust\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n\n#[pyclass(skip_from_py_object)] // opt-out of the PyO3 FromPyObject blanket\n#[derive(Clone)]\nstruct Number(i32);\n\nimpl<'py> FromPyObject<'_, 'py> for Number {\n    type Error = PyErr;\n\n    fn extract(obj: pyo3::Borrowed<'_, 'py, pyo3::PyAny>) -> Result<Self, Self::Error> {\n        if let Ok(obj) = obj.cast::<Self>() { // first try extraction via class object\n            Ok(obj.borrow().clone())\n        } else {\n            obj.extract::<i32>().map(Self) // otherwise try integer directly\n        }\n    }\n}\n```\n\nAs a second step the `from_py_object` option was introduced.\nThis option also opts-out of the blanket implementation and instead generates a custom `FromPyObject` implementation for the pyclass which is functionally equivalent to the blanket.\n\n## `IntoPyObject`\n\nThe [`IntoPyObject`] trait defines the to-python conversion for a Rust type.\nAll types in PyO3 implement this trait, as does a `#[pyclass]` which doesn't use `extends`.\n\nThis trait defines a single method, `into_pyobject()`, which returns a [`Result`] with `Ok` and `Err` types depending on the input value.\nFor convenience, there is a companion [`IntoPyObjectExt`] trait which adds methods such as `into_py_any()` which converts the `Ok` and `Err` types to commonly used types (in the case of `into_py_any()`, `Py<PyAny>` and `PyErr` respectively).\n\nOccasionally you may choose to implement this for custom types which are mapped to Python types *without* having a unique python type.\n\n### derive macro\n\n`IntoPyObject` can be implemented using our derive macro.\nBoth `struct`s and `enum`s are supported.\n\n`struct`s will turn into a `PyDict` using the field names as keys, tuple `struct`s will turn convert into `PyTuple` with the fields in declaration order.\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use std::collections::HashMap;\n# use std::hash::Hash;\n\n// structs convert into `PyDict` with field names as keys\n#[derive(IntoPyObject)]\nstruct Struct {\n    count: usize,\n    obj: Py<PyAny>,\n}\n\n// tuple structs convert into `PyTuple`\n// lifetimes and generics are supported, the impl will be bounded by\n// `K: IntoPyObject, V: IntoPyObject`\n#[derive(IntoPyObject)]\nstruct Tuple<'a, K: Hash + Eq, V>(&'a str, HashMap<K, V>);\n```\n\nFor structs with a single field (newtype pattern) the `#[pyo3(transparent)]` option can be used to forward the implementation to the inner type.\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n\n// newtype tuple structs are implicitly `transparent`\n#[derive(IntoPyObject)]\nstruct TransparentTuple(Py<PyAny>);\n\n#[derive(IntoPyObject)]\n#[pyo3(transparent)]\nstruct TransparentStruct<'py> {\n    inner: Bound<'py, PyAny>, // `'py` lifetime will be used as the Python lifetime\n}\n```\n\nFor `enum`s each variant is converted according to the rules for `struct`s above.\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use std::collections::HashMap;\n# use std::hash::Hash;\n\n#[derive(IntoPyObject)]\nenum Enum<'a, 'py, K: Hash + Eq, V> { // enums are supported and convert using the same\n    TransparentTuple(Py<PyAny>),       // rules on the variants as the structs above\n    #[pyo3(transparent)]\n    TransparentStruct { inner: Bound<'py, PyAny> },\n    Tuple(&'a str, HashMap<K, V>),\n    Struct { count: usize, obj: Py<PyAny> }\n}\n```\n\nAdditionally `IntoPyObject` can be derived for a reference to a struct or enum using the `IntoPyObjectRef` derive macro.\nAll the same rules from above apply as well.\n\n#### `#[derive(IntoPyObject)]`/`#[derive(IntoPyObjectRef)]` Field Attributes\n\n- `pyo3(into_py_with = ...)`\n  - apply a custom function to convert the field from Rust into Python.\n  - the argument must be the function identifier\n  - the function signature must be `fn(Cow<'_, T>, Python<'py>) -> PyResult<Bound<'py, PyAny>>` where `T` is the Rust type of the argument.\n    - `#[derive(IntoPyObject)]` will invoke the function with `Cow::Owned`\n    - `#[derive(IntoPyObjectRef)]` will invoke the function with `Cow::Borrowed`\n\n    ```rust,no_run\n    # use pyo3::prelude::*;\n    # use pyo3::IntoPyObjectExt;\n    # use std::borrow::Cow;\n    #[derive(Clone)]\n    struct NotIntoPy(usize);\n\n    #[derive(IntoPyObject, IntoPyObjectRef)]\n    struct MyStruct {\n        #[pyo3(into_py_with = convert)]\n        not_into_py: NotIntoPy,\n    }\n\n    /// Convert `NotIntoPy` into Python\n    fn convert<'py>(not_into_py: Cow<'_, NotIntoPy>, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {\n        not_into_py.0.into_bound_py_any(py)\n    }\n    ```\n\n### manual implementation\n\nIf the derive macro is not suitable for your use case, `IntoPyObject` can be implemented manually as demonstrated below.\n\n```rust,no_run\n# use pyo3::prelude::*;\n# #[allow(dead_code)]\nstruct MyPyObjectWrapper(Py<PyAny>);\n\nimpl<'py> IntoPyObject<'py> for MyPyObjectWrapper {\n    type Target = PyAny; // the Python type\n    type Output = Bound<'py, Self::Target>; // in most cases this will be `Bound`\n    type Error = std::convert::Infallible; // the conversion error type, has to be convertible to `PyErr`\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.0.into_bound(py))\n    }\n}\n\n// equivalent to former `ToPyObject` implementations\nimpl<'a, 'py> IntoPyObject<'py> for &'a MyPyObjectWrapper {\n    type Target = PyAny;\n    type Output = Borrowed<'a, 'py, Self::Target>; // `Borrowed` can be used to optimized reference counting\n    type Error = std::convert::Infallible;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.0.bind_borrowed(py))\n    }\n}\n```\n\n### `BoundObject` for conversions that may be `Bound` or `Borrowed`\n\n`IntoPyObject::into_py_object` returns either `Bound` or `Borrowed` depending on the implementation for a concrete type.\nFor example, the `IntoPyObject` implementation for `u32` produces a `Bound<'py, PyInt>` and the `bool` implementation produces a `Borrowed<'py, 'py, PyBool>`:\n\n```rust,no_run\nuse pyo3::prelude::*;\nuse pyo3::IntoPyObject;\nuse pyo3::types::{PyBool, PyInt};\n\nlet ints: Vec<u32> = vec![1, 2, 3, 4];\nlet bools = vec![true, false, false, true];\n\nPython::attach(|py| {\n    let ints_as_pyint: Vec<Bound<'_, PyInt>> = ints\n        .iter()\n        .map(|x| Ok(x.into_pyobject(py)?))\n        .collect::<PyResult<_>>()\n        .unwrap();\n\n    let bools_as_pybool: Vec<Borrowed<'_, '_, PyBool>> = bools\n        .iter()\n        .map(|x| Ok(x.into_pyobject(py)?))\n        .collect::<PyResult<_>>()\n        .unwrap();\n});\n```\n\nIn this example if we wanted to combine `ints_as_pyints` and `bools_as_pybool` into a single `Vec<Py<PyAny>>` to return from the `Python::attach` closure, we would have to manually convert the concrete types for the smart pointers and the python types.\n\nInstead, we can write a function that generically converts vectors of either integers or bools into a vector of `Py<PyAny>` using the [`BoundObject`] trait:\n\n```rust,no_run\n# use pyo3::prelude::*;\n# use pyo3::BoundObject;\n# use pyo3::IntoPyObject;\n\n# let bools = vec![true, false, false, true];\n# let ints = vec![1, 2, 3, 4];\n\nfn convert_to_vec_of_pyobj<'py, T>(py: Python<'py>, the_vec: Vec<T>) -> PyResult<Vec<Py<PyAny>>>\nwhere\n   T: IntoPyObject<'py> + Copy\n{\n    the_vec.iter()\n        .map(|x| {\n            Ok(\n                // Note: the below is equivalent to `x.into_py_any()`\n                // from the `IntoPyObjectExt` trait\n                x.into_pyobject(py)\n                .map_err(Into::into)?\n                .into_any()\n                .unbind()\n            )\n        })\n        .collect()\n}\n\nlet vec_of_pyobjs: Vec<Py<PyAny>> = Python::attach(|py| {\n    let mut bools_as_pyany = convert_to_vec_of_pyobj(py, bools).unwrap();\n    let mut ints_as_pyany = convert_to_vec_of_pyobj(py, ints).unwrap();\n    let mut result: Vec<Py<PyAny>> = vec![];\n    result.append(&mut bools_as_pyany);\n    result.append(&mut ints_as_pyany);\n    result\n});\n```\n\nIn the example above we used `BoundObject::into_any` and `BoundObject::unbind` to manipulate the python types and smart pointers into the result type we wanted to produce from the function.\n\n[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html\n[`IntoPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.IntoPyObject.html\n[`IntoPyObjectExt`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.IntoPyObjectExt.html\n\n[`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html\n[`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRefMut.html\n[`BoundObject`]: {{#PYO3_DOCS_URL}}/pyo3/instance/trait.BoundObject.html\n\n[`Result`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html\n"
  },
  {
    "path": "guide/src/conversions.md",
    "content": "# Type conversions\n\nIn this portion of the guide we'll talk about the mapping of Python types to Rust types offered by PyO3, as well as the traits available to perform conversions between them.\n\nSee also the conversion [tables](conversions/tables.md) and [traits](conversions/traits.md).\n"
  },
  {
    "path": "guide/src/debugging.md",
    "content": "# Debugging\n\n## Macros\n\nPyO3's attributes (`#[pyclass]`, `#[pymodule]`, etc.) are [procedural macros](https://doc.rust-lang.org/reference/procedural-macros.html), which means that they rewrite the source of the annotated item.\nYou can view the generated source with the following command, which also expands a few other things:\n\n```bash\ncargo rustc --profile=check -- -Z unstable-options --pretty=expanded > expanded.rs; rustfmt expanded.rs\n```\n\n(You might need to install [rustfmt](https://github.com/rust-lang-nursery/rustfmt) if you don't already have it.)\n\nYou can also debug classic `!`-macros by adding `-Z trace-macros`:\n\n```bash\ncargo rustc --profile=check -- -Z unstable-options --pretty=expanded -Z trace-macros > expanded.rs; rustfmt expanded.rs\n```\n\nNote that those commands require using the nightly build of rust and may occasionally have bugs.\nSee [cargo expand](https://github.com/dtolnay/cargo-expand) for a more elaborate and stable version of those commands.\n\n## Running with Valgrind\n\nValgrind is a tool to detect memory management bugs such as memory leaks.\n\nYou first need to install a debug build of Python, otherwise Valgrind won't produce usable results.\nIn Ubuntu there's e.g. a `python3-dbg` package.\n\nActivate an environment with the debug interpreter and recompile.\nIf you're on Linux, use `ldd` with the name of your binary and check that you're linking e.g. `libpython3.7d.so.1.0` instead of `libpython3.7.so.1.0`.\n\n[Download the suppressions file for CPython](https://raw.githubusercontent.com/python/cpython/master/Misc/valgrind-python.supp).\n\nRun Valgrind with `valgrind --suppressions=valgrind-python.supp ./my-command --with-options`\n\n## Getting a stacktrace\n\nThe best start to investigate a crash such as an segmentation fault is a backtrace.\nYou can set `RUST_BACKTRACE=1` as an environment variable to get the stack trace on a `panic!`.\nAlternatively you can use a debugger such as `gdb` to explore the issue.\nRust provides a wrapper, `rust-gdb`, which has pretty-printers for inspecting Rust variables.\nSince PyO3 uses `cdylib` for Python shared objects, it does not receive the pretty-print debug hooks in `rust-gdb` ([rust-lang/rust#96365](https://github.com/rust-lang/rust/issues/96365)).\nThe mentioned issue contains a workaround for enabling pretty-printers in this case.\n\n- Link against a debug build of python as described in the previous chapter\n- Run `rust-gdb <my-binary>`\n- Set a breakpoint (`b`) on `rust_panic` if you are investigating a `panic!`\n- Enter `r` to run\n- After the crash occurred, enter `bt` or `bt full` to print the stacktrace\n\n Often it is helpful to run a small piece of Python code to exercise a section of Rust.\n\n ```console\n rust-gdb --args python -c \"import my_package; my_package.sum_to_string(1, 2)\"\n ```\n\n## Setting breakpoints in your Rust code\n\nOne of the preferred ways by developers to debug their code is by setting breakpoints.\nThis can be achieved in PyO3 by using a debugger like `rust-gdb` or `rust-lldb` with your Python interpreter.\n\nFor more information about how to use both `lldb` and `gdb` you can read the [gdb to lldb command map](https://lldb.llvm.org/use/map.html) from the lldb documentation.\n\n### Common setup\n\n1. Compile your extension with debug symbols:\n\n   ```bash\n   # Debug is the default for maturin, but you can explicitly ensure debug symbols with:\n   RUSTFLAGS=\"-g\" maturin develop\n\n   # For setuptools-rust users:\n   pip install -e .\n   ```\n\n   > **Note**: When using debuggers, make sure that `python` resolves to an actual Python binary or symlink and not a shim script.\n   Some tools like pyenv use shim scripts which can interfere with debugging.\n\n### Debugger specific setup\n\nDepending on your OS and your preferences you can use two different debuggers, `rust-gdb` or `rust-lldb`.\n\n{{#tabs }}\n{{#tab name=\"Using rust-gdb\" }}\n\n1. Launch rust-gdb with the Python interpreter:\n\n   ```bash\n   rust-gdb --args python\n   ```\n\n2. Once in gdb, set a breakpoint in your Rust code:\n\n   ```bash\n   (gdb) break your_module.rs:42\n   ```\n\n3. Run your Python script that imports and uses your Rust extension:\n\n   ```bash\n   # Option 1: Run an inline Python command\n   (gdb) run -c \"import your_module; your_module.your_function()\"\n\n   # Option 2: Run a Python script\n   (gdb) run your_script.py\n\n   # Option 3: Run pytest tests\n   (gdb) run -m pytest tests/test_something.py::TestName\n   ```\n\n{{#endtab }}\n{{#tab name=\"Using rust-lldb (for macOS users)\" }}\n\n1. Start rust-lldb with Python:\n\n   ```bash\n   rust-lldb -- python\n   ```\n\n2. Set breakpoints in your Rust code:\n\n   ```bash\n   (lldb) breakpoint set --file your_module.rs --line 42\n   ```\n\n3. Run your Python script:\n\n   ```bash\n   # Option 1: Run an inline Python command\n   (lldb) run -c \"import your_module; your_module.your_function()\"\n\n   # Option 2: Run a Python script\n   (lldb) run your_script.py\n\n   # Option 3: Run pytest tests\n   (lldb) run -m pytest tests/test_something.py::TestName\n   ```\n\n{{#endtab }}\n{{#endtabs }}\n\n### Using VS Code\n\nVS Code with the Rust and Python extensions provides an integrated debugging experience:\n\n1. First, install the necessary VS Code extensions:\n\n   - [Rust Analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)\n   - [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)\n   - [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python)\n\n2. Create a `.vscode/launch.json` file with a configuration that uses the LLDB Debug Launcher:\n\n   ```json\n   {\n       \"version\": \"0.2.0\",\n       \"configurations\": [\n           {\n               \"name\": \"Debug PyO3\",\n               \"type\": \"lldb\",\n               \"request\": \"attach\",\n               \"program\": \"${workspaceFolder}/.venv/bin/python\",\n               \"pid\": \"${command:pickProcess}\",\n               \"sourceLanguages\": [\n                   \"rust\"\n               ]\n           },\n           {\n               \"name\": \"Launch Python with PyO3\",\n               \"type\": \"lldb\",\n               \"request\": \"launch\",\n               \"program\": \"${workspaceFolder}/.venv/bin/python\",\n               \"args\": [\"${file}\"],\n               \"cwd\": \"${workspaceFolder}\",\n               \"sourceLanguages\": [\"rust\"]\n           },\n           {\n               \"name\": \"Debug PyO3 with Args\",\n               \"type\": \"lldb\",\n               \"request\": \"launch\",\n               \"program\": \"${workspaceFolder}/.venv/bin/python\",\n               \"args\": [\"path/to/your/script.py\", \"arg1\", \"arg2\"],\n               \"cwd\": \"${workspaceFolder}\",\n               \"sourceLanguages\": [\"rust\"]\n           },\n           {\n               \"name\": \"Debug PyO3 Tests\",\n               \"type\": \"lldb\",\n               \"request\": \"launch\",\n               \"program\": \"${workspaceFolder}/.venv/bin/python\",\n               \"args\": [\"-m\", \"pytest\", \"tests/your_test.py::test_function\", \"-v\"],\n               \"cwd\": \"${workspaceFolder}\",\n               \"sourceLanguages\": [\"rust\"]\n           }\n        ]\n   }\n   ```\n\n   This configuration supports multiple debugging scenarios:\n\n   - Attaching to a running Python process\n   - Launching the currently open Python file\n   - Running a specific script with command-line arguments\n   - Running pytest tests\n\n3. Set breakpoints in your Rust code by clicking in the gutter next to line numbers.\n\n4. Start debugging:\n   - For attaching to a running Python process: First start the process, then select the \"Debug PyO3\" configuration and click Start Debugging (F5).\n     You'll be prompted to select the Python process to attach to.\n   - For launching a Python script: Open your Python script, select the \"Launch Python with PyO3\" configuration and click Start Debugging (F5).\n   - For running with arguments: Select \"Debug PyO3 with Args\" (remember to edit the configuration with your actual script path and arguments).\n   - For running tests: Select \"Debug PyO3 Tests\" (edit the test path as needed).\n\n5. When debugging PyO3 code:\n   - You can inspect Rust variables and data structures\n   - Use the debug console to evaluate expressions\n   - Step through Rust code line by line using the step controls\n   - Set conditional breakpoints for more complex debugging scenarios\n\n### Advanced Debugging Configurations\n\nFor advanced debugging scenarios, you might want to add environment variables or enable specific Rust debug flags:\n\n```json\n{\n    \"name\": \"Debug PyO3 with Environment\",\n    \"type\": \"lldb\",\n    \"request\": \"launch\",\n    \"program\": \"${workspaceFolder}/.venv/bin/python\",\n    \"args\": [\"${file}\"],\n    \"env\": {\n        \"RUST_BACKTRACE\": \"1\",\n        \"PYTHONPATH\": \"${workspaceFolder}\"\n    },\n    \"sourceLanguages\": [\"rust\"]\n}\n```\n\n### Debugging from Jupyter Notebooks\n\nFor Jupyter Notebooks run from VS Code, you can use the following helper functions to automate the launch configuration:\n\n```python\nfrom pathlib import Path\nimport os\nimport json\nimport sys\n\n\ndef update_launch_json(vscode_config_file_path=None):\n    \"\"\"Update VSCode launch.json with the correct Jupyter kernel PID.\n\n    Args:\n        vscode_config_file_path (str, optional): Path to the .vscode/launch.json file.\n            If not provided, will use the current working directory.\n    \"\"\"\n    pid = get_jupyter_kernel_pid()\n    if not pid:\n        print(\"Could not determine Jupyter kernel PID.\")\n        return\n\n    # Determine launch.json path\n    if vscode_config_file_path:\n        launch_json_path = vscode_config_file_path\n    else:\n        launch_json_path = os.path.join(Path(os.getcwd()), \".vscode\", \"launch.json\")\n\n    # Get Python interpreter path\n    python_path = sys.executable\n\n    # Default debugger config\n    debug_config = {\n        \"version\": \"0.2.0\",\n        \"configurations\": [\n            {\n                \"name\": \"Debug PyO3 (Jupyter)\",\n                \"type\": \"lldb\",\n                \"request\": \"attach\",\n                \"program\": python_path,\n                \"pid\": pid,\n                \"sourceLanguages\": [\"rust\"],\n            },\n            {\n                \"name\": \"Launch Python with PyO3\",\n                \"type\": \"lldb\",\n                \"request\": \"launch\",\n                \"program\": python_path,\n                \"args\": [\"${file}\"],\n                \"cwd\": \"${workspaceFolder}\",\n                \"sourceLanguages\": [\"rust\"]\n            }\n        ],\n    }\n\n    # Create .vscode directory if it doesn't exist\n    try:\n        os.makedirs(os.path.dirname(launch_json_path), exist_ok=True)\n\n        # If launch.json already exists, try to update it instead of overwriting\n        if os.path.exists(launch_json_path):\n            try:\n                with open(launch_json_path, \"r\") as f:\n                    existing_config = json.load(f)\n\n                # Check if our configuration already exists\n                config_exists = False\n                for config in existing_config.get(\"configurations\", []):\n                    if config.get(\"name\") == \"Debug PyO3 (Jupyter)\":\n                        config[\"pid\"] = pid\n                        config[\"program\"] = python_path\n                        config_exists = True\n\n                if not config_exists:\n                    existing_config.setdefault(\"configurations\", []).append(debug_config[\"configurations\"][0])\n\n                debug_config = existing_config\n            except Exception:\n                # If reading fails, we'll just overwrite with our new configuration\n                pass\n\n        with open(launch_json_path, \"w\") as f:\n            json.dump(debug_config, f, indent=4)\n        print(f\"Updated launch.json with PID: {pid} at {launch_json_path}\")\n    except Exception as e:\n        print(f\"Error updating launch.json: {e}\")\n\n\ndef get_jupyter_kernel_pid():\n    \"\"\"Find the process ID (PID) of the running Jupyter kernel.\n\n    Returns:\n        int: The process ID of the Jupyter kernel, or None if not found.\n    \"\"\"\n    # Check if we're running in a Jupyter environment\n    if 'ipykernel' in sys.modules:\n        pid = os.getpid()\n        print(f\"Jupyter kernel PID: {pid}\")\n        return pid\n    else:\n        print(\"Not running in a Jupyter environment.\")\n        return None\n```\n\nTo use these functions:\n\n1. Run the cell containing these functions in your Jupyter notebook\n2. Run `update_launch_json()` in a cell\n3. In VS Code, select the \"Debug PyO3 (Jupyter)\" configuration and start debugging\n\n## Thread Safety and Compiler Sanitizers\n\nPyO3 attempts to match the Rust language-level guarantees for thread safety, but that does not preclude other code outside of the control of PyO3 or buggy code managed by a PyO3 extension from creating a thread safety issue.\nAnalyzing whether or not a piece of Rust code that uses the CPython C API is thread safe can be quite complicated, since many Python operations can lead to arbitrary Python code execution.\nAutomated ways to discover thread safety issues can often be more fruitful than code analysis.\n\n[ThreadSanitizer](https://clang.llvm.org/docs/ThreadSanitizer.html) is a thread safety checking runtime that can be used to detect data races triggered by thread safety bugs or incorrect use of thread-unsafe data structures.\nWhile it can only detect data races triggered by code at runtime, if it does detect something the reports often point to exactly where the problem is happening.\n\nTo use `ThreadSanitizer` with a library that depends on PyO3, you will need to install a nightly Rust toolchain, along with the `rust-src` component, since you will need to compile the Rust standard library:\n\n```bash\nrustup install nightly\nrustup override set nightly\nrustup component add rust-src\n```\n\nYou will also need a version of CPython compiled using LLVM/Clang with the same major version of LLVM as is currently used to compile nightly Rust.\nAs of March 2025, Rust nightly uses LLVM 20.\n\nThe [cpython_sanity docker images](https://github.com/nascheme/cpython_sanity) contain a development environment with a pre-compiled version of CPython 3.13 or 3.14 as well as optionally NumPy and SciPy, all compiled using LLVM 20 and ThreadSanitizer.\n\nAfter activating a nightly Rust toolchain, you can build your project using `ThreadSanitizer` with the following command:\n\n```bash\nRUSTFLAGS=\"-Zsanitizer=thread\" maturin develop -Zbuild-std --target x86_64-unknown-linux-gnu\n```\n\nIf you are not running on an x86_64 Linux machine, you should replace `x86_64-unknown-linux-gnu` with the [target triple](https://doc.rust-lang.org/rustc/platform-support.html#tier-1-with-host-tools) that is appropriate for your system.\nYou can also replace `maturin develop` with `cargo test` to run `cargo` tests.\nNote that `cargo` runs tests in a thread pool, so `cargo` tests can be a good way to find thread safety issues.\n\nYou can also replace `-Zsanitizer=thread` with `-Zsanitizer=address` or any of the other sanitizers that are [supported by Rust](https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html).\nNote that you'll need to build CPython from source with the appropriate [configure script flags](https://docs.python.org/3/using/configure.html#cmdoption-with-address-sanitizer) to use the same sanitizer environment as you want to use for your Rust code.\n"
  },
  {
    "path": "guide/src/ecosystem/async-await.md",
    "content": "# Using `async` and `await`\n\n*`async`/`await` support is currently being integrated in PyO3.*\n*See the [dedicated documentation](../async-await.md)*\n\nIf you are working with a Python library that makes use of async functions or wish to provide Python bindings for an async Rust library, [`pyo3-async-runtimes`](https://github.com/PyO3/pyo3-async-runtimes) likely has the tools you need.\nIt provides conversions between async functions in both Python and Rust and was designed with first-class support for popular Rust runtimes such as [`tokio`](https://tokio.rs/) and [`async-std`](https://async.rs/).\nIn addition, all async Python code runs on the default `asyncio` event loop, so `pyo3-async-runtimes` should work just fine with existing Python libraries.\n\n## Additional Information\n\n- Managing event loop references can be tricky with `pyo3-async-runtimes`.\n  See [Event Loop References](https://docs.rs/pyo3-async-runtimes/#event-loop-references-and-contextvars) in the API docs to get a better intuition for how event loop references are managed in this library.\n- Testing `pyo3-async-runtimes` libraries and applications requires a custom test harness since Python requires control over the main thread.\n  You can find a testing guide in the [API docs for the `testing` module](https://docs.rs/pyo3-async-runtimes/latest/pyo3_async_runtimes/testing)\n"
  },
  {
    "path": "guide/src/ecosystem/logging.md",
    "content": "# Logging\n\nIt is desirable if both the Python and Rust parts of the application end up logging using the same configuration into the same place.\n\nThis section of the guide briefly discusses how to connect the two languages' logging ecosystems together.\nThe recommended way for Python extension modules is to configure Rust's logger to send log messages to Python using the `pyo3-log` crate.\nFor users who want to do the opposite and send Python log messages to Rust, see the note at the end of this guide.\n\n## Using `pyo3-log` to send Rust log messages to Python\n\nThe [pyo3-log] crate allows sending the messages from the Rust side to Python's [logging] system.\nThis is mostly suitable for writing native extensions for Python programs.\n\nUse [`pyo3_log::init`][init] to install the logger in its default configuration.\nIt's also possible to tweak its configuration (mostly to tune its performance).\n\n```rust,no_run\n#[pyo3::pymodule]\nmod my_module {\n    use log::info;\n    use pyo3::prelude::*;\n\n    #[pyfunction]\n    fn log_something() {\n        // This will use the logger installed in `my_module` to send the `info`\n        // message to the Python logging facilities.\n        info!(\"Something!\");\n    }\n\n    #[pymodule_init]\n    fn init(m: &Bound<'_, PyModule>) -> PyResult<()> {\n        // A good place to install the Rust -> Python logger.\n        pyo3_log::init();\n    }\n}\n```\n\nThen it is up to the Python side to actually output the messages somewhere.\n\n```python\nimport logging\nimport my_module\n\nFORMAT = '%(levelname)s %(name)s %(asctime)-15s %(filename)s:%(lineno)d %(message)s'\nlogging.basicConfig(format=FORMAT)\nlogging.getLogger().setLevel(logging.INFO)\nmy_module.log_something()\n```\n\nIt is important to initialize the Python loggers first, before calling any Rust functions that may log.\nThis limitation can be worked around if it is not possible to satisfy, read the documentation about [caching].\n\n## The Python to Rust direction\n\nTo have python logs be handled by Rust, one need only register a rust function to handle logs emitted from the core python logging module.\n\nThis has been implemented within the [pyo3-pylogger] crate.\n\n```rust,no_run\nuse log::{info, warn};\nuse pyo3::prelude::*;\n\nfn main() -> PyResult<()> {\n    // register the host handler with python logger, providing a logger target\n    // set the name here to something appropriate for your application\n    pyo3_pylogger::register(\"example_application_py_logger\");\n\n    // initialize up a logger\n    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or(\"trace\")).init();\n\n    // Log some messages from Rust.\n    info!(\"Just some normal information!\");\n    warn!(\"Something spooky happened!\");\n\n    // Log some messages from Python\n    Python::attach(|py| {\n        py.run(\n            \"\nimport logging\nlogging.error('Something bad happened')\n\",\n            None,\n            None,\n        )\n    })\n}\n```\n\n[logging]: https://docs.python.org/3/library/logging.html\n[pyo3-log]: https://crates.io/crates/pyo3-log\n[init]: https://docs.rs/pyo3-log/*/pyo3_log/fn.init.html\n[caching]: https://docs.rs/pyo3-log/*/pyo3_log/#performance-filtering-and-caching\n[pyo3-pylogger]: https://crates.io/crates/pyo3-pylogger\n"
  },
  {
    "path": "guide/src/ecosystem/tracing.md",
    "content": "# Tracing\n\nPython projects that write extension modules for performance reasons may want to tap into [Rust's `tracing` ecosystem] to gain insight into the performance of their extension module.\n\nThis section of the guide describes a few crates that provide ways to do that.\nThey build on [`tracing_subscriber`][tracing-subscriber] and require code changes in both Python and Rust to integrate.\nNote that each extension module must configure its own `tracing` integration; one extension module will not see `tracing` data from a different module.\n\n## `pyo3-tracing-subscriber` ([documentation][pyo3-tracing-subscriber-docs])\n\n[`pyo3-tracing-subscriber`][pyo3-tracing-subscriber] provides a way for Python projects to configure `tracing_subscriber`.\nIt exposes a few `tracing_subscriber` layers:\n\n- `tracing_subscriber::fmt` for writing human-readable output to file or stdout\n- `opentelemetry-stdout` for writing OTLP output to file or stdout\n- `opentelemetry-otlp` for writing OTLP output to an OTLP endpoint\n\nThe extension module must call [`pyo3_tracing_subscriber::add_submodule`][add-submodule] to export the Python classes needed to configure and initialize `tracing`.\n\nOn the Python side, use the `Tracing` context manager to initialize tracing and run Rust code inside the context manager's block. `Tracing` takes a `GlobalTracingConfig` instance describing the layers to be used.\n\nSee [the README on crates.io][pyo3-tracing-subscriber] for example code.\n\n## `pyo3-python-tracing-subscriber` ([documentation][pyo3-python-tracing-subscriber-docs])\n\nThe similarly-named [`pyo3-python-tracing-subscriber`][pyo3-python-tracing-subscriber] implements a shim in Rust that forwards `tracing` data to a `Layer` implementation defined in and passed in from Python.\n\nThere are many ways an extension module could integrate `pyo3-python-tracing-subscriber` but a simple one may look something like this:\n\n```rust,no_run\n#[tracing::instrument]\n#[pyfunction]\nfn fibonacci(index: usize, use_memoized: bool) -> PyResult<usize> {\n    // ...\n}\n\n#[pyfunction]\npub fn initialize_tracing(py_impl: Bound<'_, PyAny>) {\n    tracing_subscriber::registry()\n        .with(pyo3_python_tracing_subscriber::PythonCallbackLayerBridge::new(py_impl))\n        .init();\n}\n```\n\nThe extension module must provide some way for Python to pass in one or more Python objects that implement [the `Layer` interface].\nThen it should construct [`pyo3_python_tracing_subscriber::PythonCallbackLayerBridge`][PythonCallbackLayerBridge] instances with each of those Python objects and initialize `tracing_subscriber` as shown above.\n\nThe Python objects implement a modified version of the `Layer` interface:\n\n- `on_new_span()` may return some state that will stored inside the Rust span\n- other callbacks will be given that state as an additional positional argument\n\nA dummy `Layer` implementation may look like this:\n\n```python\nimport rust_extension\n\nclass MyPythonLayer:\n    def __init__(self):\n        pass\n\n    # `on_new_span` can return some state\n    def on_new_span(self, span_attrs: str, span_id: str) -> int:\n        print(f\"[on_new_span]: {span_attrs} | {span_id}\")\n        return random.randint(1, 1000)\n\n    # The state from `on_new_span` is passed back into other trait methods\n    def on_event(self, event: str, state: int):\n        print(f\"[on_event]: {event} | {state}\")\n\n    def on_close(self, span_id: str, state: int):\n        print(f\"[on_close]: {span_id} | {state}\")\n\n    def on_record(self, span_id: str, values: str, state: int):\n        print(f\"[on_record]: {span_id} | {values} | {state}\")\n\ndef main():\n    rust_extension.initialize_tracing(MyPythonLayer())\n\n    print(\"10th fibonacci number: \", rust_extension.fibonacci(10, True))\n```\n\n`pyo3-python-tracing-subscriber` has [working examples] showing both the Rust side and the Python side of an integration.\n\n[pyo3-tracing-subscriber]: https://crates.io/crates/pyo3-tracing-subscriber\n[pyo3-tracing-subscriber-docs]: https://docs.rs/pyo3-tracing-subscriber\n[add-submodule]: https://docs.rs/pyo3-tracing-subscriber/*/pyo3_tracing_subscriber/fn.add_submodule.html\n\n[pyo3-python-tracing-subscriber]: https://crates.io/crates/pyo3-python-tracing-subscriber\n[pyo3-python-tracing-subscriber-docs]: https://docs.rs/pyo3-python-tracing-subscriber\n[PythonCallbackLayerBridge]: https://docs.rs/pyo3-python-tracing-subscriber/*/pyo3_python_tracing_subscriber/struct.PythonCallbackLayerBridge.html\n[working examples]: https://github.com/getsentry/pyo3-python-tracing-subscriber/tree/main/demo\n\n[Rust's `tracing` ecosystem]: https://crates.io/crates/tracing\n[tracing-subscriber]: https://docs.rs/tracing-subscriber/*/tracing_subscriber/\n[the `Layer` interface]: https://docs.rs/tracing-subscriber/*/tracing_subscriber/layer/trait.Layer.html\n"
  },
  {
    "path": "guide/src/ecosystem.md",
    "content": "# The PyO3 ecosystem\n\nThis portion of the guide is dedicated to crates which are external to the main PyO3 project and provide additional functionality you might find useful.\n\nBecause these projects evolve independently of the PyO3 repository the content of these articles may fall out of date over time; please file issues on the PyO3 GitHub to alert maintainers when this is the case.\n"
  },
  {
    "path": "guide/src/exception.md",
    "content": "# Python exceptions\n\n## Defining a new exception\n\nUse the [`create_exception!`] macro:\n\n```rust\nuse pyo3::create_exception;\n\ncreate_exception!(module, MyError, pyo3::exceptions::PyException);\n```\n\n- `module` is the name of the containing module.\n- `MyError` is the name of the new exception type.\n\nFor example:\n\n```rust\nuse pyo3::prelude::*;\nuse pyo3::create_exception;\nuse pyo3::types::IntoPyDict;\nuse pyo3::exceptions::PyException;\n\ncreate_exception!(mymodule, CustomError, PyException);\n\n# fn main() -> PyResult<()> {\nPython::attach(|py| {\n    let ctx = [(\"CustomError\", py.get_type::<CustomError>())].into_py_dict(py)?;\n    pyo3::py_run!(\n        py,\n        *ctx,\n        \"assert str(CustomError) == \\\"<class 'mymodule.CustomError'>\\\"\"\n    );\n    pyo3::py_run!(py, *ctx, \"assert CustomError('oops').args == ('oops',)\");\n#   Ok(())\n})\n# }\n```\n\nWhen using PyO3 to create an extension module, you can add the new exception to the module like this, so that it is importable from Python:\n\n```rust,no_run\n# fn main() {}\nuse pyo3::prelude::*;\nuse pyo3::exceptions::PyException;\n\npyo3::create_exception!(mymodule, CustomError, PyException);\n\n#[pymodule]\nmod mymodule {\n    #[pymodule_export]\n    use super::CustomError;\n\n    // ... other elements added to module ...\n}\n```\n\n## Raising an exception\n\nAs described in the [function error handling](./function/error-handling.md) chapter, to raise an exception from a `#[pyfunction]` or `#[pymethods]`, return an `Err(PyErr)`.\nPyO3 will automatically raise this exception for you when returning the result to Python.\n\nYou can also manually write and fetch errors in the Python interpreter's global state:\n\n```rust\nuse pyo3::{Python, PyErr};\nuse pyo3::exceptions::PyTypeError;\n\nPython::attach(|py| {\n    PyTypeError::new_err(\"Error\").restore(py);\n    assert!(PyErr::occurred(py));\n    drop(PyErr::fetch(py));\n});\n```\n\n## Checking exception types\n\nPython has an [`isinstance`](https://docs.python.org/3/library/functions.html#isinstance) method to check an object's type.\nIn PyO3 every object has the [`PyAny::is_instance`] and [`PyAny::is_instance_of`] methods which do the same thing.\n\n```rust,no_run\nuse pyo3::prelude::*;\nuse pyo3::types::{PyBool, PyList};\n\n# fn main() -> PyResult<()> {\nPython::attach(|py| {\n    assert!(PyBool::new(py, true).is_instance_of::<PyBool>());\n    let list = PyList::new(py, &[1, 2, 3, 4])?;\n    assert!(!list.is_instance_of::<PyBool>());\n    assert!(list.is_instance_of::<PyList>());\n# Ok(())\n})\n# }\n```\n\nTo check the type of an exception, you can similarly do:\n\n```rust,no_run\n# use pyo3::exceptions::PyTypeError;\n# use pyo3::prelude::*;\n# Python::attach(|py| {\n# let err = PyTypeError::new_err(());\nerr.is_instance_of::<PyTypeError>(py);\n# });\n```\n\n## Using exceptions defined in Python code\n\nIt is possible to use an exception defined in Python code as a native Rust type.\nThe [`import_exception!`] macro allows importing a specific exception class and defines a Rust type for that exception.\n\n```rust,no_run\n#![allow(dead_code)]\nuse pyo3::prelude::*;\n\nmod io {\n    pyo3::import_exception!(io, UnsupportedOperation);\n}\n\nfn tell(file: &Bound<'_, PyAny>) -> PyResult<u64> {\n    match file.call_method0(\"tell\") {\n        Err(_) => Err(io::UnsupportedOperation::new_err(\"not supported: tell\")),\n        Ok(x) => x.extract::<u64>(),\n    }\n}\n```\n\n[`pyo3::exceptions`]({{#PYO3_DOCS_URL}}/pyo3/exceptions/index.html) defines exceptions for several standard library modules.\n\n## Creating more complex exceptions\n\nIf you need to create an exception with more complex behavior, you can also manually create a subclass of `PyException`:\n\n```rust\n#![allow(dead_code)]\n# #[cfg(any(not(Py_LIMITED_API), Py_3_12))] {\nuse pyo3::prelude::*;\nuse pyo3::types::IntoPyDict;\nuse pyo3::exceptions::PyException;\n\n#[pyclass(extends=PyException)]\nstruct CustomError {\n    #[pyo3(get)]\n    url: String,\n\n    #[pyo3(get)]\n    message: String,\n}\n\n#[pymethods]\nimpl CustomError {\n    #[new]\n    fn new(url: String, message: String) -> Self {\n        Self { url, message }\n    }\n}\n\n# fn main() -> PyResult<()> {\nPython::attach(|py| {\n    let ctx = [(\"CustomError\", py.get_type::<CustomError>())].into_py_dict(py)?;\n    pyo3::py_run!(\n        py,\n        *ctx,\n        \"assert str(CustomError) == \\\"<class 'builtins.CustomError'>\\\", repr(CustomError)\"\n    );\n    pyo3::py_run!(py, *ctx, \"assert CustomError('https://example.com', 'something went bad').args == ('https://example.com', 'something went bad')\");\n    pyo3::py_run!(py, *ctx, \"assert CustomError('https://example.com', 'something went bad').url == 'https://example.com'\");\n#   Ok(())\n})\n# }\n# }\n\n```\n\nNote that when the `abi3` feature is enabled, subclassing `PyException` is only possible on Python 3.12 or greater.\n\n[`create_exception!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.create_exception.html\n[`import_exception!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.import_exception.html\n[`PyAny::is_instance`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.is_instance\n[`PyAny::is_instance_of`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.is_instance_of\n"
  },
  {
    "path": "guide/src/faq.md",
    "content": "# Frequently Asked Questions and troubleshooting\n\nSorry that you're having trouble using PyO3.\nIf you can't find the answer to your problem in the list below, you can also reach out for help on [GitHub Discussions](https://github.com/PyO3/pyo3/discussions) and on [Discord](https://discord.gg/33kcChzH7f).\n\n## I'm experiencing deadlocks using PyO3 with `std::sync::OnceLock`, `std::sync::LazyLock`, `lazy_static`, and `once_cell`\n\n`OnceLock`, `LazyLock`, and their thirdparty predecessors use blocking to ensure only one thread ever initializes them.\nBecause the Python interpreter can introduce additional locks (the Python GIL and GC can both require all other threads to pause) this can lead to deadlocks in the following way:\n\n1. A thread (thread A) which is attached to the Python interpreter starts initialization of a `OnceLock` value.\n2. The initialization code calls some Python API which temporarily detaches from the interpreter e.g. `Python::import`.\n3. Another thread (thread B) attaches to the Python interpreter and attempts to access the same `OnceLock` value.\n4. Thread B is blocked, because it waits for `OnceLock`'s initialization to lock to release.\n5. On non-free-threaded Python, thread A is now also blocked, because it waits to re-attach to the interpreter (by taking the GIL which thread B still holds).\n6. Deadlock.\n\nPyO3 provides a struct [`PyOnceLock`] which implements a single-initialization API based on these types that avoids deadlocks.\nYou can also make use of the [`OnceExt`] and [`OnceLockExt`] extension traits that enable using the standard library types for this purpose by providing new methods for these types that avoid the risk of deadlocking with the Python interpreter.\nThis means they can be used in place of other choices when you are experiencing the deadlock described above.\nSee the documentation for [`PyOnceLock`] and [`OnceExt`] for further details and an example how to use them.\n\n[`PyOnceLock`]: {{#PYO3_DOCS_URL}}/pyo3/sync/struct.PyOnceLock.html\n[`OnceExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html\n[`OnceLockExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceLockExt.html\n\n## I can't run `cargo test`; or I can't build in a Cargo workspace: I'm having linker issues like \"Symbol not found\" or \"Undefined reference to _PyExc_SystemError\"\n\nThe `extension-module` feature (now deprecated) disables linking to `libpython`.\nThis breaks binaries and tests which need to load symbols from `libpython` to execute.\n\nRemove the `extension-module` feature and upgrade to `maturin >= 1.9.4` or `setuptools-rust 1.12`.\n\nIf building manually, see the [`PYO3_BUILD_EXTENSION_MODULE` environment variable](./building-and-distribution.md#the-pyo3_build_extension_module-environment-variable).\n\n## I can't run `cargo test`: my crate cannot be found for tests in `tests/` directory\n\nThe Rust book suggests to [put integration tests inside a `tests/` directory](https://doc.rust-lang.org/book/ch11-03-test-organization.html#integration-tests).\n\nFor a PyO3 project where the `crate-type` is set to `\"cdylib\"` in your `Cargo.toml`, the compiler won't be able to find your crate and will display errors such as `E0432` or `E0463`:\n\n```text\nerror[E0432]: unresolved import `my_crate`\n --> tests/test_my_crate.rs:1:5\n  |\n1 | use my_crate;\n  |     ^^^^^^^^^^^^ no external crate `my_crate`\n```\n\nThe best solution is to make your crate types include both `rlib` and `cdylib`:\n\n```toml\n# Cargo.toml\n[lib]\ncrate-type = [\"cdylib\", \"rlib\"]\n```\n\n## Ctrl-C doesn't do anything while my Rust code is executing\n\nThis is because Ctrl-C raises a SIGINT signal, which is handled by the calling Python process by simply setting a flag to action upon later.\nThis flag isn't checked while Rust code called from Python is executing, only once control returns to the Python interpreter.\n\nYou can give the Python interpreter a chance to process the signal properly by calling `Python::check_signals`.\nIt's good practice to call this function regularly if you have a long-running Rust function so that your users can cancel it.\n\n## `#[pyo3(get)]` clones my field\n\nYou may have a nested struct similar to this:\n\n```rust,no_run\n# use pyo3::prelude::*;\n#[pyclass(from_py_object)]\n#[derive(Clone)]\nstruct Inner {/* fields omitted */}\n\n#[pyclass]\nstruct Outer {\n    #[pyo3(get)]\n    inner: Inner,\n}\n\n#[pymethods]\nimpl Outer {\n    #[new]\n    fn __new__() -> Self {\n        Self { inner: Inner {} }\n    }\n}\n```\n\nWhen Python code accesses `Outer`'s field, PyO3 will return a new object on every access (note that their addresses are different):\n\n```python\nouter = Outer()\n\na = outer.inner\nb = outer.inner\n\nassert a is b, f\"a: {a}\\nb: {b}\"\n```\n\n```text\nAssertionError: a: <builtins.Inner object at 0x00000238FFB9C7B0>\nb: <builtins.Inner object at 0x00000238FFB9C830>\n```\n\nThis can be especially confusing if the field is mutable, as getting the field and then mutating it won't persist - you'll just get a fresh clone of the original on the next access.\nUnfortunately Python and Rust don't agree about ownership - if PyO3 gave out references to (possibly) temporary Rust objects to Python code, Python code could then keep that reference alive indefinitely.\nTherefore returning Rust objects requires cloning.\n\nIf you don't want that cloning to happen, a workaround is to allocate the field on the Python heap and store a reference to that, by using [`Py<...>`]({{#PYO3_DOCS_URL}}/pyo3/struct.Py.html):\n\n```rust,no_run\n# use pyo3::prelude::*;\n#[pyclass]\nstruct Inner {/* fields omitted */}\n\n#[pyclass]\nstruct Outer {\n    inner: Py<Inner>,\n}\n\n#[pymethods]\nimpl Outer {\n    #[new]\n    fn __new__(py: Python<'_>) -> PyResult<Self> {\n        Ok(Self {\n            inner: Py::new(py, Inner {})?,\n        })\n    }\n\n    #[getter]\n    fn inner(&self, py: Python<'_>) -> Py<Inner> {\n        self.inner.clone_ref(py)\n    }\n}\n```\n\nThis time `a` and `b` *are* the same object:\n\n```python\nouter = Outer()\n\na = outer.inner\nb = outer.inner\n\nassert a is b, f\"a: {a}\\nb: {b}\"\nprint(f\"a: {a}\\nb: {b}\")\n```\n\n```text\na: <builtins.Inner object at 0x0000020044FCC670>\nb: <builtins.Inner object at 0x0000020044FCC670>\n```\n\nThe downside to this approach is that any Rust code working on the `Outer` struct potentially has to attach to the Python interpreter to do anything with the `inner` field. (If `Inner` is `#[pyclass(frozen)]` and implements `Sync`, then `Py::get` may be used to access the `Inner` contents from `Py<Inner>` without needing to attach to the interpreter.)\n\n## I want to use the `pyo3` crate re-exported from dependency but the proc-macros fail\n\nAll PyO3 proc-macros (`#[pyclass]`, `#[pyfunction]`, `#[derive(FromPyObject)]` and so on) expect the `pyo3` crate to be available under that name in your crate root, which is the normal situation when `pyo3` is a direct dependency of your crate.\n\nHowever, when the dependency is renamed, or your crate only indirectly depends on `pyo3`, you need to let the macro code know where to find the crate.\nThis is done with the `crate` attribute:\n\n```rust,no_run\n# use pyo3::prelude::*;\n# pub extern crate pyo3;\n# mod reexported { pub use ::pyo3; }\n# #[allow(dead_code)]\n#[pyclass]\n#[pyo3(crate = \"reexported::pyo3\")]\nstruct MyClass;\n```\n\n## I'm trying to call Python from Rust but I get `STATUS_DLL_NOT_FOUND` or `STATUS_ENTRYPOINT_NOT_FOUND`\n\nThis happens on Windows when linking to the python DLL fails or the wrong one is linked.\nThe Python DLL on Windows will usually be called something like:\n\n- `python3X.dll` for Python 3.X, e.g. `python310.dll` for Python 3.10\n- `python3.dll` when using PyO3's `abi3` feature\n\nThe DLL needs to be locatable using the [Windows DLL search order](https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order#standard-search-order-for-unpackaged-apps).\nSome ways to achieve this are:\n\n- Put the Python DLL in the same folder as your build artifacts\n- Add the directory containing the Python DLL to your `PATH` environment variable, for example `C:\\Users\\<You>\\AppData\\Local\\Programs\\Python\\Python310`\n- If this happens when you are *distributing* your program, consider using [PyOxidizer](https://github.com/indygreg/PyOxidizer) to package it with your binary.\n\nIf the wrong DLL is linked it is possible that this happened because another program added itself and its own Python DLLs to `PATH`.\nRearrange your `PATH` variables to give the correct DLL priority.\n\n> [!NOTE]\n> Changes to `PATH` (or any other environment variable) are not visible to existing shells. Restart it for changes to take effect.\n\nFor advanced troubleshooting, [Dependency Walker](https://www.dependencywalker.com/) can be used to diagnose linking errors.\n"
  },
  {
    "path": "guide/src/features.md",
    "content": "# Features reference\n\nPyO3 provides a number of Cargo features to customize functionality.\nThis chapter of the guide provides detail on each of them.\n\nBy default, only the `macros` feature is enabled.\n\n## Features for extension module authors\n\n### `extension-module`\n\nDeprecated, users should remove this feature and upgrade to `maturin >= 1.9.4` or `setuptools-rust >= 1.12`.\n\nSee the [building and distribution](building-and-distribution.md#the-extension-module-feature) section for further detail.\n\n### `abi3`\n\nThis feature is used when building Python extension modules to create wheels which are compatible with multiple Python versions.\n\nIt restricts PyO3's API to a subset of the full Python API which is guaranteed by [PEP 384](https://www.python.org/dev/peps/pep-0384/) to be forwards-compatible with future Python versions.\n\nSee the [building and distribution](building-and-distribution.md#py_limited_apiabi3) section for further detail.\n\n### The `abi3-pyXY` features\n\n(`abi3-py37`, `abi3-py38`, `abi3-py39`, `abi3-py310`, `abi3-py311`, `abi3-py312`, `abi3-py313` and `abi3-py314`)\n\nThese features are extensions of the `abi3` feature to specify the exact minimum Python version which the multiple-version-wheel will support.\n\nSee the [building and distribution](building-and-distribution.md#minimum-python-version-for-abi3) section for further detail.\n\n### `generate-import-lib`\n\nThis feature is deprecated and has no effect.\nPyO3 now uses Rust's `raw-dylib` linking feature to link against the Python DLL on Windows, eliminating the need for import library (`.lib`) files entirely.\nCross-compiling for Windows targets works without any additional setup.\n\n## Features for embedding Python in Rust\n\n### `auto-initialize`\n\nThis feature changes [`Python::attach`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.attach) to automatically initialize a Python interpreter (by calling [`Python::initialize`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.initialize)) if needed.\n\nIf you do not enable this feature, you should call `Python::initialize()` before attempting to call any other Python APIs.\n\n## Advanced Features\n\n### `experimental-async`\n\nThis feature adds support for `async fn` in `#[pyfunction]` and `#[pymethods]`.\n\nThe feature has some unfinished refinements and performance improvements.\nTo help finish this off, see [issue #1632](https://github.com/PyO3/pyo3/issues/1632) and its associated draft PRs.\n\n### `experimental-inspect`\n\nThis feature adds to the built binaries introspection data that can be then retrieved using the `pyo3-introspection` crate to generate [type stubs](https://typing.readthedocs.io/en/latest/source/stubs.html).\n\nAlso, this feature adds the `pyo3::inspect` module, as well as `IntoPy::type_output` and `FromPyObject::type_input` APIs to produce Python type \"annotations\" for Rust types.\n\nThis is a first step towards adding first-class support for generating type annotations automatically in PyO3, however work is needed to finish this off.\nAll feedback and offers of help welcome on [issue #2454](https://github.com/PyO3/pyo3/issues/2454).\n\n### `py-clone`\n\nThis feature was introduced to ease migration.\nIt was found that delayed reference counting (which PyO3 used historically) could not be made sound and hence `Clone`-ing an instance of `Py<T>` is impossible when not attached to Python interpreter (it will panic).\nTo avoid migrations introducing new panics without warning, the `Clone` implementation itself is now gated behind this feature.\n\n### `pyo3_disable_reference_pool`\n\nThis is a performance-oriented conditional compilation flag, e.g. [set via `$RUSTFLAGS`][set-configuration-options], which disabled the global reference pool and the associated overhead for the crossing the Python-Rust boundary.\nHowever, if enabled, `Drop`ping an instance of `Py<T>` when not attached to the Python interpreter will abort the process.\n\n### `macros`\n\nThis feature enables a dependency on the `pyo3-macros` crate, which provides the procedural macros portion of PyO3's API:\n\n- `#[pymodule]`\n- `#[pyfunction]`\n- `#[pyclass]`\n- `#[pymethods]`\n- `#[derive(FromPyObject)]`\n\nIt also provides the `py_run!` macro.\n\nThese macros require a number of dependencies which may not be needed by users who just need PyO3 for Python FFI.\nDisabling this feature enables faster builds for those users, as these dependencies will not be built if this feature is disabled.\n\n> [!NOTE]\n> This feature is enabled by default. To disable it, set `default-features = false` for the `pyo3` entry in your Cargo.toml.\n\n### `multiple-pymethods`\n\nThis feature enables each `#[pyclass]` to have more than one `#[pymethods]` block.\n\nMost users should only need a single `#[pymethods]` per `#[pyclass]`.\nIn addition, not all platforms (e.g. Wasm) are supported by `inventory`, which is used in the implementation of the feature.\nFor this reason this feature is not enabled by default, meaning fewer dependencies and faster compilation for the majority of users.\n\nSee [the `#[pyclass]` implementation details](class.md#implementation-details) for more information.\n\n### `nightly`\n\nThe `nightly` feature needs the nightly Rust compiler.\nThis allows PyO3 to use the `auto_traits` and `negative_impls` features to fix the `Python::detach` function.\n\n### `resolve-config`\n\nThe `resolve-config` feature of the `pyo3-build-config` crate controls whether that crate's build script automatically resolves a Python interpreter / build configuration.\nThis feature is primarily useful when building PyO3 itself.\nBy default this feature is not enabled, meaning you can freely use `pyo3-build-config` as a standalone library to read or write PyO3 build configuration files or resolve metadata about a Python interpreter.\n\n## Optional Dependencies\n\nThese features enable conversions between Python types and types from other Rust crates, enabling easy access to the rest of the Rust ecosystem.\n\n### `anyhow`\n\nAdds a dependency on [anyhow](https://docs.rs/anyhow).\nEnables a conversion from [anyhow](https://docs.rs/anyhow)’s [`Error`](https://docs.rs/anyhow/latest/anyhow/struct.Error.html) type to [`PyErr`]({{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html), for easy error handling.\n\n### `arc_lock`\n\nEnables Pyo3's `MutexExt` trait for all Mutexes that extend on [`lock_api::Mutex`](https://docs.rs/lock_api/latest/lock_api/struct.Mutex.html) or [`parking_lot::ReentrantMutex`](https://docs.rs/lock_api/latest/lock_api/struct.ReentrantMutex.html) and are wrapped in an [`Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) type.\nLike [`Arc<parking_lot::Mutex>`](https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html#method.lock_arc)\n\n### `bigdecimal`\n\nAdds a dependency on [bigdecimal](https://docs.rs/bigdecimal) and enables conversions into its [`BigDecimal`](https://docs.rs/bigdecimal/latest/bigdecimal/struct.BigDecimal.html) type.\n\n### `bytes`\n\nAdds a dependency on [bytes](https://docs.rs/bytes/latest/bytes) and enables conversions into its [`Bytes`](https://docs.rs/bytes/latest/bytes/struct.Bytes.html) type.\n\n### `chrono`\n\nAdds a dependency on [chrono](https://docs.rs/chrono).\nEnables a conversion from [chrono](https://docs.rs/chrono)'s types to python:\n\n- [TimeDelta](https://docs.rs/chrono/latest/chrono/struct.TimeDelta.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html)\n- [FixedOffset](https://docs.rs/chrono/latest/chrono/offset/struct.FixedOffset.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html)\n- [Utc](https://docs.rs/chrono/latest/chrono/offset/struct.Utc.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html)\n- [NaiveDate](https://docs.rs/chrono/latest/chrono/naive/struct.NaiveDate.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html)\n- [NaiveTime](https://docs.rs/chrono/latest/chrono/naive/struct.NaiveTime.html) -> [`PyTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTime.html)\n- [DateTime](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html)\n\n### `chrono-local`\n\nEnables conversion from and to [Local](https://docs.rs/chrono/latest/chrono/struct.Local.html) timezones.\nThe current system timezone as determined by [`iana_time_zone::get_timezone()`](https://docs.rs/iana-time-zone/latest/iana_time_zone/fn.get_timezone.html) will be used for conversions.\n\n`chrono::DateTime<Local>` will convert from either of:\n\n- `datetime` objects with `tzinfo` equivalent to the current system timezone.\n- \"naive\" `datetime` objects (those without a `tzinfo`), as it is a convention that naive datetime objects should be treated as using the system timezone.\n\nWhen converting to Python, `Local` tzinfo is converted to a `zoneinfo.ZoneInfo` matching the current system timezone.\n\n### `chrono-tz`\n\nAdds a dependency on [chrono-tz](https://docs.rs/chrono-tz).\nEnables conversion from and to [`Tz`](https://docs.rs/chrono-tz/latest/chrono_tz/enum.Tz.html).\n\n### `either`\n\nAdds a dependency on [either](https://docs.rs/either).\nEnables a conversions into [either](https://docs.rs/either)’s [`Either`](https://docs.rs/either/latest/either/enum.Either.html) type.\n\n### `eyre`\n\nAdds a dependency on [eyre](https://docs.rs/eyre).\nEnables a conversion from [eyre](https://docs.rs/eyre)’s [`Report`](https://docs.rs/eyre/latest/eyre/struct.Report.html) type to [`PyErr`]({{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html), for easy error handling.\n\n### `hashbrown`\n\nAdds a dependency on [hashbrown](https://docs.rs/hashbrown) and enables conversions into its [`HashMap`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html) and [`HashSet`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html) types.\n\n### `indexmap`\n\nAdds a dependency on [indexmap](https://docs.rs/indexmap) and enables conversions into its [`IndexMap`](https://docs.rs/indexmap/latest/indexmap/map/struct.IndexMap.html) type.\n\n### `jiff-02`\n\nAdds a dependency on [jiff@0.2](https://docs.rs/jiff/0.2).\nEnables a conversion from [jiff](https://docs.rs/jiff)'s types to python:\n\n- [SignedDuration](https://docs.rs/jiff/0.2/jiff/struct.SignedDuration.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html)\n- [TimeZone](https://docs.rs/jiff/0.2/jiff/tz/struct.TimeZone.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html)\n- [Offset](https://docs.rs/jiff/0.2/jiff/tz/struct.Offset.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html)\n- [Date](https://docs.rs/jiff/0.2/jiff/civil/struct.Date.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html)\n- [Time](https://docs.rs/jiff/0.2/jiff/civil/struct.Time.html) -> [`PyTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTime.html)\n- [DateTime](https://docs.rs/jiff/0.2/jiff/civil/struct.DateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html)\n- [Zoned](https://docs.rs/jiff/0.2/jiff/struct.Zoned.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html)\n- [Timestamp](https://docs.rs/jiff/0.2/jiff/struct.Timestamp.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html)\n- [ISOWeekDate](https://docs.rs/jiff/0.2/jiff/civil/struct.ISOWeekDate.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html)\n\n### `lock_api`\n\nAdds a dependency on [lock_api](https://docs.rs/lock_api) and enables Pyo3's `MutexExt` trait for all mutexes that extend on [`lock_api::Mutex`](https://docs.rs/lock_api/latest/lock_api/struct.Mutex.html) and [`parking_lot::ReentrantMutex`](https://docs.rs/lock_api/latest/lock_api/struct.ReentrantMutex.html) (like `parking_lot` or `spin`).\n\n### `num-bigint`\n\nAdds a dependency on [num-bigint](https://docs.rs/num-bigint) and enables conversions into its [`BigInt`](https://docs.rs/num-bigint/latest/num_bigint/struct.BigInt.html) and [`BigUint`](https://docs.rs/num-bigint/latest/num_bigint/struct.BigUint.html) types.\n\n### `num-complex`\n\nAdds a dependency on [num-complex](https://docs.rs/num-complex) and enables conversions into its [`Complex`](https://docs.rs/num-complex/latest/num_complex/struct.Complex.html) type.\n\n### `num-rational`\n\nAdds a dependency on [num-rational](https://docs.rs/num-rational) and enables conversions into its [`Ratio`](https://docs.rs/num-rational/latest/num_rational/struct.Ratio.html) type.\n\n### `ordered-float`\n\nAdds a dependency on [ordered-float](https://docs.rs/ordered-float) and enables conversions between [ordered-float](https://docs.rs/ordered-float)'s types and Python:\n\n- [NotNan](https://docs.rs/ordered-float/latest/ordered_float/struct.NotNan.html) -> [`PyFloat`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyFloat.html)\n- [OrderedFloat](https://docs.rs/ordered-float/latest/ordered_float/struct.OrderedFloat.html) -> [`PyFloat`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyFloat.html)\n\n### `parking-lot`\n\nAdds a dependency on [parking_lot](https://docs.rs/parking_lot) and enables Pyo3's `OnceExt` & `MutexExt` traits for [`parking_lot::Once`](https://docs.rs/parking_lot/latest/parking_lot/struct.Once.html) [`parking_lot::Mutex`](https://docs.rs/parking_lot/latest/parking_lot/type.Mutex.html) and [`parking_lot::ReentrantMutex`](https://docs.rs/parking_lot/latest/parking_lot/type.ReentrantMutex.html) types.\n\n### `rust_decimal`\n\nAdds a dependency on [rust_decimal](https://docs.rs/rust_decimal) and enables conversions into its [`Decimal`](https://docs.rs/rust_decimal/latest/rust_decimal/struct.Decimal.html) type.\n\n### `time`\n\nAdds a dependency on [time](https://docs.rs/time).\nEnables conversions between [time](https://docs.rs/time)'s types and Python:\n\n- [Date](https://docs.rs/time/0.3.38/time/struct.Date.html) -> [`PyDate`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDate.html)\n- [Time](https://docs.rs/time/0.3.38/time/struct.Time.html) -> [`PyTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTime.html)\n- [OffsetDateTime](https://docs.rs/time/0.3.38/time/struct.OffsetDateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html)\n- [PrimitiveDateTime](https://docs.rs/time/0.3.38/time/struct.PrimitiveDateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html)\n- [Duration](https://docs.rs/time/0.3.38/time/struct.Duration.html) -> [`PyDelta`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDelta.html)\n- [UtcOffset](https://docs.rs/time/0.3.38/time/struct.UtcOffset.html) -> [`PyTzInfo`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyTzInfo.html)\n- [UtcDateTime](https://docs.rs/time/0.3.38/time/struct.UtcDateTime.html) -> [`PyDateTime`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyDateTime.html)\n\n### `serde`\n\nEnables (de)serialization of `Py<T>` objects via [serde](https://serde.rs/).\nThis allows to use [`#[derive(Serialize, Deserialize)`](https://serde.rs/derive.html) on structs that hold references to `#[pyclass]` instances\n\n```rust,no_run\n# #[cfg(feature = \"serde\")]\n# #[allow(dead_code)]\n# mod serde_only {\n# use pyo3::prelude::*;\n# use serde::{Deserialize, Serialize};\n\n#[pyclass]\n#[derive(Serialize, Deserialize)]\nstruct Permission {\n    name: String,\n}\n\n#[pyclass]\n#[derive(Serialize, Deserialize)]\nstruct User {\n    username: String,\n    permissions: Vec<Py<Permission>>,\n}\n# }\n```\n\n### `smallvec`\n\nAdds a dependency on [smallvec](https://docs.rs/smallvec) and enables conversions into its [`SmallVec`](https://docs.rs/smallvec/latest/smallvec/struct.SmallVec.html) type.\n\n[set-configuration-options]: https://doc.rust-lang.org/reference/conditional-compilation.html#set-configuration-options\n\n### `uuid`\n\nAdds a dependency on [uuid](https://docs.rs/uuid) and enables conversions into its [`Uuid`](https://docs.rs/uuid/latest/uuid/struct.Uuid.html) type.\n"
  },
  {
    "path": "guide/src/free-threading.md",
    "content": "# Supporting Free-Threaded CPython\n\nCPython 3.14 declared support for the \"free-threaded\" build of CPython that does not rely on the [global interpreter lock](https://docs.python.org/3/glossary.html#term-global-interpreter-lock) (often referred to as the GIL) for thread safety.\nSince version 0.23, PyO3 supports building Rust extensions for the free-threaded Python build and calling into free-threaded Python from Rust.\n\nIf you want more background on free-threaded Python in general, see the [what's new](https://docs.python.org/3/whatsnew/3.13.html#whatsnew313-free-threaded-cpython) entry in the 3.13 release notes (when the \"free-threaded\" build was first added as an experimental mode), the [free-threading HOWTO guide](https://docs.python.org/3/howto/free-threading-extensions.html#freethreading-extensions-howto) in the CPython docs, the [extension porting guide](https://py-free-threading.github.io/porting-extensions/) in the community-maintained Python free-threading guide, and [PEP 703](https://peps.python.org/pep-0703/), which provides the technical background for the free-threading implementation in CPython.\n\nIn the GIL-enabled build (the only choice before the \"free-threaded\" build was introduced), the global interpreter lock serializes access to the Python runtime.\nThe GIL is therefore a fundamental limitation to parallel scaling of multithreaded Python workflows, due to [Amdahl's law](https://en.wikipedia.org/wiki/Amdahl%27s_law), because any time spent executing a parallel processing task on only one execution context fundamentally cannot be sped up using parallelism.\n\nThe free-threaded build removes this limit on multithreaded Python scaling.\nThis means it's much more straightforward to achieve parallelism using the Python [`threading`] module.\nIf you have ever needed to use [`multiprocessing`](https://docs.python.org/3/library/multiprocessing.html) to achieve a parallel speedup for some Python code, free-threading will likely allow the use of Python threads instead for the same workflow.\n\nPyO3's support for free-threaded Python will enable authoring native Python extensions that are thread-safe by construction, with much stronger safety guarantees than C extensions.\nOur goal is to enable [\"fearless concurrency\"](https://doc.rust-lang.org/book/ch16-00-concurrency.html) in the native Python runtime by building on the Rust [`Send` and `Sync`](https://doc.rust-lang.org/nomicon/send-and-sync.html) traits.\n\nThis document provides advice for porting Rust code using PyO3 to run under free-threaded Python.\n\n## Supporting free-threaded Python with PyO3\n\nSince PyO3 0.28, PyO3 defaults to assuming Python modules created with it are thread-safe.\nThis will be the case except for Rust code which has used `unsafe` to assume thread-safety incorrectly.\nAn example of this is `unsafe` code which was written with the historical assumption that Python was single-threaded due to the GIL, and so the `Python<'py>` token used by PyO3 could be used to guarantee thread-safety.\nA module can opt-out of supporting free-threaded Python until it has audited its `unsafe` code for correctness by declaring the module with `#[pymodule(gil_used = true)]` (see below).\n\nComplicated `#[pyclass]` types may need to deal with thread-safety directly; there is [a dedicated section of the guide](./class/thread-safety.md) to discuss this.\n\nAt a low-level, annotating a module sets the `Py_MOD_GIL` slot on modules defined by an extension to `Py_MOD_GIL_NOT_USED`, which allows the interpreter to see at runtime that the author of the extension thinks the extension is thread-safe.\n\nBy opting-out of supporting free-threaded Python, the Python interpreter will re-enable the GIL at runtime while importing your module and print a `RuntimeWarning` with a message containing the name of the module causing it to re-enable the GIL.\nYou can force the GIL to remain disabled by setting the `PYTHON_GIL=0` as an environment variable or passing `-Xgil=0` when starting Python (`0` means the GIL is turned off).\n\nIf you are sure that all data structures exposed in a `PyModule` are thread-safe, then pass `gil_used = false` as a parameter to the `pymodule` procedural macro declaring the module or call `PyModule::gil_used` on a `PyModule` instance.\nFor example:\n\n### Example opting-in\n\n(Note: for PyO3 versions 0.23 through 0.27, the default was `gil_used = true` and so the opposite was needed; modules needed to opt-in to free-threaded Python support with `gil_used = false`.)\n\n```rust,no_run\n/// This module relies on the GIL for thread safety\n#[pyo3::pymodule(gil_used = true)]\nmod my_extension {\n    use pyo3::prelude::*;\n\n    // this type is not thread-safe\n    #[pyclass]\n    struct MyNotThreadSafeType {\n        // insert not thread-safe code\n    }\n}\n```\n\nOr for a module that is set up without using the `pymodule` macro:\n\n```rust,no_run\nuse pyo3::prelude::*;\n\n# #[allow(dead_code)]\nfn register_child_module(parent_module: &Bound<'_, PyModule>) -> PyResult<()> {\n    let child_module = PyModule::new(parent_module.py(), \"child_module\")?;\n    child_module.gil_used(true)?;\n    parent_module.add_submodule(&child_module)\n}\n\n```\n\nSee the [`string-sum`](https://github.com/PyO3/pyo3/tree/main/pyo3-ffi/examples/string-sum) example for how to declare free-threaded support using raw FFI calls for modules using single-phase initialization and the [`sequential`](https://github.com/PyO3/pyo3/tree/main/pyo3-ffi/examples/sequential) example for modules using multi-phase initialization.\n\nIf you would like to use conditional compilation to trigger different code paths under the free-threaded build, you can use the `Py_GIL_DISABLED` attribute once you have configured your crate to generate the necessary build configuration data.\nSee [the guide section](./building-and-distribution/multiple-python-versions.md) for more details about supporting multiple different Python versions, including the free-threaded build.\n\n## Special considerations for the free-threaded build\n\nThe free-threaded interpreter does not have a GIL.\nMany existing extensions providing mutable data structures relied on the GIL to lock Python objects and make interior mutability thread-safe.\n\nCalling into the CPython C API is only legal when an OS thread is explicitly attached to the interpreter runtime.\nIn the GIL-enabled build, this happens when the GIL is acquired.\nIn the free-threaded build there is no GIL, but the same C macros that release or acquire the GIL in the GIL-enabled build instead ask the interpreter to attach the thread to the Python runtime, and there can be many threads simultaneously attached.\nSee [PEP 703](https://peps.python.org/pep-0703/#thread-states) for more background about how threads can be attached and detached from the interpreter runtime, in a manner analogous to releasing and acquiring the GIL in the GIL-enabled build.\n\nIn the GIL-enabled build, PyO3 uses the [`Python<'py>`] type and the `'py` lifetime to signify that the global interpreter lock is held.\nIn the freethreaded build, holding a `'py` lifetime means only that the thread is currently attached to the Python interpreter -- other threads can be simultaneously interacting with the interpreter.\n\n### Attaching to the runtime\n\nYou still need to obtain a `'py` lifetime to interact with Python objects or call into the CPython C API.\nIf you are not yet attached to the Python runtime, you can register a thread using the [`Python::attach`] function.\nThreads created via the Python [`threading`] module do not need to do this, and pyo3 will handle setting up the [`Python<'py>`] token when CPython calls into your extension.\n\n### Detaching to avoid hangs and deadlocks\n\nThe free-threaded build triggers global synchronization events in the following situations:\n\n- During garbage collection in order to get a globally consistent view of\n  reference counts and references between objects\n- In Python 3.13, when the first background thread is started in\n  order to mark certain objects as immortal\n- When either `sys.settrace` or `sys.setprofile` are called in order to\n  instrument running code objects and threads\n- During a call to `os.fork()`, to ensure a process-wide consistent state.\n\nThis is a non-exhaustive list and there may be other situations in future Python versions that can trigger global synchronization events.\n\nThis means that you should detach from the interpreter runtime using [`Python::detach`] in exactly the same situations as you should detach from the runtime in the GIL-enabled build: when doing long-running tasks that do not require the CPython runtime or when doing any task that needs to re-attach to the runtime (see the [guide section](parallelism.md#sharing-python-objects-between-rust-threads) that covers this).\nIn the former case, you would observe a hang on threads that are waiting on the long-running task to complete, and in the latter case you would see a deadlock while a thread tries to attach after the runtime triggers a global synchronization event, but the spawning thread prevents the synchronization event from completing.\n\n### Exceptions and panics for multithreaded access of mutable `pyclass` instances\n\nData attached to `pyclass` instances is protected from concurrent access by a `RefCell`-like pattern of runtime borrow checking.\nLike a `RefCell`, PyO3 will raise exceptions (or in some cases panic) to enforce exclusive access for mutable borrows.\nIt was always possible to generate panics like this in PyO3 in code that releases the GIL with [`Python::detach`] or calling a python method accepting `&self` from a `&mut self` (see [the docs on interior mutability](./class.md#bound-and-interior-mutability),) but now in free-threaded Python there are more opportunities to trigger these panics from Python because there is no GIL to lock concurrent access to mutably borrowed data from Python.\n\nThe most straightforward way to trigger this problem is to use the Python [`threading`] module to simultaneously call a rust function that mutably borrows a [`pyclass`]({{#PYO3_DOCS_URL}}/pyo3/attr.pyclass.html) in multiple threads.\nFor example, consider the following implementation:\n\n```rust,no_run\n# use pyo3::prelude::*;\n#[pyclass]\n#[derive(Default)]\nstruct ThreadIter {\n    count: usize,\n}\n\n#[pymethods]\nimpl ThreadIter {\n    #[new]\n    pub fn new() -> Self {\n        Default::default()\n    }\n\n    fn __next__(&mut self, py: Python<'_>) -> usize {\n        self.count += 1;\n        self.count\n    }\n}\n```\n\nAnd then if we do something like this in Python:\n\n```python\nimport concurrent.futures\nfrom my_module import ThreadIter\n\ni = ThreadIter()\n\ndef increment():\n    next(i)\n\nwith concurrent.futures.ThreadPoolExecutor(max_workers=16) as tpe:\n    futures = [tpe.submit(increment) for _ in range(100)]\n    [f.result() for f in futures]\n```\n\nWe will see an exception:\n\n```text\nTraceback (most recent call last)\n  File \"example.py\", line 5, in <module>\n    next(i)\nRuntimeError: Already borrowed\n```\n\nWe may allow user-selectable semantics for mutable pyclass definitions in a future version of PyO3, allowing some form of opt-in locking to emulate the GIL if that is needed.\nFor now you should explicitly add locking, possibly using conditional compilation or using the critical section API, to avoid creating deadlocks with the GIL.\n\n### Cannot build extensions using the limited API\n\nThe free-threaded build uses a completely new ABI and there is not yet an equivalent to the limited API for the free-threaded ABI.\nThat means if your crate depends on PyO3 using the `abi3` feature or an an `abi3-pyxx` feature, PyO3 will print a warning and ignore that setting when building extensions using the free-threaded interpreter.\n\nThis means that if your package makes use of the ABI forward compatibility provided by the limited API to upload only one wheel for each release of your package, you will need to update your release procedure to also upload a version-specific free-threaded wheel.\n\nSee [the guide section](./building-and-distribution/multiple-python-versions.md) for more details about supporting multiple different Python versions, including the free-threaded build.\n\n### Thread-safe single initialization\n\nTo initialize data exactly once, use the [`PyOnceLock`] type, which is a close equivalent to [`std::sync::OnceLock`][`OnceLock`] that also helps avoid deadlocks by detaching from the Python interpreter when threads are blocking waiting for another thread to complete initialization.\nIf already using [`OnceLock`] and it is impractical to replace with a [`PyOnceLock`], there is the [`OnceLockExt`] extension trait which adds [`OnceLockExt::get_or_init_py_attached`] to detach from the interpreter when blocking in the same fashion as [`PyOnceLock`].\nHere is an example using [`PyOnceLock`] to single-initialize a runtime cache holding a `Py<PyDict>`:\n\n```rust\n# use pyo3::prelude::*;\nuse pyo3::sync::PyOnceLock;\nuse pyo3::types::PyDict;\n\nlet cache: PyOnceLock<Py<PyDict>> = PyOnceLock::new();\n\nPython::attach(|py| {\n    // guaranteed to be called once and only once\n    cache.get_or_init(py, || PyDict::new(py).unbind())\n});\n```\n\nIn cases where a function must run exactly once, you can bring the [`OnceExt`] trait into scope.\nThe [`OnceExt`] trait adds [`OnceExt::call_once_py_attached`] and [`OnceExt::call_once_force_py_attached`] functions to the api of `std::sync::Once`, enabling use of [`Once`] in contexts where the thread is attached to the Python interpreter.\nThese functions are analogous to [`Once::call_once`], [`Once::call_once_force`] except they accept a [`Python<'py>`] token in addition to an `FnOnce`.\nAll of these functions detach from the interpreter before blocking and re-attach before executing the function, avoiding deadlocks that are possible without using the PyO3 extension traits.\nHere the same example as above built using a [`Once`] instead of a\n[`PyOnceLock`]:\n\n```rust\n# use pyo3::prelude::*;\nuse std::sync::Once;\nuse pyo3::sync::OnceExt;\nuse pyo3::types::PyDict;\n\nstruct RuntimeCache {\n    once: Once,\n    cache: Option<Py<PyDict>>\n}\n\nlet mut cache = RuntimeCache {\n    once: Once::new(),\n    cache: None\n};\n\nPython::attach(|py| {\n    // guaranteed to be called once and only once\n    cache.once.call_once_py_attached(py, || {\n        cache.cache = Some(PyDict::new(py).unbind());\n    });\n});\n```\n\n### `GILProtected` has been removed\n\n[`GILProtected`] was a PyO3 type that allowed mutable access to static data by leveraging the GIL to lock concurrent access from other threads.\nIn free-threaded Python there is no GIL, so this type had to be replaced with alternative forms of locking.\nIn many cases, a type from [`std::sync::atomic`](https://doc.rust-lang.org/std/sync/atomic/) or a [`std::sync::Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) was sufficient.\n\nBefore:\n\n```rust,ignore\n# fn main() {\n# #[cfg(not(Py_GIL_DISABLED))] {\n# use pyo3::prelude::*;\nuse pyo3::sync::GILProtected;\nuse pyo3::types::{PyDict, PyNone};\nuse std::cell::RefCell;\n\nstatic OBJECTS: GILProtected<RefCell<Vec<Py<PyDict>>>> =\n    GILProtected::new(RefCell::new(Vec::new()));\n\nPython::attach(|py| {\n    // stand-in for something that executes arbitrary Python code\n    let d = PyDict::new(py);\n    d.set_item(PyNone::get(py), PyNone::get(py)).unwrap();\n    OBJECTS.get(py).borrow_mut().push(d.unbind());\n});\n# }}\n```\n\nAfter (using a `Mutex`):\n\n```rust\n# use pyo3::prelude::*;\n# fn main() {\nuse pyo3::types::{PyDict, PyNone};\nuse std::sync::Mutex;\n\nstatic OBJECTS: Mutex<Vec<Py<PyDict>>> = Mutex::new(Vec::new());\n\nPython::attach(|py| {\n    // stand-in for something that executes arbitrary Python code\n    let d = PyDict::new(py);\n    d.set_item(PyNone::get(py), PyNone::get(py)).unwrap();\n    // as with any `Mutex` usage, lock the mutex for as little time as possible\n    // in this case, we do it just while pushing into the `Vec`\n    OBJECTS.lock().unwrap().push(d.unbind());\n});\n# }\n```\n\nIf you are executing arbitrary Python code while holding the lock, then you should import the [`MutexExt`] trait and use the `lock_py_attached` method instead of `lock`.\nThis ensures that global synchronization events started by the Python runtime can proceed, avoiding possible deadlocks with the interpreter.\n\n[`GILProtected`]: https://docs.rs/pyo3/0.22/pyo3/sync/struct.GILProtected.html\n[`MutexExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.MutexExt.html\n[`Once`]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html\n[`Once::call_once`]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.call_once\n[`Once::call_once_force`]: https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.call_once_force\n[`OnceExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html\n[`OnceExt::call_once_py_attached`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html#tymethod.call_once_py_attached\n[`OnceExt::call_once_force_py_attached`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceExt.html#tymethod.call_once_force_py_attached\n[`OnceLockExt`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceLockExt.html\n[`OnceLockExt::get_or_init_py_attached`]: {{#PYO3_DOCS_URL}}/pyo3/sync/trait.OnceLockExt.html#tymethod.get_or_init_py_attached\n[`OnceLock`]: https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html\n[`Python::detach`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.detach\n[`Python::attach`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.attach\n[`Python<'py>`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html\n[`PyOnceLock`]: {{#PYO3_DOCS_URL}}/pyo3/sync/struct.PyOnceLock.html\n[`threading`]: https://docs.python.org/3/library/threading.html\n"
  },
  {
    "path": "guide/src/function/error-handling.md",
    "content": "# Error handling\n\nThis chapter contains a little background of error handling in Rust and how PyO3 integrates this with Python exceptions.\n\nThis covers enough detail to create a `#[pyfunction]` which raises Python exceptions from errors originating in Rust.\n\nThere is a later section of the guide on [Python exceptions](../exception.md) which covers exception types in more detail.\n\n## Representing Python exceptions\n\nRust code uses the generic [`Result<T, E>`] enum to propagate errors.\nThe error type `E` is chosen by the code author to describe the possible errors which can happen.\n\nPyO3 has the [`PyErr`] type which represents a Python exception.\nIf a PyO3 API could result in a Python exception being raised, the return type of that `API` will be [`PyResult<T>`], which is an alias for the type `Result<T, PyErr>`.\n\nIn summary:\n\n- When Python exceptions are raised and caught by PyO3, the exception will be stored in the `Err` variant of the `PyResult`.\n- Passing Python exceptions through Rust code then uses all the \"normal\" techniques such as the `?` operator, with `PyErr` as the error type.\n- Finally, when a `PyResult` crosses from Rust back to Python via PyO3, if the result is an `Err` variant the contained exception will be raised.\n\n(There are many great tutorials on Rust error handling and the `?` operator, so this guide will not go into detail on Rust-specific topics.)\n\n## Raising an exception from a function\n\nAs indicated in the previous section, when a `PyResult` containing an `Err` crosses from Rust to Python, PyO3 will raise the exception contained within.\n\nAccordingly, to raise an exception from a `#[pyfunction]`, change the return type `T` to `PyResult<T>`.\nWhen the function returns an `Err` it will raise a Python exception. (Other `Result<T, E>` types can be used as long as the error `E` has a `From` conversion for `PyErr`, see [custom Rust error types](#custom-rust-error-types) below.)\n\nThis also works for functions in `#[pymethods]`.\n\nFor example, the following `check_positive` function raises a `ValueError` when the input is negative:\n\n```rust\nuse pyo3::exceptions::PyValueError;\nuse pyo3::prelude::*;\n\n#[pyfunction]\nfn check_positive(x: i32) -> PyResult<()> {\n    if x < 0 {\n        Err(PyValueError::new_err(\"x is negative\"))\n    } else {\n        Ok(())\n    }\n}\n#\n# fn main(){\n# \tPython::attach(|py|{\n# \t\tlet fun = pyo3::wrap_pyfunction!(check_positive, py).unwrap();\n# \t\tfun.call1((-1,)).unwrap_err();\n# \t\tfun.call1((1,)).unwrap();\n# \t});\n# }\n```\n\nAll built-in Python exception types are defined in the [`pyo3::exceptions`] module.\nThey have a `new_err` constructor to directly build a `PyErr`, as seen in the example above.\n\n## Custom Rust error types\n\nPyO3 will automatically convert a `Result<T, E>` returned by a `#[pyfunction]` into a `PyResult<T>` as long as there is an implementation of `std::from::From<E> for PyErr`.\nMany error types in the Rust standard library have a [`From`] conversion defined in this way.\n\nIf the type `E` you are handling is defined in a third-party crate, see the section on [foreign rust error types](#foreign-rust-error-types) below for ways to work with this error.\n\nThe following example makes use of the implementation of `From<ParseIntError> for PyErr` to raise exceptions encountered when parsing strings as integers:\n\n```rust\n# use pyo3::prelude::*;\nuse std::num::ParseIntError;\n\n#[pyfunction]\nfn parse_int(x: &str) -> Result<usize, ParseIntError> {\n    x.parse()\n}\n\n# fn main() {\n#     Python::attach(|py| {\n#         let fun = pyo3::wrap_pyfunction!(parse_int, py).unwrap();\n#         let value: usize = fun.call1((\"5\",)).unwrap().extract().unwrap();\n#         assert_eq!(value, 5);\n#     });\n# }\n```\n\nWhen passed a string which doesn't contain a floating-point number, the exception raised will look like the below:\n\n```python\n>>> parse_int(\"bar\")\nTraceback (most recent call last):\n  File \"<stdin>\", line 1, in <module>\nValueError: invalid digit found in string\n```\n\nAs a more complete example, the following snippet defines a Rust error named `CustomIOError`.\nIt then defines a `From<CustomIOError> for PyErr`, which returns a `PyErr` representing Python's `OSError`.\nTherefore, it can use this error in the result of a `#[pyfunction]` directly, relying on the conversion if it has to be propagated into a Python exception.\n\n```rust\nuse pyo3::exceptions::PyOSError;\nuse pyo3::prelude::*;\nuse std::fmt;\n\n#[derive(Debug)]\nstruct CustomIOError;\n\nimpl std::error::Error for CustomIOError {}\n\nimpl fmt::Display for CustomIOError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"Oh no!\")\n    }\n}\n\nimpl std::convert::From<CustomIOError> for PyErr {\n    fn from(err: CustomIOError) -> PyErr {\n        PyOSError::new_err(err.to_string())\n    }\n}\n\npub struct Connection {/* ... */}\n\nfn bind(addr: String) -> Result<Connection, CustomIOError> {\n    if &addr == \"0.0.0.0\" {\n        Err(CustomIOError)\n    } else {\n        Ok(Connection{ /* ... */})\n    }\n}\n\n#[pyfunction]\nfn connect(s: String) -> Result<(), CustomIOError> {\n    bind(s)?;\n    // etc.\n    Ok(())\n}\n\nfn main() {\n    Python::attach(|py| {\n        let fun = pyo3::wrap_pyfunction!(connect, py).unwrap();\n        let err = fun.call1((\"0.0.0.0\",)).unwrap_err();\n        assert!(err.is_instance_of::<PyOSError>(py));\n    });\n}\n```\n\nIf lazy construction of the Python exception instance is desired, the [`PyErrArguments`]({{#PYO3_DOCS_URL}}/pyo3/trait.PyErrArguments.html) trait can be implemented instead of `From`.\nIn that case, actual exception argument creation is delayed until the `PyErr` is needed.\n\nA final note is that any errors `E` which have a `From` conversion can be used with the `?` (\"try\") operator with them.\nAn alternative implementation of the above `parse_int` which instead returns `PyResult` is below:\n\n```rust\nuse pyo3::prelude::*;\n\nfn parse_int(s: String) -> PyResult<usize> {\n    let x = s.parse()?;\n    Ok(x)\n}\n#\n# use pyo3::exceptions::PyValueError;\n#\n# fn main() {\n#     Python::attach(|py| {\n#         assert_eq!(parse_int(String::from(\"1\")).unwrap(), 1);\n#         assert_eq!(parse_int(String::from(\"1337\")).unwrap(), 1337);\n#\n#         assert!(parse_int(String::from(\"-1\"))\n#             .unwrap_err()\n#             .is_instance_of::<PyValueError>(py));\n#         assert!(parse_int(String::from(\"foo\"))\n#             .unwrap_err()\n#             .is_instance_of::<PyValueError>(py));\n#         assert!(parse_int(String::from(\"13.37\"))\n#             .unwrap_err()\n#             .is_instance_of::<PyValueError>(py));\n#     })\n# }\n```\n\n## Foreign Rust error types\n\nThe Rust compiler will not permit implementation of traits for types outside of the crate where the type is defined. (This is known as the \"orphan rule\".)\n\nGiven a type `OtherError` which is defined in third-party code, there are two main strategies available to integrate it with PyO3:\n\n- Create a newtype wrapper, e.g. `MyOtherError`.\n  Then implement `From<MyOtherError> for PyErr` (or `PyErrArguments`), as well as `From<OtherError>` for `MyOtherError`.\n- Use Rust's Result combinators such as `map_err` to write code freely to convert `OtherError` into whatever is needed.\n  This requires boilerplate at every usage however gives unlimited flexibility.\n\nTo detail the newtype strategy a little further, the key trick is to return `Result<T, MyOtherError>` from the `#[pyfunction]`.\nThis means that PyO3 will make use of `From<MyOtherError> for PyErr` to create Python exceptions while the `#[pyfunction]` implementation can use `?` to convert `OtherError` to `MyOtherError` automatically.\n\nThe following example demonstrates this for some imaginary third-party crate `some_crate` with a function `get_x` returning `Result<i32, OtherError>`:\n\n```rust\n# mod some_crate {\n#   pub struct OtherError(());\n#   impl OtherError {\n#       pub fn message(&self) -> &'static str { \"some error occurred\" }\n#   }\n#   pub fn get_x() -> Result<i32, OtherError> { Ok(5) }\n# }\n\nuse pyo3::prelude::*;\nuse pyo3::exceptions::PyValueError;\nuse some_crate::{OtherError, get_x};\n\nstruct MyOtherError(OtherError);\n\nimpl From<MyOtherError> for PyErr {\n    fn from(error: MyOtherError) -> Self {\n        PyValueError::new_err(error.0.message())\n    }\n}\n\nimpl From<OtherError> for MyOtherError {\n    fn from(other: OtherError) -> Self {\n        Self(other)\n    }\n}\n\n#[pyfunction]\nfn wrapped_get_x() -> Result<i32, MyOtherError> {\n    // get_x is a function returning Result<i32, OtherError>\n    let x: i32 = get_x()?;\n    Ok(x)\n}\n\n# fn main() {\n#     Python::attach(|py| {\n#         let fun = pyo3::wrap_pyfunction!(wrapped_get_x, py).unwrap();\n#         let value: usize = fun.call0().unwrap().extract().unwrap();\n#         assert_eq!(value, 5);\n#     });\n# }\n```\n\n## Notes\n\nIn Python 3.11 and up, notes can be added to Python exceptions to provide additional debugging information when printing the exception.\nIn PyO3, you can use the `add_note` method on `PyErr` to accomplish this functionality.\n\n[`From`]: https://doc.rust-lang.org/stable/std/convert/trait.From.html\n[`Result<T, E>`]: https://doc.rust-lang.org/stable/std/result/enum.Result.html\n[`PyResult<T>`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/type.PyResult.html\n[`PyErr`]: {{#PYO3_DOCS_URL}}/pyo3/struct.PyErr.html\n[`pyo3::exceptions`]: {{#PYO3_DOCS_URL}}/pyo3/exceptions/index.html\n"
  },
  {
    "path": "guide/src/function/signature.md",
    "content": "# Function signatures\n\nThe `#[pyfunction]` attribute also accepts parameters to control how the generated Python function accepts arguments.\nJust like in Python, arguments can be positional-only, keyword-only, or accept either.\n`*args` lists and `**kwargs` dicts can also be accepted.\nThese parameters also work for `#[pymethods]` which will be introduced in the [Python Classes](../class.md) section of the guide.\n\nLike Python, by default PyO3 accepts all arguments as either positional or keyword arguments.\nAll arguments are required by default.\nThis behaviour can be configured by the `#[pyo3(signature = (...))]` option which allows writing a signature in Python syntax.\n\nThis section of the guide goes into detail about use of the `#[pyo3(signature = (...))]` option and its related option `#[pyo3(text_signature = \"...\")]`\n\n## Using `#[pyo3(signature = (...))]`\n\nFor example, below is a function that accepts arbitrary keyword arguments (`**kwargs` in Python syntax) and returns the number that was passed:\n\n```rust,no_run\n#[pyo3::pymodule]\nmod module_with_functions {\n    use pyo3::prelude::*;\n    use pyo3::types::PyDict;\n\n    #[pyfunction]\n    #[pyo3(signature = (**kwds))]\n    fn num_kwds(kwds: Option<&Bound<'_, PyDict>>) -> usize {\n        kwds.map_or(0, |dict| dict.len())\n    }\n}\n```\n\nJust like in Python, the following constructs can be part of the signature::\n\n- `/`: positional-only arguments separator, each parameter defined before `/` is a positional-only parameter.\n- `*`: var arguments separator, each parameter defined after `*` is a keyword-only parameter.\n- `*args`: \"args\" is var args.\n  Type of the `args` parameter has to be `&Bound<'_, PyTuple>`.\n- `**kwargs`: \"kwargs\" receives keyword arguments.\n  The type of the `kwargs` parameter has to be `Option<&Bound<'_, PyDict>>`.\n- `arg=Value`: arguments with default value.\n   If the `arg` argument is defined after var arguments, it is treated as a keyword-only argument.\n   Note that `Value` has to be valid rust code, PyO3 just inserts it into the generated code unmodified.\n\nExample:\n\n```rust,no_run\n# use pyo3::prelude::*;\nuse pyo3::types::{PyDict, PyTuple};\n#\n# #[pyclass]\n# struct MyClass {\n#     num: i32,\n# }\n#[pymethods]\nimpl MyClass {\n    #[new]\n    #[pyo3(signature = (num=-1))]\n    fn new(num: i32) -> Self {\n        MyClass { num }\n    }\n\n    #[pyo3(signature = (num=10, *py_args, name=\"Hello\", **py_kwargs))]\n    fn method(\n        &mut self,\n        num: i32,\n        py_args: &Bound<'_, PyTuple>,\n        name: &str,\n        py_kwargs: Option<&Bound<'_, PyDict>>,\n    ) -> String {\n        let num_before = self.num;\n        self.num = num;\n        format!(\n            \"num={} (was previously={}), py_args={:?}, name={}, py_kwargs={:?} \",\n            num, num_before, py_args, name, py_kwargs,\n        )\n    }\n\n    fn make_change(&mut self, num: i32) -> PyResult<String> {\n        self.num = num;\n        Ok(format!(\"num={}\", self.num))\n    }\n}\n```\n\nArguments of type `Python` must not be part of the signature:\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n#[pyfunction]\n#[pyo3(signature = (lambda))]\npub fn simple_python_bound_function(py: Python<'_>, lambda: Py<PyAny>) -> PyResult<()> {\n    Ok(())\n}\n```\n\nN.B. the position of the `/` and `*` arguments (if included) control the system of handling positional and keyword arguments.\nIn Python:\n\n```python\nimport mymodule\n\nmc = mymodule.MyClass()\nprint(mc.method(44, False, \"World\", 666, x=44, y=55))\nprint(mc.method(num=-1, name=\"World\"))\nprint(mc.make_change(44))\n```\n\nProduces output:\n\n```text\nnum=44 (was previously=-1), py_args=(False, 'World', 666), name=Hello, py_kwargs=Some({'x': 44, 'y': 55})\nnum=-1 (was previously=44), py_args=(), name=World, py_kwargs=None\nnum=44\n```\n\n> [!NOTE]\n> To use keywords like `struct` as a function argument, use \"raw identifier\" syntax `r#struct` in both the signature and the function definition:\n>\n> ```rust,no_run\n> # #![allow(dead_code)]\n> # use pyo3::prelude::*;\n> #[pyfunction(signature = (r#struct = \"foo\"))]\n> fn function_with_keyword(r#struct: &str) {\n> #     let _ = r#struct;\n>     /* ... */\n> }\n> ```\n\n## Making the function signature available to Python\n\nThe function signature is exposed to Python via the `__text_signature__` attribute.\nPyO3 automatically generates this for every `#[pyfunction]` and all `#[pymethods]` directly from the Rust function, taking into account any override done with the `#[pyo3(signature = (...))]` option.\n\nThis automatic generation can only display the value of default arguments for strings, integers, boolean types, and `None`.\nAny other default arguments will be displayed as `...`. (`.pyi` type stub files commonly also use `...` for default arguments in the same way.)\n\nIn cases where the automatically-generated signature needs adjusting, it can [be overridden](#overriding-the-generated-signature) using the `#[pyo3(text_signature)]` option.)\n\nThe example below creates a function `add` which accepts two positional-only arguments `a` and `b`, where `b` has a default value of zero.\n\n```rust\nuse pyo3::prelude::*;\n\n/// This function adds two unsigned 64-bit integers.\n#[pyfunction]\n#[pyo3(signature = (a, b=0, /))]\nfn add(a: u64, b: u64) -> u64 {\n    a + b\n}\n#\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| {\n#         let fun = pyo3::wrap_pyfunction!(add, py)?;\n#\n#         let doc: String = fun.getattr(\"__doc__\")?.extract()?;\n#         assert_eq!(doc, \"This function adds two unsigned 64-bit integers.\");\n#\n#         let inspect = PyModule::import(py, \"inspect\")?.getattr(\"signature\")?;\n#         let sig: String = inspect\n#             .call1((fun,))?\n#             .call_method0(\"__str__\")?\n#             .extract()?;\n#\n#         #[cfg(Py_3_8)]  // on 3.7 the signature doesn't render b, upstream bug?\n#         assert_eq!(sig, \"(a, b=0, /)\");\n#\n#         Ok(())\n#     })\n# }\n```\n\nThe following IPython output demonstrates how this generated signature will be seen from Python tooling:\n\n```text\n>>> pyo3_test.add.__text_signature__\n'(a, b=..., /)'\n>>> pyo3_test.add?\nSignature: pyo3_test.add(a, b=0, /)\nDocstring: This function adds two unsigned 64-bit integers.\nType:      builtin_function_or_method\n```\n\n### Overriding the generated signature\n\nThe `#[pyo3(text_signature = \"(<some signature>)\")]` attribute can be used to override the default generated signature.\n\nIn the snippet below, the text signature attribute is used to include the default value of `0` for the argument `b`, instead of the automatically-generated default value of `...`:\n\n```rust\nuse pyo3::prelude::*;\n\n/// This function adds two unsigned 64-bit integers.\n#[pyfunction]\n#[pyo3(signature = (a, b=0, /), text_signature = \"(a, b=0, /)\")]\nfn add(a: u64, b: u64) -> u64 {\n    a + b\n}\n#\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| {\n#         let fun = pyo3::wrap_pyfunction!(add, py)?;\n#\n#         let doc: String = fun.getattr(\"__doc__\")?.extract()?;\n#         assert_eq!(doc, \"This function adds two unsigned 64-bit integers.\");\n#\n#         let inspect = PyModule::import(py, \"inspect\")?.getattr(\"signature\")?;\n#         let sig: String = inspect\n#             .call1((fun,))?\n#             .call_method0(\"__str__\")?\n#             .extract()?;\n#         assert_eq!(sig, \"(a, b=0, /)\");\n#\n#         Ok(())\n#     })\n# }\n```\n\nPyO3 will include the contents of the annotation unmodified as the `__text_signature__`.\nBelow shows how IPython will now present this (see the default value of 0 for b):\n\n```text\n>>> pyo3_test.add.__text_signature__\n'(a, b=0, /)'\n>>> pyo3_test.add?\nSignature: pyo3_test.add(a, b=0, /)\nDocstring: This function adds two unsigned 64-bit integers.\nType:      builtin_function_or_method\n```\n\nIf no signature is wanted at all, `#[pyo3(text_signature = None)]` will disable the built-in signature.\nThe snippet below demonstrates use of this:\n\n```rust\nuse pyo3::prelude::*;\n\n/// This function adds two unsigned 64-bit integers.\n#[pyfunction]\n#[pyo3(signature = (a, b=0, /), text_signature = None)]\nfn add(a: u64, b: u64) -> u64 {\n    a + b\n}\n#\n# fn main() -> PyResult<()> {\n#     Python::attach(|py| {\n#         let fun = pyo3::wrap_pyfunction!(add, py)?;\n#\n#         let doc: String = fun.getattr(\"__doc__\")?.extract()?;\n#         assert_eq!(doc, \"This function adds two unsigned 64-bit integers.\");\n#         assert!(fun.getattr(\"__text_signature__\")?.is_none());\n#\n#         Ok(())\n#     })\n# }\n```\n\nNow the function's `__text_signature__` will be set to `None`, and IPython will not display any signature in the help:\n\n```text\n>>> pyo3_test.add.__text_signature__ == None\nTrue\n>>> pyo3_test.add?\nDocstring: This function adds two unsigned 64-bit integers.\nType:      builtin_function_or_method\n```\n\n### Type annotations in the signature\n\nWhen the `experimental-inspect` Cargo feature is enabled, the `signature` attribute can also contain type hints:\n\n```rust\n# #[cfg(feature = \"experimental-inspect\")] {\nuse pyo3::prelude::*;\n\n#[pymodule]\npub mod example {\n   use pyo3::prelude::*;\n\n   #[pyfunction]\n   #[pyo3(signature = (arg: \"list[int]\") -> \"list[int]\")]\n   fn list_of_int_identity(arg: Bound<'_, PyAny>) -> Bound<'_, PyAny> {\n      arg\n   }\n}\n# }\n```\n\nIt enables the [work-in-progress capacity of PyO3 to autogenerate type stubs](../type-stub.md) to generate a file with the correct type hints:\n\n```python\ndef list_of_int_identity(arg: list[int]) -> list[int]: ...\n```\n\ninstead of the generic:\n\n```python\nimport typing\n\ndef list_of_int_identity(arg: typing.Any) -> typing.Any: ...\n```\n\nNote that currently type annotations must be written as Rust strings.\n"
  },
  {
    "path": "guide/src/function-calls.md",
    "content": "# Calling Python functions\n"
  },
  {
    "path": "guide/src/function.md",
    "content": "# Python functions\n\nThe `#[pyfunction]` attribute is used to define a Python function from a Rust function.\nOnce defined, the function needs to be added to a [module](./module.md).\n\nThe following example defines a function called `double` in a Python module called `my_extension`:\n\n```rust,no_run\n#[pyo3::pymodule]\nmod my_extension {\n    use pyo3::prelude::*;\n\n    #[pyfunction]\n    fn double(x: usize) -> usize {\n        x * 2\n    }\n}\n```\n\nThis chapter of the guide explains full usage of the `#[pyfunction]` attribute.\nIn this first section, the following topics are covered:\n\n- [Function options](#function-options)\n  - [`#[pyo3(name = \"...\")]`](#name)\n  - [`#[pyo3(signature = (...))]`](#signature)\n  - [`#[pyo3(text_signature = \"...\")]`](#text_signature)\n  - [`#[pyo3(pass_module)]`](#pass_module)\n  - [`#[pyo3(warn(message = \"...\", category = ...))]`](#warn)\n- [Per-argument options](#per-argument-options)\n- [Advanced function patterns](#advanced-function-patterns)\n\nThere are also additional sections on the following topics:\n\n- [Function Signatures](./function/signature.md)\n- [Error Handling](./function/error-handling.md)\n\n## Function options\n\nThe `#[pyo3]` attribute can be used to modify properties of the generated Python function.\nIt can take any combination of the following options:\n\n- <a id=\"name\"></a> `#[pyo3(name = \"...\")]`\n\n    Overrides the name exposed to Python.\n\n    In the following example, the Rust function `no_args_py` will be added to the Python module `module_with_functions` as the Python function `no_args`:\n\n    ```rust\n    # use pyo3::prelude::*;\n    #[pyo3::pymodule]\n    mod module_with_functions {\n        use pyo3::prelude::*;\n\n        #[pyfunction]\n        #[pyo3(name = \"no_args\")]\n        fn no_args_py() -> usize {\n            42\n        }\n    }\n\n    # Python::attach(|py| {\n    #     let m = pyo3::wrap_pymodule!(module_with_functions)(py);\n    #     assert!(m.getattr(py, \"no_args\").is_ok());\n    #     assert!(m.getattr(py, \"no_args_py\").is_err());\n    # });\n    ```\n\n- <a id=\"signature\"></a> `#[pyo3(signature = (...))]`\n\n    Defines the function signature in Python.\n    See [Function Signatures](./function/signature.md).\n\n- <a id=\"text_signature\"></a> `#[pyo3(text_signature = \"...\")]`\n\n    Overrides the PyO3-generated function signature visible in Python tooling (such as via [`inspect.signature`]).\n    See the [corresponding topic in the Function Signatures subchapter](./function/signature.md#making-the-function-signature-available-to-python).\n\n- <a id=\"pass_module\" ></a> `#[pyo3(pass_module)]`\n\n    Set this option to make PyO3 pass the containing module as the first argument to the function.\n    It is then possible to use the module in the function body.\n    The first argument **must** be of type `&Bound<'_, PyModule>`, `Bound<'_, PyModule>`, or `Py<PyModule>`.\n\n    The following example creates a function `pyfunction_with_module` which returns the containing module's name (i.e. `module_with_fn`):\n\n    ```rust,no_run\n    #[pyo3::pymodule]\n    mod module_with_fn {\n        use pyo3::prelude::*;\n        use pyo3::types::PyString;\n\n        #[pyfunction]\n        #[pyo3(pass_module)]\n        fn pyfunction_with_module<'py>(\n            module: &Bound<'py, PyModule>,\n        ) -> PyResult<Bound<'py, PyString>> {\n            module.name()\n        }\n    }\n    ```\n\n- <a id=\"warn\"></a> `#[pyo3(warn(message = \"...\", category = ...))]`\n\n    This option is used to display a warning when the function is used in Python.\n    It is equivalent to [`warnings.warn(message, category)`](https://docs.python.org/3/library/warnings.html#warnings.warn).\n    The `message` parameter is a string that will be displayed when the function is called, and the `category` parameter is optional and has to be a subclass of [`Warning`](https://docs.python.org/3/library/exceptions.html#Warning).\n    When the `category` parameter is not provided, the warning will be defaulted to [`UserWarning`](https://docs.python.org/3/library/exceptions.html#UserWarning).\n\n    > Note: when used with `#[pymethods]`, this attribute does not work with `#[classattr]` nor `__traverse__` magic method.\n\n    The following are examples of using the `#[pyo3(warn)]` attribute:\n\n    ```rust\n    use pyo3::prelude::*;\n\n    #[pymodule]\n    mod raising_warning_fn {\n        use pyo3::prelude::pyfunction;\n        use pyo3::exceptions::PyFutureWarning;\n\n        #[pyfunction]\n        #[pyo3(warn(message = \"This is a warning message\"))]\n        fn function_with_warning() -> usize {\n            42\n        }\n\n        #[pyfunction]\n        #[pyo3(warn(message = \"This function is warning with FutureWarning\", category = PyFutureWarning))]\n        fn function_with_warning_and_custom_category() -> usize {\n            42\n        }\n    }\n\n    # use pyo3::exceptions::{PyFutureWarning, PyUserWarning};\n    # use pyo3::types::{IntoPyDict, PyList};\n    # use pyo3::PyTypeInfo;\n    #\n    # fn catch_warning(py: Python<'_>, f: impl FnOnce(&Bound<'_, PyList>) -> ()) -> PyResult<()> {\n    #     let warnings = py.import(\"warnings\")?;\n    #     let kwargs = [(\"record\", true)].into_py_dict(py)?;\n    #     let catch_warnings = warnings\n    #         .getattr(\"catch_warnings\")?\n    #         .call((), Some(&kwargs))?;\n    #     let list = catch_warnings.call_method0(\"__enter__\")?.cast_into()?;\n    #     warnings.getattr(\"simplefilter\")?.call1((\"always\",))?;  // show all warnings\n    #     f(&list);\n    #     catch_warnings\n    #         .call_method1(\"__exit__\", (py.None(), py.None(), py.None()))\n    #         .unwrap();\n    #     Ok(())\n    # }\n    #\n    # macro_rules! assert_warnings {\n    #     ($py:expr, $body:expr, [$(($category:ty, $message:literal)),+] $(,)? ) => {\n    #         catch_warning($py, |list| {\n    #             $body;\n    #             let expected_warnings = [$((<$category as PyTypeInfo>::type_object($py), $message)),+];\n    #             assert_eq!(list.len(), expected_warnings.len());\n    #             for (warning, (category, message)) in list.iter().zip(expected_warnings) {\n    #                 assert!(warning.getattr(\"category\").unwrap().is(&category));\n    #                 assert_eq!(\n    #                     warning.getattr(\"message\").unwrap().str().unwrap().to_string_lossy(),\n    #                     message\n    #                 );\n    #             }\n    #         }).unwrap();\n    #     };\n    # }\n    #\n    # Python::attach(|py| {\n    #     assert_warnings!(\n    #         py,\n    #         {\n    #             let m = pyo3::wrap_pymodule!(raising_warning_fn)(py);\n    #             let f1 = m.getattr(py, \"function_with_warning\").unwrap();\n    #             let f2 = m.getattr(py, \"function_with_warning_and_custom_category\").unwrap();\n    #             f1.call0(py).unwrap();\n    #             f2.call0(py).unwrap();\n    #         },\n    #         [\n    #             (PyUserWarning, \"This is a warning message\"),\n    #             (\n    #                 PyFutureWarning,\n    #                 \"This function is warning with FutureWarning\"\n    #             )\n    #         ]\n    #     );\n    # });\n    ```\n\n    When the functions are called as the following, warnings will be displayed.\n\n    ```python\n    import warnings\n    from raising_warning_fn import function_with_warning, function_with_warning_and_custom_category\n\n    function_with_warning()\n    function_with_warning_and_custom_category()\n    ```\n\n    The warning output will be:\n\n    ```plaintext\n    UserWarning: This is a warning message\n    FutureWarning: This function is warning with FutureWarning\n    ```\n\n## Per-argument options\n\nThe `#[pyo3]` attribute can be used on individual arguments to modify properties of them in the generated function.\nIt can take any combination of the following options:\n\n- <a id=\"from_py_with\"></a> `#[pyo3(from_py_with = ...)]`\n\n    Set this on an option to specify a custom function to convert the function argument from Python to the desired Rust type, instead of using the default `FromPyObject` extraction.\n    The function signature must be `fn(&Bound<'_, PyAny>) -> PyResult<T>` where `T` is the Rust type of the argument.\n\n    The following example uses `from_py_with` to convert the input Python object to its length:\n\n    ```rust\n    use pyo3::prelude::*;\n\n    fn get_length(obj: &Bound<'_, PyAny>) -> PyResult<usize> {\n        obj.len()\n    }\n\n    #[pyfunction]\n    fn object_length(#[pyo3(from_py_with = get_length)] argument: usize) -> usize {\n        argument\n    }\n\n    # Python::attach(|py| {\n    #     let f = pyo3::wrap_pyfunction!(object_length)(py).unwrap();\n    #     assert_eq!(f.call1((vec![1, 2, 3],)).unwrap().extract::<usize>().unwrap(), 3);\n    # });\n    ```\n\n## Advanced function patterns\n\n### Calling Python functions in Rust\n\nYou can pass Python `def`'d functions and built-in functions to Rust functions [`PyFunction`] corresponds to regular Python functions while [`PyCFunction`] describes built-ins such as `repr()`.\n\nYou can also use [`Bound<'_, PyAny>::is_callable`] to check if you have a callable object.\n`is_callable` will return `true` for functions (including lambdas), methods and objects with a `__call__` method.\nYou can call the object with [`Bound<'_, PyAny>::call`] with the args as first parameter and the kwargs (or `None`) as second parameter.\nThere are also [`Bound<'_, PyAny>::call0`] with no args and [`Bound<'_, PyAny>::call1`] with only positional args.\n\n### Calling Rust functions in Python\n\nThe ways to convert a Rust function into a Python object vary depending on the function:\n\n- Named functions, e.g. `fn foo()`: add `#[pyfunction]` and then use [`wrap_pyfunction!`] to get the corresponding [`PyCFunction`].\n- Anonymous functions (or closures), e.g. `foo: fn()` either:\n  - use a `#[pyclass]` struct which stores the function as a field and implement `__call__` to call the stored function.\n  - use `PyCFunction::new_closure` to create an object directly from the function.\n\n### Accessing the FFI functions\n\nIn order to make Rust functions callable from Python, PyO3 generates an `extern \"C\"` function whose exact signature depends on the Rust signature. (PyO3 chooses the optimal Python argument passing convention.) It then embeds the call to the Rust function inside this FFI-wrapper function.\nThis wrapper handles extraction of the regular arguments and the keyword arguments from the input `PyObject`s.\n\nThe `wrap_pyfunction` macro can be used to directly get a `Bound<PyCFunction>` given a `#[pyfunction]` and a `Bound<PyModule>`: `wrap_pyfunction!(rust_fun, module)`.\n\n[`Bound<'_, PyAny>::is_callable`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.is_callable\n[`Bound<'_, PyAny>::call`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call\n[`Bound<'_, PyAny>::call0`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call0\n[`Bound<'_, PyAny>::call1`]: {{#PYO3_DOCS_URL}}/pyo3/prelude/trait.PyAnyMethods.html#tymethod.call1\n[`wrap_pyfunction!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.wrap_pyfunction.html\n[`PyFunction`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyFunction.html\n[`PyCFunction`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyCFunction.html\n[`inspect.signature`]: https://docs.python.org/3/library/inspect.html#inspect.signature\n"
  },
  {
    "path": "guide/src/getting-started.md",
    "content": "# Installation\n\nTo get started using PyO3 you will need three things: a Rust toolchain, a Python environment, and a way to build.\nWe'll cover each of these below.\n\n> [!TIP]\n> If you'd like to chat to the PyO3 maintainers and other PyO3 users, consider joining the [PyO3 Discord server](https://discord.gg/33kcChzH7f). We're keen to hear about your experience getting started, so we can make PyO3 as accessible as possible for everyone!\n\n## Rust\n\nFirst, make sure you have Rust installed on your system.\nIf you haven't already done so, try following the instructions [on the Rust website](https://www.rust-lang.org/tools/install).\nPyO3 runs on both the `stable` and `nightly` versions so you can choose whichever one fits you best.\nThe minimum required Rust version is 1.83.\n\nIf you can run `rustc --version` and the version is new enough you're good to go!\n\n## Python\n\nTo use PyO3, you need at least Python 3.7.\nWhile you can simply use the default Python interpreter on your system, it is recommended to use a virtual environment.\n\n## Virtualenvs\n\nWhile you can use any virtualenv manager you like, we recommend the use of `pyenv` in particular if you want to develop or test for multiple different Python versions, so that is what the examples in this book will use.\nThe installation instructions for `pyenv` can be found [in the `pyenv` GitHub repository](https://github.com/pyenv/pyenv#a-getting-pyenv). (Note: To get the `pyenv activate` and `pyenv virtualenv` commands, you will also need to install the [`pyenv-virtualenv`](https://github.com/pyenv/pyenv-virtualenv) plugin.\nThe [pyenv installer](https://github.com/pyenv/pyenv-installer#installation--update--uninstallation) will install both together.)\n\nIt can be useful to keep the sources used when installing using `pyenv` so that future debugging can see the original source files.\nThis can be done by passing the `--keep` flag as part of the `pyenv install` command.\n\nFor example:\n\n```bash\npyenv install 3.12 --keep\n```\n\n### Building\n\nThere are a number of build and Python package management systems such as [`setuptools-rust`](https://github.com/PyO3/setuptools-rust) or [manually](./building-and-distribution.md#manual-builds).\nWe recommend the use of `maturin`, which you can install [as per the `maturin` documentation](https://maturin.rs/installation.html).\nIt is developed to work with PyO3 and provides the most \"batteries included\" experience, especially if you are aiming to publish to PyPI.\n`maturin` is just a Python package, so you can add it in the same way you already install Python packages.\n\nSystem Python:\n\n```bash\npip install maturin --user\n```\n\npipx:\n\n```bash\npipx install maturin\n```\n\npyenv:\n\n```bash\npyenv activate pyo3\npip install maturin\n```\n\npoetry:\n\n```bash\npoetry add -G dev maturin\n```\n\nAfter installation, you can run `maturin --version` to check that you have correctly installed it.\n\n## Starting a new project\n\nFirst you should create the folder and virtual environment that are going to contain your new project.\nHere we will use the recommended `pyenv`:\n\n```bash\nmkdir pyo3-example\ncd pyo3-example\npyenv virtualenv pyo3\npyenv local pyo3\n```\n\nAfter this, you should install your build manager.\nIn this example, we will use `maturin`.\nAfter you've activated your virtualenv, add `maturin` to it:\n\n```bash\npip install maturin\n```\n\nNow you can initialize the new project:\n\n```bash\nmaturin init\n```\n\nIf `maturin` is already installed, you can create a new project using that directly as well:\n\n```bash\nmaturin new -b pyo3 pyo3-example\ncd pyo3-example\npyenv virtualenv pyo3\npyenv local pyo3\n```\n\n## Adding to an existing project\n\nSadly, `maturin` cannot currently be run in existing projects, so if you want to use Python in an existing project you basically have two options:\n\n1. Create a new project as above and move your existing code into that project\n2. Manually edit your project configuration as necessary\n\nIf you opt for the second option, here are the things you need to pay attention to:\n\n## Cargo.toml\n\nMake sure that the Rust crate you want to be able to access from Python is compiled into a library.\nYou can have a binary output as well, but the code you want to access from Python has to be in the library part.\nAlso, make sure that the crate type is `cdylib` and add PyO3 as a dependency as so:\n\n```toml\n# If you already have [package] information in `Cargo.toml`, you can ignore\n# this section!\n[package]\n# `name` here is name of the package.\nname = \"pyo3_start\"\n# these are good defaults:\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\n# The name of the native library. This is the name which will be used in Python to import the\n# library (i.e. `import string_sum`). If you change this, you must also change the name of the\n# `#[pymodule]` in `src/lib.rs`.\nname = \"pyo3_example\"\n\n# \"cdylib\" is necessary to produce a shared library for Python to import from.\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3 = {{#PYO3_CRATE_VERSION}}\n```\n\n## pyproject.toml\n\nYou should also create a `pyproject.toml` with the following contents:\n\n```toml\n[build-system]\nrequires = [\"maturin>=1.9.4,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"pyo3_example\"\nrequires-python = \">=3.7\"\nclassifiers = [\n    \"Programming Language :: Rust\",\n    \"Programming Language :: Python :: Implementation :: CPython\",\n    \"Programming Language :: Python :: Implementation :: PyPy\",\n]\n```\n\n## Running code\n\nAfter this you can setup Rust code to be available in Python as below; for example, you can place this code in `src/lib.rs`:\n\n```rust,no_run\n/// A Python module implemented in Rust. The name of this function must match\n/// the `lib.name` setting in the `Cargo.toml`, else Python will not be able to\n/// import the module.\n#[pyo3::pymodule]\nmod pyo3_example {\n    use pyo3::prelude::*;\n\n    /// Formats the sum of two numbers as string.\n    #[pyfunction]\n    fn sum_as_string(a: usize, b: usize) -> PyResult<String> {\n        Ok((a + b).to_string())\n    }\n}\n```\n\nNow you can run `maturin develop` to prepare the Python package, after which you can use it like so:\n\n```bash\n$ maturin develop\n# lots of progress output as maturin runs the compilation...\n$ python\n>>> import pyo3_example\n>>> pyo3_example.sum_as_string(5, 20)\n'25'\n```\n\nFor more instructions on how to use Python code from Rust, see the [Python from Rust](python-from-rust.md) page.\n\n## Maturin Import Hook\n\nIn development, any changes in the code would require running `maturin develop` before testing.\nTo streamline the development process, you may want to install [Maturin Import Hook](https://github.com/PyO3/maturin-import-hook) which will run `maturin develop` automatically when the library with code changes is being imported.\n"
  },
  {
    "path": "guide/src/index.md",
    "content": "# The PyO3 user guide\n\nWelcome to the PyO3 user guide!\nThis book is a companion to [PyO3's API docs](https://docs.rs/pyo3).\nIt contains examples and documentation to explain all of PyO3's use cases in detail.\n\nThe rough order of material in this user guide is as follows:\n  1. Getting started\n  2. Wrapping Rust code for use from Python\n  3. How to use Python code from Rust\n  4. Remaining topics which go into advanced concepts in detail\n\nPlease choose from the chapters on the left to jump to individual topics, or continue below to start with PyO3's README.\n\n<hr style=\"opacity:0.2\">\n\n{{#include ../../README.md}}\n"
  },
  {
    "path": "guide/src/migration.md",
    "content": "# Migrating from older PyO3 versions\n\nThis guide can help you upgrade code through breaking changes from one PyO3 version to the next.\nFor a detailed list of all changes, see the [CHANGELOG](changelog.md).\n\n## from 0.28.* to 0.29\n\n### Removed implementations of `From<str::Utf8Error>`, `From<string::FromUtf16Error>`, and `From<char::DecodeUtf16Error>` for `PyErr`\n\nPreviously the implementations of `From<string::FromUtf8Error>`, `From<ffi::IntoStringError>`, `From<str::Utf8Error>`, `From<string::FromUtf16Error>`, and `From<char::DecodeUtf16Error>` failed to construct the correct Python exception class, as reported in <https://github.com/PyO3/pyo3/issues/5651>.\nThe implementations for `string::FromUtf8Error` and `ffi::IntoStringError` were fixed in this release.\n\nFor `str::Utf8Error`, the Rust error does not contain the source bytes required to construct the Python exception.\nInstead, `PyUnicodeDecodeError::new_err_from_utf8` can be used to convert the error to a `PyErr`.\n\nBefore:\n\n```rust,ignore\nfn bytes_to_str(bytes: &[u8]) -> PyResult<&str> {\n    Ok(std::str::from_utf8(bytes)?)\n}\n```\n\nAfter:\n\n```rust\n# use pyo3::prelude::*;\nuse pyo3::exceptions::PyUnicodeDecodeError;\n\n# #[expect(dead_code)]\nfn bytes_to_str<'a>(py: Python<'_>, bytes: &'a [u8]) -> PyResult<&'a str> {\n    std::str::from_utf8(bytes).map_err(|e| PyUnicodeDecodeError::new_err_from_utf8(py, bytes, e))\n}\n```\n\nFor `string::FromUtf16Error` and `char::DecodeUtf16Error` the Rust error types do not contain any of the information required to construct a `UnicodeDecodeError`.\nTo raise a Python `UnicodeDecodeError` a new error should be manually constructed by calling `PyUnicodeDecodeError::new_err(...)`.\n\n## from 0.27.* to 0.28\n\n### Default to supporting free-threaded Python\n\n<details open>\n<summary><small>Click to expand</small></summary>\n\nWhen PyO3 0.23 added support for free-threaded Python, this was as an opt-in feature for modules by annotating with `#[pymodule(gil_used = false)]`.\n\nAs the support has matured and PyO3's own API has evolved to remove reliance on the GIL, the time is right to switch the default.\nModules now automatically allow use on free-threaded Python, unless they directly state they require the GIL with `#[pymodule(gil_used = true)]`.\n</details>\n\n### Deprecation of automatic `FromPyObject` for `#[pyclass]` types which implement `Clone`\n\n<details open>\n<summary><small>Click to expand</small></summary>\n\n`#[pyclass]` types which implement `Clone` used to also implement `FromPyObject` automatically.\nThis behavior is being phased out and replaced by an explicit opt-in, which will allow [better error messages and more user control](https://github.com/PyO3/pyo3/issues/5419).\nAffected types will by marked by a deprecation message.\n\nTo migrate use either\n\n- `#[pyclass(from_py_object)]` to keep the automatic derive, or\n- `#[pyclass(skip_from_py_object)]` to accept the new behavior.\n\nBefore:\n\n```rust\n# #![allow(deprecated)]\n# use pyo3::prelude::*;\n#[pyclass]\n#[derive(Clone)]\nstruct PyClass {}\n```\n\nAfter:\n\n```rust\n# use pyo3::prelude::*;\n// If the automatic implementation of `FromPyObject` is desired, opt in:\n#[pyclass(from_py_object)]\n#[derive(Clone)]\nstruct PyClass {}\n\n// or if the `FromPyObject` implementation is not needed:\n#[pyclass(skip_from_py_object)]\n#[derive(Clone)]\nstruct PyClassWithoutFromPyObject {}\n```\n\nThe `#[pyclass(skip_from_py_object)]` option will eventually be deprecated and removed as it becomes the default behavior.\n\n</details>\n\n### Deprecation of `Py<T>` constructors from raw pointer\n\n<details open>\n<summary><small>Click to expand</small></summary>\n\nThe constructors `Py::from_owned_ptr`, `Py::from_owned_ptr_or_opt`, and `Py::from_owned_ptr_or_err` (and similar \"borrowed\" variants) perform an unchecked cast to the `Py<T>` target type `T`.\nThis unchecked cast is a footgun on APIs where the primary concern is about constructing PyO3's safe smart pointer types correctly from the raw pointer value.\n\nThe equivalent constructors on `Bound` always produce a `Bound<PyAny>`, which encourages any subsequent cast to be done explicitly as either checked or unchecked.\nThese should be used instead.\n\nBefore:\n\n```rust\n# #![allow(deprecated)]\n# use pyo3::prelude::*;\n# use pyo3::types::PyNone;\n# Python::attach(|py| {\nlet raw_ptr = py.None().into_ptr();\n\nlet _: Py<PyNone> = unsafe { Py::from_borrowed_ptr(py, raw_ptr) };\nlet _: Py<PyNone> = unsafe { Py::from_owned_ptr(py, raw_ptr) };\n# })\n```\n\nAfter:\n\n```rust\n# use pyo3::prelude::*;\n# use pyo3::types::PyNone;\n# Python::attach(|py| {\nlet raw_ptr = py.None().into_ptr();\n\n// Bound APIs require choice of doing unchecked or checked cast. Optionally `.unbind()` to\n// produce `Py<T>` values.\nlet _: Bound<'_, PyNone> = unsafe { Bound::from_borrowed_ptr(py, raw_ptr).cast_into_unchecked() };\nlet _: Bound<'_, PyNone> = unsafe { Bound::from_owned_ptr(py, raw_ptr).cast_into_unchecked() };\n# })\n```\n\n</details>\n\n### Removal of `From<Bound<'_, T>` and `From<Py<T>> for PyClassInitializer<T>`\n\n<details open>\n<summary><small>Click to expand</small></summary>\n\nAs part of refactoring the initialization code these impls were removed and its functionality was moved into the generated code for `#[new]`.\nAs a small side side effect the following pattern will not be accepted anymore:\n\n```rust,ignore\n# use pyo3::prelude::*;\n# Python::attach(|py| {\n# let existing_py: Py<PyAny> = py.None();\nlet obj_1 = Py::new(py, existing_py);\n\n# let existing_bound: Bound<'_, PyAny> = py.None().into_bound(py);\nlet obj_2 = Bound::new(py, existing_bound);\n# })\n```\n\nTo migrate use `clone` or `clone_ref`:\n\n```rust\n# use pyo3::prelude::*;\n# Python::attach(|py| {\n# let existing_py: Py<PyAny> = py.None();\nlet obj_1 = existing_py.clone_ref(py);\n\n# let existing_bound: Bound<'_, PyAny> = py.None().into_bound(py);\nlet obj_2 = existing_bound.clone();\n# })\n```\n\n</details>\n\n### Untyped buffer API moved to PyUntypedBuffer\n\n<details open>\n<summary><small>Click to expand</small></summary>\n\n`PyBuffer<T>` now is a typed wrapper around `PyUntypedBuffer`.\nMany methods such as `PyBuffer::format` have been moved to `PyUntypedBuffer::format`.\n`PyBuffer<T>` dereferences to `PyUntypedBuffer`, so method call syntax will continue to work as-is.\nUsers may need to update references to the moved functions.\n</details>\n\n### Internal change to use multi-phase initialization\n\n<details open>\n<summary><small>Click to expand</small></summary>\n\n[PEP 489](https://peps.python.org/pep-0489/) introduced \"multi-phase initialization\" for extension modules which provides ways to allocate and clean up per-module state.\nThis is a necessary step towards supporting Python \"subinterpreters\" which run on their own copy of state.\n\nStarting in PyO3 0.28, the `#[pymodule]` macro machinery has been reworked to use multi-phase initialization.\nThe possibility of creating and consuming per-module state (and supporting subinterpreters) is left for a future PyO3 version.\nThis should not require migration, nor is there expected to be breakage caused by the change.\n\nNevertheless, this affects the order of initialization so seemed worth noting in this guide.\n</details>\n\n## from 0.26.* to 0.27\n\n### `FromPyObject` reworked for flexibility and efficiency\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nWith the removal of the `gil-ref` API in PyO3 0.23 it is now possible to fully split the Python lifetime `'py` and the input lifetime `'a`.\nThis allows borrowing from the input data without extending the lifetime of being attached to the interpreter.\n\n`FromPyObject` now takes an additional lifetime `'a` describing the input lifetime.\nThe argument type of the `extract` method changed from `&Bound<'py, PyAny>` to `Borrowed<'a, 'py, PyAny>`.\nThis was done because `&'a Bound<'py, PyAny>` would have an implicit restriction `'py: 'a` due to the reference type.\n\nThis new form was partly implemented already in 0.22 using the internal `FromPyObjectBound` trait and is now extended to all types.\n\nMost implementations can just add an elided lifetime to migrate.\n\nAdditionally `FromPyObject` gained an associated type `Error`.\nThis is the error type that can be used in case of a conversion error.\nDuring migration using `PyErr` is a good default, later a custom error type can be introduced to prevent unnecessary creation of Python exception objects and improved type safety.\n\nBefore:\n\n```rust,ignore\nimpl<'py> FromPyObject<'py> for IpAddr {\n    fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {\n        ...\n    }\n}\n```\n\nAfter\n\n```rust,ignore\nimpl<'py> FromPyObject<'_, 'py> for IpAddr {\n    type Error = PyErr;\n\n    fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        ...\n        // since `Borrowed` derefs to `&Bound`, the body often\n        // needs no changes, or adding an occasional `&`\n    }\n}\n```\n\nOccasionally, more steps are necessary.\nFor generic types, the bounds need to be adjusted.\nThe correct bound depends on how the type is used.\n\nFor simple wrapper types usually it's possible to just forward the bound.\n\nBefore:\n\n```rust,ignore\nstruct MyWrapper<T>(T);\n\nimpl<'py, T> FromPyObject<'py> for MyWrapper<T>\nwhere\n    T: FromPyObject<'py>\n{\n    fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {\n        ob.extract().map(MyWrapper)\n    }\n}\n```\n\nAfter:\n\n```rust\n# use pyo3::prelude::*;\n# #[allow(dead_code)]\n# pub struct MyWrapper<T>(T);\nimpl<'a, 'py, T> FromPyObject<'a, 'py> for MyWrapper<T>\nwhere\n    T: FromPyObject<'a, 'py>\n{\n    type Error = T::Error;\n\n    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        obj.extract().map(MyWrapper)\n    }\n}\n```\n\nContainer types that need to create temporary Python references during extraction, for example extracting from a `PyList`, requires a stronger bound.\nFor these the `FromPyObjectOwned` trait was introduced.\nIt is automatically implemented for any type that implements `FromPyObject` and does not borrow from the input.\nIt is intended to be used as a trait bound in these situations.\n\nBefore:\n\n```rust,ignore\nstruct MyVec<T>(Vec<T>);\nimpl<'py, T> FromPyObject<'py> for Vec<T>\nwhere\n    T: FromPyObject<'py>,\n{\n    fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {\n        let mut v = MyVec(Vec::new());\n        for item in obj.try_iter()? {\n            v.0.push(item?.extract::<T>()?);\n        }\n        Ok(v)\n    }\n}\n```\n\nAfter:\n\n```rust\n# use pyo3::prelude::*;\n# #[allow(dead_code)]\n# pub struct MyVec<T>(Vec<T>);\nimpl<'py, T> FromPyObject<'_, 'py> for MyVec<T>\nwhere\n    T: FromPyObjectOwned<'py> // 👈 can only extract owned values, because each `item` below\n                              //    is a temporary short lived owned reference\n{\n    type Error = PyErr;\n\n    fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        let mut v = MyVec(Vec::new());\n        for item in obj.try_iter()? {\n            v.0.push(item?.extract::<T>().map_err(Into::into)?); // `map_err` is needed because `?` uses `From`, not `Into` 🙁\n        }\n        Ok(v)\n    }\n}\n```\n\nThis is very similar to `serde`s [`Deserialize`] and [`DeserializeOwned`] traits, see [the `serde` docs](https://serde.rs/lifetimes.html).\n\n[`Deserialize`]: https://docs.rs/serde/latest/serde/trait.Deserialize.html\n[`DeserializeOwned`]: https://docs.rs/serde/latest/serde/de/trait.DeserializeOwned.html\n</details>\n\n### `.downcast()` and `DowncastError` replaced with `.cast()` and `CastError`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThe `.downcast()` family of functions were only available on `Bound<PyAny>`.\nIn corner cases (particularly related to `.downcast_into()`) this would require use of `.as_any().downcast()` or `.into_any().downcast_into()` chains.\nAdditionally, `DowncastError` produced Python exception messages which are not very Pythonic due to use of Rust type names in the error messages.\n\nThe `.cast()` family of functions are available on all `Bound` and `Borrowed` smart pointers, whatever the type, and have error messages derived from the actual type at runtime.\nThis produces a nicer experience for both PyO3 module authors and consumers.\n\nTo migrate, replace `.downcast()` with `.cast()` and `DowncastError` with `CastError` (and similar with `.downcast_into()` / `DowncastIntoError` etc).\n\n`CastError` requires a Python `type` object (or other \"classinfo\" object compatible with `isinstance()`) as the second object, so in the rare case where `DowncastError` was manually constructed, small adjustments to code may apply.\n</details>\n\n### `PyTypeCheck` is now an `unsafe trait`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nBecause `PyTypeCheck` is the trait used to guard the `.cast()` functions to treat Python objects as specific concrete types, the trait is `unsafe` to implement.\n\nThis should always have been the case, it was an unfortunate omission from its original implementation which is being corrected in this release.\n</details>\n\n## from 0.25.* to 0.26\n\n### Rename of `Python::with_gil`, `Python::allow_threads`, and `pyo3::prepare_freethreaded_python`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThe names for these APIs were created when the global interpreter lock (GIL) was mandatory.\nWith the introduction of free-threading in Python 3.13 this is no longer the case, and the naming has no universal meaning anymore.\nFor this reason, we chose to rename these to more modern terminology introduced in free-threading:\n\n- `Python::with_gil` is now called `Python::attach`, it attaches a Python thread-state to the current thread.\n  In GIL enabled builds there can only be 1 thread attached to the interpreter, in free-threading there can be more.\n- `Python::allow_threads` is now called `Python::detach`, it detaches a previously attached thread-state.\n- `pyo3::prepare_freethreaded_python` is now called `Python::initialize`.\n</details>\n\n### Deprecation of `PyObject` type alias\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThe type alias `PyObject` (aka `Py<PyAny>`) is often confused with the identically named FFI definition `pyo3::ffi::PyObject`.\nFor this reason we are deprecating its usage.\nTo migrate simply replace its usage by the target type `Py<PyAny>`.\n</details>\n\n### Replacement of `GILOnceCell` with `PyOnceLock`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nSimilar to the above renaming of `Python::with_gil` and related APIs, the `GILOnceCell` type was designed for a Python interpreter which was limited by the GIL.\nAside from its name, it allowed for the \"once\" initialization to race because the racing was mediated by the GIL and was extremely unlikely to manifest in practice.\n\nWith the introduction of free-threaded Python the racy initialization behavior is more likely to be problematic and so a new type `PyOnceLock` has been introduced which performs true single-initialization correctly while attached to the Python interpreter.\nIt exposes the same API as `GILOnceCell`, so should be a drop-in replacement with the notable exception that if the racy initialization of `GILOnceCell` was inadvertently relied on (e.g. due to circular references) then the stronger once-ever guarantee of `PyOnceLock` may lead to deadlocking which requires refactoring.\n\nBefore:\n\n```rust,ignore\n# use pyo3::prelude::*;\n# use pyo3::sync::GILOnceCell;\n# use pyo3::types::PyType;\n# fn main() -> PyResult<()> {\n# Python::attach(|py| {\nstatic DECIMAL_TYPE: GILOnceCell<Py<PyType>> = GILOnceCell::new();\nDECIMAL_TYPE.import(py, \"decimal\", \"Decimal\")?;\n# Ok(())\n# })\n# }\n```\n\nAfter:\n\n```rust\n# use pyo3::prelude::*;\n# use pyo3::sync::PyOnceLock;\n# use pyo3::types::PyType;\n# fn main() -> PyResult<()> {\n# Python::attach(|py| {\nstatic DECIMAL_TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\nDECIMAL_TYPE.import(py, \"decimal\", \"Decimal\")?;\n# Ok(())\n# })\n# }\n```\n\n</details>\n\n### Deprecation of `GILProtected`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nAs another cleanup related to concurrency primitives designed for a Python constrained by the GIL, the `GILProtected` type is now deprecated.\nPrefer to use concurrency primitives which are compatible with free-threaded Python, such as [`std::sync::Mutex`](https://doc.rust-lang.org/std/sync/struct.Mutex.html) (in combination with PyO3's [`MutexExt`]({{#PYO3_DOCS_URL}}/pyo3/sync/trait.MutexExt.html) trait).\n\nBefore:\n\n```rust,ignore\n# use pyo3::prelude::*;\n# fn main() {\n# #[cfg(not(Py_GIL_DISABLED))] {\nuse pyo3::sync::GILProtected;\nuse std::cell::RefCell;\n# Python::attach(|py| {\nstatic NUMBERS: GILProtected<RefCell<Vec<i32>>> = GILProtected::new(RefCell::new(Vec::new()));\nPython::attach(|py| {\n    NUMBERS.get(py).borrow_mut().push(42);\n});\n# })\n# }\n# }\n```\n\nAfter:\n\n```rust\n# use pyo3::prelude::*;\nuse pyo3::sync::MutexExt;\nuse std::sync::Mutex;\n# fn main() {\n# Python::attach(|py| {\nstatic NUMBERS: Mutex<Vec<i32>> = Mutex::new(Vec::new());\nPython::attach(|py| {\n    NUMBERS.lock_py_attached(py).expect(\"no poisoning\").push(42);\n});\n# })\n# }\n```\n\n</details>\n\n### `PyMemoryError` now maps to `io::ErrorKind::OutOfMemory` when converted to `io::Error`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPreviously, converting a `PyMemoryError` into a Rust `io::Error` would result in an error with kind `Other`.\nNow, it produces an error with kind `OutOfMemory`.\nSimilarly, converting an `io::Error` with kind `OutOfMemory` back into a Python error would previously yield a generic `PyOSError`.\nNow, it yields a `PyMemoryError`.\n\nThis change makes error conversions more precise and matches the semantics of out-of-memory errors between Python and Rust.\n</details>\n\n## from 0.24.* to 0.25\n\n### `AsPyPointer` removal\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThe `AsPyPointer` trait is mostly a leftover from the now removed gil-refs API.\nThe last remaining uses were the GC API, namely `PyVisit::call`, and identity comparison (`PyAnyMethods::is` and `Py::is`).\n\n`PyVisit::call` has been updated to take `T: Into<Option<&Py<T>>>`, which allows for arguments of type `&Py<T>`, `&Option<Py<T>>` and `Option<&Py<T>>`.\nIt is unlikely any changes are needed here to migrate.\n\n`PyAnyMethods::is`/ `Py::is` has been updated to take `T: AsRef<Py<PyAny>>>`.\nAdditionally `AsRef<Py<PyAny>>>` implementations were added for `Py`, `Bound` and `Borrowed`.\nBecause of the existing `AsRef<Bound<PyAny>> for Bound<T>` implementation this may cause inference issues in non-generic code.\nThis can be easily migrated by switching to `as_any` instead of `as_ref` for these calls.\n</details>\n\n## from 0.23.* to 0.24\n\n<details>\n<summary><small>Click to expand</small></summary>\nThere were no significant changes from 0.23 to 0.24 which required documenting in this guide.\n</details>\n\n## from 0.22.* to 0.23\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPyO3 0.23 is a significant rework of PyO3's internals for two major improvements:\n\n- Support of Python 3.13's new freethreaded build (aka \"3.13t\")\n- Rework of to-Python conversions with a new `IntoPyObject` trait.\n\nThese changes are both substantial and reasonable efforts have been made to allow as much code as possible to continue to work as-is despite the changes.\nThe impacts are likely to be seen in three places when upgrading:\n\n- PyO3's data structures [are now thread-safe](#free-threaded-python-support) instead of reliant on the GIL for synchronization.\n  In particular, `#[pyclass]` types are [now required to be `Sync`](./class/thread-safety.md).\n- The [`IntoPyObject` trait](#new-intopyobject-trait-unifies-to-python-conversions) may need to be implemented for types in your codebase.\n  In most cases this can simply be done with [`#[derive(IntoPyObject)]`](#intopyobject-and-intopyobjectref-derive-macros).\n  There will be many deprecation warnings from the replacement of `IntoPy` and `ToPyObject` traits.\n- There will be many deprecation warnings from the [final removal of the `gil-refs` feature](#gil-refs-feature-removed), which opened up API space for a cleanup and simplification to PyO3's \"Bound\" API.\n\nThe sections below discuss the rationale and details of each change in more depth.\n</details>\n\n### Free-threaded Python Support\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPyO3 0.23 introduces initial support for the new free-threaded build of CPython 3.13, aka \"3.13t\".\n\nBecause this build allows multiple Python threads to operate simultaneously on underlying Rust data, the `#[pyclass]` macro now requires that types it operates on implement `Sync`.\n\nAside from the change to `#[pyclass]`, most features of PyO3 work unchanged, as the changes have been to the internal data structures to make them thread-safe.\nAn example of this is the `GILOnceCell` type, which used the GIL to synchronize single-initialization.\nIt now uses internal locks to guarantee that only one write ever succeeds, however it allows for multiple racing runs of the initialization closure.\nIt may be preferable to instead use `std::sync::OnceLock` in combination with the `pyo3::sync::OnceLockExt` trait which adds `OnceLock::get_or_init_py_attached` for single-initialization where the initialization closure is guaranteed only ever to run once and without deadlocking with the GIL.\n\nFuture PyO3 versions will likely add more traits and data structures to make working with free-threaded Python easier.\n\nSome features are inaccessible on the free-threaded build:\n\n- The `GILProtected` type, which relied on the GIL to expose synchronized access to inner contents\n- `PyList::get_item_unchecked`, which cannot soundly be used due to races between time-of-check and time-of-use\n\nIf you make use of these features then you will need to account for the unavailability of the API in the free-threaded build.\nOne way to handle it is via conditional compilation -- extensions can use `pyo3-build-config` to get access to a `#[cfg(Py_GIL_DISABLED)]` guard.\n\nSee [the guide section on free-threaded Python](free-threading.md) for more details about supporting free-threaded Python in your PyO3 extensions.\n</details>\n\n### New `IntoPyObject` trait unifies to-Python conversions\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPyO3 0.23 introduces a new `IntoPyObject` trait to convert Rust types into Python objects which replaces both `IntoPy` and `ToPyObject`.\nNotable features of this new trait include:\n\n- conversions can now return an error\n- it is designed to work efficiently for both `T` owned types and `&T` references\n- compared to `IntoPy<T>` the generic `T` moved into an associated type, so\n  - there is now only one way to convert a given type\n  - the output type is stronger typed and may return any Python type instead of just `PyAny`\n- byte collections are specialized to convert into `PyBytes` now, see [below](#to-python-conversions-changed-for-byte-collections-vecu8-u8-n-and-smallvecu8-n)\n- `()` (unit) is now only specialized in return position of `#[pyfunction]` and `#[pymethods]` to return `None`, in normal usage it converts into an empty `PyTuple`\n\nAll PyO3 provided types as well as `#[pyclass]`es already implement `IntoPyObject`.\nOther types will need to adapt an implementation of `IntoPyObject` to stay compatible with the Python APIs.\nIn many cases the new [`#[derive(IntoPyObject)]`](#intopyobject-and-intopyobjectref-derive-macros) macro can be used instead of [manual implementations](#intopyobject-manual-implementation).\n\nSince `IntoPyObject::into_pyobject` may return either a `Bound` or `Borrowed`, you may find the [`BoundObject`](conversions/traits.md#boundobject-for-conversions-that-may-be-bound-or-borrowed) trait to be useful to write code that generically handles either type of smart pointer.\n\nTogether with the introduction of `IntoPyObject` the old conversion traits `ToPyObject` and `IntoPy` are deprecated and will be removed in a future PyO3 version.\n\n#### `IntoPyObject` and `IntoPyObjectRef` derive macros\n\nTo implement the new trait you may use the new `IntoPyObject` and `IntoPyObjectRef` derive macros as below.\n\n```rust,no_run\n# use pyo3::prelude::*;\n#[derive(IntoPyObject, IntoPyObjectRef)]\nstruct Struct {\n    count: usize,\n    obj: Py<PyAny>,\n}\n```\n\nThe `IntoPyObjectRef` derive macro derives implementations for references (e.g. for `&Struct` in the example above), which is a replacement for the `ToPyObject` trait.\n\n#### `IntoPyObject` manual implementation\n\nBefore:\n\n```rust,ignore\n# use pyo3::prelude::*;\n# #[allow(dead_code)]\nstruct MyPyObjectWrapper(PyObject);\n\nimpl IntoPy<PyObject> for MyPyObjectWrapper {\n    fn into_py(self, py: Python<'_>) -> PyObject {\n        self.0\n    }\n}\n\nimpl ToPyObject for MyPyObjectWrapper {\n    fn to_object(&self, py: Python<'_>) -> PyObject {\n        self.0.clone_ref(py)\n    }\n}\n```\n\nAfter:\n\n```rust,ignore\n# use pyo3::prelude::*;\n# #[allow(dead_code)]\n# struct MyPyObjectWrapper(PyObject);\n\nimpl<'py> IntoPyObject<'py> for MyPyObjectWrapper {\n    type Target = PyAny; // the Python type\n    type Output = Bound<'py, Self::Target>; // in most cases this will be `Bound`\n    type Error = std::convert::Infallible;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.0.into_bound(py))\n    }\n}\n\n// `ToPyObject` implementations should be converted to implementations on reference types\nimpl<'a, 'py> IntoPyObject<'py> for &'a MyPyObjectWrapper {\n    type Target = PyAny;\n    type Output = Borrowed<'a, 'py, Self::Target>; // `Borrowed` can be used to optimized reference counting\n    type Error = std::convert::Infallible;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.0.bind_borrowed(py))\n    }\n}\n```\n\n</details>\n\n### To-Python conversions changed for byte collections (`Vec<u8>`, `[u8; N]` and `SmallVec<[u8; N]>`)\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nWith the introduction of the `IntoPyObject` trait, PyO3's macros now prefer `IntoPyObject` implementations over `IntoPy<PyObject>` when producing Python values.\nThis applies to `#[pyfunction]` and `#[pymethods]` return values and also fields accessed via `#[pyo3(get)]`.\n\nThis change has an effect on functions and methods returning _byte_ collections like\n\n- `Vec<u8>`\n- `[u8; N]`\n- `SmallVec<[u8; N]>`\n\nIn their new `IntoPyObject` implementation these will now turn into `PyBytes` rather than a `PyList`.\nAll other `T`s are unaffected and still convert into a `PyList`.\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n#[pyfunction]\nfn foo() -> Vec<u8> { // would previously turn into a `PyList`, now `PyBytes`\n    vec![0, 1, 2, 3]\n}\n\n#[pyfunction]\nfn bar() -> Vec<u16> { // unaffected, returns `PyList`\n    vec![0, 1, 2, 3]\n}\n```\n\nIf this conversion is _not_ desired, consider building a list manually using `PyList::new`.\n\nThe following types were previously _only_ implemented for `u8` and now allow other `T`s turn into `PyList`:\n\n- `&[T]`\n- `Cow<[T]>`\n\nThis is purely additional and should just extend the possible return types.\n\n</details>\n\n### `gil-refs` feature removed\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPyO3 0.23 completes the removal of the \"GIL Refs\" API in favour of the new \"Bound\" API introduced in PyO3 0.21.\n\nWith the removal of the old API, many \"Bound\" API functions which had been introduced with `_bound` suffixes no longer need the suffixes as these names have been freed up.\nFor example, `PyTuple::new_bound` is now just `PyTuple::new` (the existing name remains but is deprecated).\n\nBefore:\n\n```rust,ignore\n# #![allow(deprecated)]\n# use pyo3::prelude::*;\n# use pyo3::types::PyTuple;\n# fn main() {\n# Python::attach(|py| {\n// For example, for PyTuple. Many such APIs have been changed.\nlet tup = PyTuple::new_bound(py, [1, 2, 3]);\n# })\n# }\n```\n\nAfter:\n\n```rust\n# use pyo3::prelude::*;\n# use pyo3::types::PyTuple;\n# fn main() {\n# Python::attach(|py| {\n// For example, for PyTuple. Many such APIs have been changed.\nlet tup = PyTuple::new(py, [1, 2, 3]);\n# })\n# }\n```\n\n#### `IntoPyDict` trait adjusted for removal of `gil-refs`\n\nAs part of this API simplification, the `IntoPyDict` trait has had a small breaking change: `IntoPyDict::into_py_dict_bound` method has been renamed to `IntoPyDict::into_py_dict`.\nIt is also now fallible as part of the `IntoPyObject` trait addition.\n\nIf you implemented `IntoPyDict` for your type, you should implement `into_py_dict` instead of `into_py_dict_bound`.\nThe old name is still available for calling but deprecated.\n\nBefore:\n\n```rust,ignore\n# use pyo3::prelude::*;\n# use pyo3::types::{PyDict, IntoPyDict};\n# use std::collections::HashMap;\n\nstruct MyMap<K, V>(HashMap<K, V>);\n\nimpl<K, V> IntoPyDict for MyMap<K, V>\nwhere\n    K: ToPyObject,\n    V: ToPyObject,\n{\n    fn into_py_dict_bound(self, py: Python<'_>) -> Bound<'_, PyDict> {\n        let dict = PyDict::new_bound(py);\n        for (key, value) in self.0 {\n            dict.set_item(key, value)\n                .expect(\"Failed to set_item on dict\");\n        }\n        dict\n    }\n}\n```\n\nAfter:\n\n```rust,no_run\n# use pyo3::prelude::*;\n# use pyo3::types::{PyDict, IntoPyDict};\n# use std::collections::HashMap;\n\n# #[allow(dead_code)]\nstruct MyMap<K, V>(HashMap<K, V>);\n\nimpl<'py, K, V> IntoPyDict<'py> for MyMap<K, V>\nwhere\n    K: IntoPyObject<'py>,\n    V: IntoPyObject<'py>,\n{\n    fn into_py_dict(self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {\n        let dict = PyDict::new(py);\n        for (key, value) in self.0 {\n            dict.set_item(key, value)?;\n        }\n        Ok(dict)\n    }\n}\n```\n\n</details>\n\n## from 0.21.* to 0.22\n\n### Deprecation of `gil-refs` feature continues\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nFollowing the introduction of the \"Bound\" API in PyO3 0.21 and the planned removal of the \"GIL Refs\" API, all functionality related to GIL Refs is now gated behind the `gil-refs` feature and emits a deprecation warning on use.\n\nSee <a href=\"#from-021-to-022\">the 0.21 migration entry</a> for help upgrading.\n</details>\n\n### Deprecation of implicit default for trailing optional arguments\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nWith `pyo3` 0.22 the implicit `None` default for trailing `Option<T>` type argument is deprecated.\nTo migrate, place a `#[pyo3(signature = (...))]` attribute on affected functions or methods and specify the desired behavior.\nThe migration warning specifies the corresponding signature to keep the current behavior.\nWith 0.23 the signature will be required for any function containing `Option<T>` type parameters to prevent accidental and unnoticed changes in behavior.\nWith 0.24 this restriction will be lifted again and `Option<T>` type arguments will be treated as any other argument _without_ special handling.\n\nBefore:\n\n```rust,no_run\n# #![allow(deprecated, dead_code)]\n# use pyo3::prelude::*;\n#[pyfunction]\nfn increment(x: u64, amount: Option<u64>) -> u64 {\n    x + amount.unwrap_or(1)\n}\n```\n\nAfter:\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n#[pyfunction]\n#[pyo3(signature = (x, amount=None))]\nfn increment(x: u64, amount: Option<u64>) -> u64 {\n    x + amount.unwrap_or(1)\n}\n```\n\n</details>\n\n### `Py::clone` is now gated behind the `py-clone` feature\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nIf you rely on `impl<T> Clone for Py<T>` to fulfil trait requirements imposed by existing Rust code written without PyO3-based code in mind, the newly introduced feature `py-clone` must be enabled.\n\nHowever, take care to note that the behaviour is different from previous versions.\nIf `Clone` was called without the GIL being held, we tried to delay the application of these reference count increments until PyO3-based code would re-acquire it.\nThis turned out to be impossible to implement in a sound manner and hence was removed.\nNow, if `Clone` is called without the GIL being held, we panic instead for which calling code might not be prepared.\n\nIt is advised to migrate off the `py-clone` feature.\nThe simplest way to remove dependency on `impl<T> Clone for Py<T>` is to wrap `Py<T>` as `Arc<Py<T>>` and use cloning of the arc.\n\nRelated to this, we also added a `pyo3_disable_reference_pool` conditional compilation flag which removes the infrastructure necessary to apply delayed reference count decrements implied by `impl<T> Drop for Py<T>`.\nThey do not appear to be a soundness hazard as they should lead to memory leaks in the worst case.\nHowever, the global synchronization adds significant overhead to cross the Python-Rust boundary.\nEnabling this feature will remove these costs and make the `Drop` implementation abort the process if called without the GIL being held instead.\n</details>\n\n### Require explicit opt-in for comparison for simple enums\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nWith `pyo3` 0.22 the new `#[pyo3(eq)]` options allows automatic implementation of Python equality using Rust's `PartialEq`.\nPreviously simple enums automatically implemented equality in terms of their discriminants.\nTo make PyO3 more consistent, this automatic equality implementation is deprecated in favour of having opt-ins for all `#[pyclass]` types.\nSimilarly, simple enums supported comparison with integers, which is not covered by Rust's `PartialEq` derive, so has been split out into the `#[pyo3(eq_int)]` attribute.\n\nTo migrate, place a `#[pyo3(eq, eq_int)]` attribute on simple enum classes.\n\nBefore:\n\n```rust,no_run\n# #![allow(deprecated, dead_code)]\n# use pyo3::prelude::*;\n#[pyclass]\nenum SimpleEnum {\n    VariantA,\n    VariantB = 42,\n}\n```\n\nAfter:\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n#[pyclass(eq, eq_int)]\n#[derive(PartialEq)]\nenum SimpleEnum {\n    VariantA,\n    VariantB = 42,\n}\n```\n\n</details>\n\n### `PyType::name` reworked to better match Python `__name__`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThis function previously would try to read directly from Python type objects' C API field (`tp_name`), in which case it would return a `Cow::Borrowed`.\nHowever the contents of `tp_name` don't have well-defined semantics.\n\nInstead `PyType::name()` now returns the equivalent of Python `__name__` and returns `PyResult<Bound<'py, PyString>>`.\n\nThe closest equivalent to PyO3 0.21's version of `PyType::name()` has been introduced as a new function `PyType::fully_qualified_name()`, which is equivalent to `__module__` and `__qualname__` joined as `module.qualname`.\n\nBefore:\n\n```rust,ignore\n# #![allow(deprecated, dead_code)]\n# use pyo3::prelude::*;\n# use pyo3::types::{PyBool};\n# fn main() -> PyResult<()> {\nPython::with_gil(|py| {\n    let bool_type = py.get_type_bound::<PyBool>();\n    let name = bool_type.name()?.into_owned();\n    println!(\"Hello, {}\", name);\n\n    let mut name_upper = bool_type.name()?;\n    name_upper.to_mut().make_ascii_uppercase();\n    println!(\"Hello, {}\", name_upper);\n\n    Ok(())\n})\n# }\n```\n\nAfter:\n\n```rust,ignore\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use pyo3::types::{PyBool};\n# fn main() -> PyResult<()> {\nPython::with_gil(|py| {\n    let bool_type = py.get_type_bound::<PyBool>();\n    let name = bool_type.name()?;\n    println!(\"Hello, {}\", name);\n\n    // (if the full dotted path was desired, switch from `name()` to `fully_qualified_name()`)\n    let mut name_upper = bool_type.fully_qualified_name()?.to_string();\n    name_upper.make_ascii_uppercase();\n    println!(\"Hello, {}\", name_upper);\n\n    Ok(())\n})\n# }\n```\n\n</details>\n\n## from 0.20.* to 0.21\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPyO3 0.21 introduces a new `Bound<'py, T>` smart pointer which replaces the existing \"GIL Refs\" API to interact with Python objects.\nFor example, in PyO3 0.20 the reference `&'py PyAny` would be used to interact with Python objects.\nIn PyO3 0.21 the updated type is `Bound<'py, PyAny>`.\nMaking this change moves Rust ownership semantics out of PyO3's internals and into user code.\nThis change fixes [a known soundness edge case of interaction with gevent](https://github.com/PyO3/pyo3/issues/3668) as well as improves CPU and [memory performance](https://github.com/PyO3/pyo3/issues/1056).\nFor a full history of discussion see .\nFor a full history of discussion see <https://github.com/PyO3/pyo3/issues/3382>.\n\nThe \"GIL Ref\" `&'py PyAny` and similar types such as `&'py PyDict` continue to be available as a deprecated API.\nDue to the advantages of the new API it is advised that all users make the effort to upgrade as soon as possible.\n\nIn addition to the major API type overhaul, PyO3 has needed to make a few small breaking adjustments to other APIs to close correctness and soundness gaps.\n\nThe recommended steps to update to PyO3 0.21 is as follows:\n\n1. Enable the `gil-refs` feature to silence deprecations related to the API change\n2. Fix all other PyO3 0.21 migration steps\n3. Disable the `gil-refs` feature and migrate off the deprecated APIs\n\nThe following sections are laid out in this order.\n</details>\n\n### Enable the `gil-refs` feature\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nTo make the transition for the PyO3 ecosystem away from the GIL Refs API as smooth as possible, in PyO3 0.21 no APIs consuming or producing GIL Refs have been altered.\nInstead, variants using `Bound<T>` smart pointers have been introduced, for example `PyTuple::new_bound` which returns `Bound<PyTuple>` is the replacement form of `PyTuple::new`.\nThe GIL Ref APIs have been deprecated, but to make migration easier it is possible to disable these deprecation warnings by enabling the `gil-refs` feature.\n\n> [!TIP]\n> The one single exception where an existing API was changed in-place is the `pyo3::intern!` macro. Almost all uses of this macro did not need to update code to account it changing to return `&Bound<PyString>` immediately, and adding an `intern_bound!` replacement was perceived as adding more work for users.\n\nIt is recommended that users do this as a first step of updating to PyO3 0.21 so that the deprecation warnings do not get in the way of resolving the rest of the migration steps.\n\nBefore:\n\n```toml\n# Cargo.toml\n[dependencies]\npyo3 = \"0.20\"\n```\n\nAfter:\n\n```toml\n# Cargo.toml\n[dependencies]\npyo3 = { version = \"0.21\", features = [\"gil-refs\"] }\n```\n\n</details>\n\n### `PyTypeInfo` and `PyTryFrom` have been adjusted\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThe `PyTryFrom` trait has aged poorly, its `try_from` method now conflicts with `TryFrom::try_from` in the 2021 edition prelude.\nA lot of its functionality was also duplicated with `PyTypeInfo`.\n\nTo tighten up the PyO3 traits as part of the deprecation of the GIL Refs API the `PyTypeInfo` trait has had a simpler companion `PyTypeCheck`.\nThe methods `PyAny::downcast` and `PyAny::downcast_exact` no longer use `PyTryFrom` as a bound, instead using `PyTypeCheck` and `PyTypeInfo` respectively.\n\nTo migrate, switch all type casts to use `obj.downcast()` instead of `try_from(obj)` (and similar for `downcast_exact`).\n\nBefore:\n\n```rust,ignore\n# #![allow(deprecated)]\n# use pyo3::prelude::*;\n# use pyo3::types::{PyInt, PyList};\n# fn main() -> PyResult<()> {\nPython::with_gil(|py| {\n    let list = PyList::new(py, 0..5);\n    let b = <PyInt as PyTryFrom>::try_from(list.get_item(0).unwrap())?;\n    Ok(())\n})\n# }\n```\n\nAfter:\n\n```rust,ignore\n# use pyo3::prelude::*;\n# use pyo3::types::{PyInt, PyList};\n# fn main() -> PyResult<()> {\nPython::with_gil(|py| {\n    // Note that PyList::new is deprecated for PyList::new_bound as part of the GIL Refs API removal,\n    // see the section below on migration to Bound<T>.\n    #[allow(deprecated)]\n    let list = PyList::new(py, 0..5);\n    let b = list.get_item(0).unwrap().downcast::<PyInt>()?;\n    Ok(())\n})\n# }\n```\n\n</details>\n\n### `Iter(A)NextOutput` are deprecated\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThe `__next__` and `__anext__` magic methods can now return any type convertible into Python objects directly just like all other `#[pymethods]`.\nThe `IterNextOutput` used by `__next__` and `IterANextOutput` used by `__anext__` are subsequently deprecated.\nMost importantly, this change allows returning an awaitable from `__anext__` without non-sensically wrapping it into `Yield` or `Some`.\nOnly the return types `Option<T>` and `Result<Option<T>, E>` are still handled in a special manner where `Some(val)` yields `val` and `None` stops iteration.\n\nStarting with an implementation of a Python iterator using `IterNextOutput`, e.g.\n\n```rust,ignore\nuse pyo3::prelude::*;\nuse pyo3::iter::IterNextOutput;\n\n#[pyclass]\nstruct PyClassIter {\n    count: usize,\n}\n\n#[pymethods]\nimpl PyClassIter {\n    fn __next__(&mut self) -> IterNextOutput<usize, &'static str> {\n        if self.count < 5 {\n            self.count += 1;\n            IterNextOutput::Yield(self.count)\n        } else {\n            IterNextOutput::Return(\"done\")\n        }\n    }\n}\n```\n\nIf returning `\"done\"` via `StopIteration` is not really required, this should be written as\n\n```rust,no_run\nuse pyo3::prelude::*;\n\n#[pyclass]\nstruct PyClassIter {\n    count: usize,\n}\n\n#[pymethods]\nimpl PyClassIter {\n    fn __next__(&mut self) -> Option<usize> {\n        if self.count < 5 {\n            self.count += 1;\n            Some(self.count)\n        } else {\n            None\n        }\n    }\n}\n```\n\nThis form also has additional benefits: It has already worked in previous PyO3 versions, it matches the signature of Rust's [`Iterator` trait](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html) and it allows using a fast path in CPython which completely avoids the cost of raising a `StopIteration` exception.\nNote that using [`Option::transpose`](https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.transpose) and the `Result<Option<T>, E>` variant, this form can also be used to wrap fallible iterators.\n\nAlternatively, the implementation can also be done as it would in Python itself, i.e. by \"raising\" a `StopIteration` exception\n\n```rust,no_run\nuse pyo3::prelude::*;\nuse pyo3::exceptions::PyStopIteration;\n\n#[pyclass]\nstruct PyClassIter {\n    count: usize,\n}\n\n#[pymethods]\nimpl PyClassIter {\n    fn __next__(&mut self) -> PyResult<usize> {\n        if self.count < 5 {\n            self.count += 1;\n            Ok(self.count)\n        } else {\n            Err(PyStopIteration::new_err(\"done\"))\n        }\n    }\n}\n```\n\nFinally, an asynchronous iterator can directly return an awaitable without confusing wrapping\n\n```rust,no_run\nuse pyo3::prelude::*;\n\n#[pyclass]\nstruct PyClassAwaitable {\n    number: usize,\n}\n\n#[pymethods]\nimpl PyClassAwaitable {\n    fn __next__(&self) -> usize {\n        self.number\n    }\n\n    fn __await__(slf: Py<Self>) -> Py<Self> {\n        slf\n    }\n}\n\n#[pyclass]\nstruct PyClassAsyncIter {\n    number: usize,\n}\n\n#[pymethods]\nimpl PyClassAsyncIter {\n    fn __anext__(&mut self) -> PyClassAwaitable {\n        self.number += 1;\n        PyClassAwaitable {\n            number: self.number,\n        }\n    }\n\n    fn __aiter__(slf: Py<Self>) -> Py<Self> {\n        slf\n    }\n}\n```\n\n</details>\n\n### `PyType::name` has been renamed to `PyType::qualname`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\n`PyType::name` has been renamed to `PyType::qualname` to indicate that it does indeed return the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name), matching the `__qualname__` attribute.\nThe newly added `PyType::name` yields the full name including the module name now which corresponds to `__module__.__name__` on the level of attributes.\n</details>\n\n### `PyCell` has been deprecated\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nInteractions with Python objects implemented in Rust no longer need to go though `PyCell<T>`.\nInstead interactions with Python object now consistently go through `Bound<T>` or `Py<T>` independently of whether `T` is native Python object or a `#[pyclass]` implemented in Rust.\nUse `Bound::new` or `Py::new` respectively to create and `Bound::borrow(_mut)` / `Py::borrow(_mut)` to borrow the Rust object.\n</details>\n\n### Migrating from the GIL Refs API to `Bound<T>`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nTo minimise breakage of code using the GIL Refs API, the `Bound<T>` smart pointer has been introduced by adding complements to all functions which accept or return GIL Refs.\nThis allows code to migrate by replacing the deprecated APIs with the new ones.\n\nTo identify what to migrate, temporarily switch off the `gil-refs` feature to see deprecation warnings on [almost](#cases-where-pyo3-cannot-emit-gil-ref-deprecation-warnings) all uses of APIs accepting and producing GIL Refs .\nOver one or more PRs it should be possible to follow the deprecation hints to update code.\nDepending on your development environment, switching off the `gil-refs` feature may introduce [some very targeted breakages](#deactivating-the-gil-refs-feature), so you may need to fixup those first.\n\nFor example, the following APIs have gained updated variants:\n\n- `PyList::new`, `PyTuple::new` and similar constructors have replacements `PyList::new_bound`, `PyTuple::new_bound` etc.\n- `FromPyObject::extract` has a new `FromPyObject::extract_bound` (see the section below)\n- The `PyTypeInfo` trait has had new `_bound` methods added to accept / return `Bound<T>`.\n\nBecause the new `Bound<T>` API brings ownership out of the PyO3 framework and into user code, there are a few places where user code is expected to need to adjust while switching to the new API:\n\n- Code will need to add the occasional `&` to borrow the new smart pointer as `&Bound<T>` to pass these types around (or use `.clone()` at the very small cost of increasing the Python reference count)\n- `Bound<PyList>` and `Bound<PyTuple>` cannot support indexing with `list[0]`, you should use `list.get_item(0)` instead.\n- `Bound<PyTuple>::iter_borrowed` is slightly more efficient than `Bound<PyTuple>::iter`.\n  The default iteration of `Bound<PyTuple>` cannot return borrowed references because Rust does not (yet) have \"lending iterators\".\n  Similarly `Bound<PyTuple>::get_borrowed_item` is more efficient than `Bound<PyTuple>::get_item` for the same reason.\n- `&Bound<T>` does not implement `FromPyObject` (although it might be possible to do this in the future once the GIL Refs API is completely removed).\n  Use `bound_any.downcast::<T>()` instead of `bound_any.extract::<&Bound<T>>()`.\n- `Bound<PyString>::to_str` now borrows from the `Bound<PyString>` rather than from the `'py` lifetime, so code will need to store the smart pointer as a value in some cases where previously `&PyString` was just used as a temporary. (There are some more details relating to this in [the section below](#deactivating-the-gil-refs-feature).)\n- `.extract::<&str>()` now borrows from the source Python object.\n  The simplest way to update is to change to `.extract::<PyBackedStr>()`, which retains ownership of the Python reference.\n  See more information [in the section on deactivating the `gil-refs` feature](#deactivating-the-gil-refs-feature).\n\nTo convert between `&PyAny` and `&Bound<PyAny>` use the `as_borrowed()` method:\n\n```rust,ignore\nlet gil_ref: &PyAny = ...;\nlet bound: &Bound<PyAny> = &gil_ref.as_borrowed();\n```\n\nTo convert between `Py<T>` and `Bound<T>` use the `bind()` / `into_bound()` methods, and `as_unbound()` / `unbind()` to go back from `Bound<T>` to `Py<T>`.\n\n```rust,ignore\nlet obj: Py<PyList> = ...;\nlet bound: &Bound<'py, PyList> = obj.bind(py);\nlet bound: Bound<'py, PyList> = obj.into_bound(py);\n\nlet obj: &Py<PyList> = bound.as_unbound();\nlet obj: Py<PyList> = bound.unbind();\n```\n\n> [!WARNING]\n> Dangling pointer trap 💣\n> \n> Because of the ownership changes, code which uses `.as_ptr()` to convert `&PyAny` and other GIL Refs to a `*mut pyo3_ffi::PyObject` should take care to avoid creating dangling pointers now that `Bound<PyAny>` carries ownership.\n>\n> For example, the following pattern with `Option<&PyAny>` can easily create a dangling pointer when migrating to the `Bound<PyAny>` smart pointer:\n>\n> ```rust,ignore\n> let opt: Option<&PyAny> = ...;\n> let p: *mut ffi::PyObject = opt.map_or(std::ptr::null_mut(), |any| any.as_ptr());\n> ```\n>\n> The correct way to migrate this code is to use `.as_ref()` to avoid dropping the `Bound<PyAny>` in the `map_or` closure:\n>\n> ```rust,ignore\n> let opt: Option<Bound<PyAny>> = ...;\n> let p: *mut ffi::PyObject = opt.as_ref().map_or(std::ptr::null_mut(), Bound::as_ptr);\n> ```\n\n#### Migrating `FromPyObject` implementations\n\n`FromPyObject` has had a new method `extract_bound` which takes `&Bound<'py, PyAny>` as an argument instead of `&PyAny`.\nBoth `extract` and `extract_bound` have been given default implementations in terms of the other, to avoid breaking code immediately on update to 0.21.\n\nAll implementations of `FromPyObject` should be switched from `extract` to `extract_bound`.\n\nBefore:\n\n```rust,ignore\nimpl<'py> FromPyObject<'py> for MyType {\n    fn extract(obj: &'py PyAny) -> PyResult<Self> {\n        /* ... */\n    }\n}\n```\n\nAfter:\n\n```rust,ignore\nimpl<'py> FromPyObject<'py> for MyType {\n    fn extract_bound(obj: &Bound<'py, PyAny>) -> PyResult<Self> {\n        /* ... */\n    }\n}\n```\n\nThe expectation is that in 0.22 `extract_bound` will have the default implementation removed and in 0.23 `extract` will be removed.\n\n#### Cases where PyO3 cannot emit GIL Ref deprecation warnings\n\nDespite a large amount of deprecations warnings produced by PyO3 to aid with the transition from GIL Refs to the Bound API, there are a few cases where PyO3 cannot automatically warn on uses of GIL Refs.\nIt is worth checking for these cases manually after the deprecation warnings have all been addressed:\n\n- Individual implementations of the `FromPyObject` trait cannot be deprecated, so PyO3 cannot warn about uses of code patterns like `.extract<&PyAny>()` which produce a GIL Ref.\n- GIL Refs in `#[pyfunction]` arguments emit a warning, but if the GIL Ref is wrapped inside another container such as `Vec<&PyAny>` then PyO3 cannot warn against this.\n- The `wrap_pyfunction!(function)(py)` deferred argument form of the `wrap_pyfunction` macro taking `py: Python<'py>` produces a GIL Ref, and due to limitations in type inference PyO3 cannot warn against this specific case.\n\n</details>\n\n### Deactivating the `gil-refs` feature\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nAs a final step of migration, deactivating the `gil-refs` feature will set up code for best performance and is intended to set up a forward-compatible API for PyO3 0.22.\n\nAt this point code that needed to manage GIL Ref memory can safely remove uses of `GILPool` (which are constructed by calls to `Python::new_pool` and `Python::with_pool`).\nDeprecation warnings will highlight these cases.\n\nThere is just one case of code that changes upon disabling these features: `FromPyObject` trait implementations for types that borrow directly from the input data cannot be implemented by PyO3 without GIL Refs (while the GIL Refs API is in the process of being removed).\nThe main types affected are `&str`, `Cow<'_, str>`, `&[u8]`, `Cow<'_, u8>`.\n\nTo make PyO3's core functionality continue to work while the GIL Refs API is in the process of being removed, disabling the `gil-refs` feature moves the implementations of `FromPyObject` for `&str`, `Cow<'_, str>`, `&[u8]`, `Cow<'_, u8>` to a new temporary trait `FromPyObjectBound`.\nThis trait is the expected future form of `FromPyObject` and has an additional lifetime `'a` to enable these types to borrow data from Python objects.\n\nPyO3 0.21 has introduced the [`PyBackedStr`]({{#PYO3_DOCS_URL}}/pyo3/pybacked/struct.PyBackedStr.html) and [`PyBackedBytes`]({{#PYO3_DOCS_URL}}/pyo3/pybacked/struct.PyBackedBytes.html) types to help with this case.\nThe easiest way to avoid lifetime challenges from extracting `&str` is to use these.\nFor more complex types like `Vec<&str>`, is now impossible to extract directly from a Python object and `Vec<PyBackedStr>` is the recommended upgrade path.\n\nA key thing to note here is because extracting to these types now ties them to the input lifetime, some extremely common patterns may need to be split into multiple Rust lines.\nFor example, the following snippet of calling `.extract::<&str>()` directly on the result of `.getattr()` needs to be adjusted when deactivating the `gil-refs` feature.\n\nBefore:\n\n```rust,ignore\n# #[cfg(feature = \"gil-refs\")] {\n# use pyo3::prelude::*;\n# use pyo3::types::{PyList, PyType};\n# fn example<'py>(py: Python<'py>) -> PyResult<()> {\n#[allow(deprecated)] // GIL Ref API\nlet obj: &'py PyType = py.get_type::<PyList>();\nlet name: &'py str = obj.getattr(\"__name__\")?.extract()?;\nassert_eq!(name, \"list\");\n# Ok(())\n# }\n# Python::with_gil(example).unwrap();\n# }\n```\n\nAfter:\n\n```rust,ignore\n# #[cfg(any(not(Py_LIMITED_API), Py_3_10))] {\n# use pyo3::prelude::*;\n# use pyo3::types::{PyList, PyType};\n# fn example<'py>(py: Python<'py>) -> PyResult<()> {\nlet obj: Bound<'py, PyType> = py.get_type_bound::<PyList>();\nlet name_obj: Bound<'py, PyAny> = obj.getattr(\"__name__\")?;\n// the lifetime of the data is no longer `'py` but the much shorter\n// lifetime of the `name_obj` smart pointer above\nlet name: &'_ str = name_obj.extract()?;\nassert_eq!(name, \"list\");\n# Ok(())\n# }\n# Python::with_gil(example).unwrap();\n# }\n```\n\nTo avoid needing to worry about lifetimes at all, it is also possible to use the new `PyBackedStr` type, which stores a reference to the Python `str` without a lifetime attachment.\nIn particular, `PyBackedStr` helps for `abi3` builds for Python older than 3.10.\nDue to limitations in the `abi3` CPython API for those older versions, PyO3 cannot offer a `FromPyObjectBound` implementation for `&str` on those versions.\nThe easiest way to migrate for older `abi3` builds is to replace any cases of `.extract::<&str>()` with `.extract::<PyBackedStr>()`.\nAlternatively, use `.extract::<Cow<str>>()`, `.extract::<String>()` to copy the data into Rust.\n\nThe following example uses the same snippet as those just above, but this time the final extracted type is `PyBackedStr`:\n\n```rust,ignore\n# use pyo3::prelude::*;\n# use pyo3::types::{PyList, PyType};\n# fn example<'py>(py: Python<'py>) -> PyResult<()> {\nuse pyo3::pybacked::PyBackedStr;\nlet obj: Bound<'py, PyType> = py.get_type_bound::<PyList>();\nlet name: PyBackedStr = obj.getattr(\"__name__\")?.extract()?;\nassert_eq!(&*name, \"list\");\n# Ok(())\n# }\n# Python::with_gil(example).unwrap();\n```\n\n</details>\n\n## from 0.19.* to 0.20\n\n### Drop support for older technologies\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPyO3 0.20 has increased minimum Rust version to 1.56.\nThis enables use of newer language features and simplifies maintenance of the project.\n</details>\n\n### `PyDict::get_item` now returns a `Result`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\n`PyDict::get_item` in PyO3 0.19 and older was implemented using a Python API which would suppress all exceptions and return `None` in those cases.\nThis included errors in `__hash__` and `__eq__` implementations of the key being looked up.\n\nNewer recommendations by the Python core developers advise against using these APIs which suppress exceptions, instead allowing exceptions to bubble upwards. `PyDict::get_item_with_error` already implemented this recommended behavior, so that API has been renamed to `PyDict::get_item`.\n\nBefore:\n\n```rust,ignore\nuse pyo3::prelude::*;\nuse pyo3::exceptions::PyTypeError;\nuse pyo3::types::{PyDict, IntoPyDict};\n\n# fn main() {\n# let _ =\nPython::with_gil(|py| {\n    let dict: &PyDict = [(\"a\", 1)].into_py_dict(py);\n    // `a` is in the dictionary, with value 1\n    assert!(dict.get_item(\"a\").map_or(Ok(false), |x| x.eq(1))?);\n    // `b` is not in the dictionary\n    assert!(dict.get_item(\"b\").is_none());\n    // `dict` is not hashable, so this fails with a `TypeError`\n    assert!(dict\n        .get_item_with_error(dict)\n        .unwrap_err()\n        .is_instance_of::<PyTypeError>(py));\n});\n# }\n```\n\nAfter:\n\n```rust,ignore\nuse pyo3::prelude::*;\nuse pyo3::exceptions::PyTypeError;\nuse pyo3::types::{PyDict, IntoPyDict};\n\n# fn main() {\n# let _ =\nPython::with_gil(|py| -> PyResult<()> {\n    let dict: &PyDict = [(\"a\", 1)].into_py_dict(py);\n    // `a` is in the dictionary, with value 1\n    assert!(dict.get_item(\"a\")?.map_or(Ok(false), |x| x.eq(1))?);\n    // `b` is not in the dictionary\n    assert!(dict.get_item(\"b\")?.is_none());\n    // `dict` is not hashable, so this fails with a `TypeError`\n    assert!(dict\n        .get_item(dict)\n        .unwrap_err()\n        .is_instance_of::<PyTypeError>(py));\n\n    Ok(())\n});\n# }\n```\n\n</details>\n\n### Required arguments are no longer accepted after optional arguments\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nTrailing `Option<T>` arguments have an automatic default of `None`.\nTo avoid unwanted changes when modifying function signatures, in PyO3 0.18 it was deprecated to have a required argument after an `Option<T>` argument without using `#[pyo3(signature = (...))]` to specify the intended defaults.\nIn PyO3 0.20, this becomes a hard error.\n\nBefore:\n\n```rust,ignore\n#[pyfunction]\nfn x_or_y(x: Option<u64>, y: u64) -> u64 {\n    x.unwrap_or(y)\n}\n```\n\nAfter:\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n\n#[pyfunction]\n#[pyo3(signature = (x, y))] // both x and y have no defaults and are required\nfn x_or_y(x: Option<u64>, y: u64) -> u64 {\n    x.unwrap_or(y)\n}\n```\n\n</details>\n\n### Remove deprecated function forms\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nIn PyO3 0.18 the `#[args]` attribute for `#[pymethods]`, and directly specifying the function signature in `#[pyfunction]`, was deprecated.\nThis functionality has been removed in PyO3 0.20.\n\nBefore:\n\n```rust,ignore\n#[pyfunction]\n#[pyo3(a, b = \"0\", \"/\")]\nfn add(a: u64, b: u64) -> u64 {\n    a + b\n}\n```\n\nAfter:\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n\n#[pyfunction]\n#[pyo3(signature = (a, b=0, /))]\nfn add(a: u64, b: u64) -> u64 {\n    a + b\n}\n```\n\n</details>\n\n### `IntoPyPointer` trait removed\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThe trait `IntoPyPointer`, which provided the `into_ptr` method on many types, has been removed. `into_ptr` is now available as an inherent method on all types that previously implemented this trait.\n</details>\n\n### `AsPyPointer` now `unsafe` trait\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThe trait `AsPyPointer` is now `unsafe trait`, meaning any external implementation of it must be marked as `unsafe impl`, and ensure that they uphold the invariant of returning valid pointers.\n</details>\n\n## from 0.18.* to 0.19\n\n### Access to `Python` inside `__traverse__` implementations are now forbidden\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nDuring `__traverse__` implementations for Python's Garbage Collection it is forbidden to do anything other than visit the members of the `#[pyclass]` being traversed.\nThis means making Python function calls or other API calls are forbidden.\n\nPrevious versions of PyO3 would allow access to `Python` (e.g. via `Python::with_gil`), which could cause the Python interpreter to crash or otherwise confuse the garbage collection algorithm.\n\nAttempts to acquire the GIL will now panic.\nSee [#3165](https://github.com/PyO3/pyo3/issues/3165) for more detail.\n\n```rust,ignore\n# use pyo3::prelude::*;\n\n#[pyclass]\nstruct SomeClass {}\n\nimpl SomeClass {\n    fn __traverse__(&self, pyo3::class::gc::PyVisit<'_>) -> Result<(), pyo3::class::gc::PyTraverseError>` {\n        Python::with_gil(|| { /*...*/ })  // ERROR: this will panic\n    }\n}\n```\n\n</details>\n\n### Smarter `anyhow::Error` / `eyre::Report` conversion when inner error is \"simple\" `PyErr`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nWhen converting from `anyhow::Error` or `eyre::Report` to `PyErr`, if the inner error is a \"simple\" `PyErr` (with no source error), then the inner error will be used directly as the `PyErr` instead of wrapping it in a new `PyRuntimeError` with the original information converted into a string.\n\n```rust,ignore\n# #[cfg(feature = \"anyhow\")]\n# #[allow(dead_code)]\n# mod anyhow_only {\n# use pyo3::prelude::*;\n# use pyo3::exceptions::PyValueError;\n#[pyfunction]\nfn raise_err() -> anyhow::Result<()> {\n    Err(PyValueError::new_err(\"original error message\").into())\n}\n\nfn main() {\n    Python::with_gil(|py| {\n        let rs_func = wrap_pyfunction!(raise_err, py).unwrap();\n        pyo3::py_run!(\n            py,\n            rs_func,\n            r\"\n        try:\n            rs_func()\n        except Exception as e:\n            print(repr(e))\n        \"\n        );\n    })\n}\n# }\n```\n\nBefore, the above code would have printed `RuntimeError('ValueError: original error message')`, which might be confusing.\n\nAfter, the same code will print `ValueError: original error message`, which is more straightforward.\n\nHowever, if the `anyhow::Error` or `eyre::Report` has a source, then the original exception will still be wrapped in a `PyRuntimeError`.\n</details>\n\n### The deprecated `Python::acquire_gil` was removed and `Python::with_gil` must be used instead\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nWhile the API provided by [`Python::acquire_gil`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html#method.acquire_gil) seems convenient, it is somewhat brittle as the design of the [`Python`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html) token relies on proper nesting and panics if not used correctly, e.g.\n\n```rust,ignore\n# #![allow(dead_code, deprecated)]\n# use pyo3::prelude::*;\n\n#[pyclass]\nstruct SomeClass {}\n\nstruct ObjectAndGuard {\n    object: Py<SomeClass>,\n    guard: GILGuard,\n}\n\nimpl ObjectAndGuard {\n    fn new() -> Self {\n        let guard = Python::acquire_gil();\n        let object = Py::new(guard.python(), SomeClass {}).unwrap();\n\n        Self { object, guard }\n    }\n}\n\nlet first = ObjectAndGuard::new();\nlet second = ObjectAndGuard::new();\n// Panics because the guard within `second` is still alive.\ndrop(first);\ndrop(second);\n```\n\nThe replacement is [`Python::with_gil`](https://docs.rs/pyo3/0.18.3/pyo3/marker/struct.Python.html#method.with_gil) which is more cumbersome but enforces the proper nesting by design, e.g.\n\n```rust,ignore\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n\n#[pyclass]\nstruct SomeClass {}\n\nstruct Object {\n    object: Py<SomeClass>,\n}\n\nimpl Object {\n    fn new(py: Python<'_>) -> Self {\n        let object = Py::new(py, SomeClass {}).unwrap();\n\n        Self { object }\n    }\n}\n\n// It either forces us to release the GIL before acquiring it again.\nlet first = Python::with_gil(|py| Object::new(py));\nlet second = Python::with_gil(|py| Object::new(py));\ndrop(first);\ndrop(second);\n\n// Or it ensures releasing the inner lock before the outer one.\nPython::with_gil(|py| {\n    let first = Object::new(py);\n    let second = Python::with_gil(|py| Object::new(py));\n    drop(first);\n    drop(second);\n});\n```\n\nFurthermore, `Python::acquire_gil` provides ownership of a `GILGuard` which can be freely stored and passed around.\nThis is usually not helpful as it may keep the lock held for a long time thereby blocking progress in other parts of the program.\nDue to the generative lifetime attached to the Python token supplied by `Python::with_gil`, the problem is avoided as the Python token can only be passed down the call chain.\nOften, this issue can also be avoided entirely as any GIL-bound reference `&'py PyAny` implies access to a Python token `Python<'py>` via the [`PyAny::py`](https://docs.rs/pyo3/0.22.5/pyo3/types/struct.PyAny.html#method.py) method.\n</details>\n\n## from 0.17.* to 0.18\n\n### Required arguments after `Option<_>` arguments will no longer be automatically inferred\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nIn `#[pyfunction]` and `#[pymethods]`, if a \"required\" function input such as `i32` came after an `Option<_>` input, then the `Option<_>` would be implicitly treated as required. (All trailing `Option<_>` arguments were treated as optional with a default value of `None`).\n\nStarting with PyO3 0.18, this is deprecated and a future PyO3 version will require a [`#[pyo3(signature = (...))]` option](./function/signature.md) to explicitly declare the programmer's intention.\n\nBefore, x in the below example would be required to be passed from Python code:\n\n```rust,compile_fail,ignore\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n\n#[pyfunction]\nfn required_argument_after_option(x: Option<i32>, y: i32) {}\n```\n\nAfter, specify the intended Python signature explicitly:\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n\n// If x really was intended to be required\n#[pyfunction(signature = (x, y))]\nfn required_argument_after_option_a(x: Option<i32>, y: i32) {}\n\n// If x was intended to be optional, y needs a default too\n#[pyfunction(signature = (x=None, y=0))]\nfn required_argument_after_option_b(x: Option<i32>, y: i32) {}\n```\n\n</details>\n\n### `__text_signature__` is now automatically generated for `#[pyfunction]` and `#[pymethods]`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThe [`#[pyo3(text_signature = \"...\")]` option](./function/signature.md#making-the-function-signature-available-to-python) was previously the only supported way to set the `__text_signature__` attribute on generated Python functions.\n\nPyO3 is now able to automatically populate `__text_signature__` for all functions automatically based on their Rust signature (or the [new `#[pyo3(signature = (...))]` option](./function/signature.md)).\nThese automatically-generated `__text_signature__` values will currently only render `...` for all default values.\nMany `#[pyo3(text_signature = \"...\")]` options can be removed from functions when updating to PyO3 0.18, however in cases with default values a manual implementation may still be preferred for now.\n\nAs examples:\n\n```rust\n# use pyo3::prelude::*;\n\n// The `text_signature` option here is no longer necessary, as PyO3 will automatically\n// generate exactly the same value.\n#[pyfunction(text_signature = \"(a, b, c)\")]\nfn simple_function(a: i32, b: i32, c: i32) {}\n\n// The `text_signature` still provides value here as of PyO3 0.18, because the automatically\n// generated signature would be \"(a, b=..., c=...)\".\n#[pyfunction(signature = (a, b = 1, c = 2), text_signature = \"(a, b=1, c=2)\")]\nfn function_with_defaults(a: i32, b: i32, c: i32) {}\n\n# fn main() {\n#     Python::attach(|py| {\n#         let simple = wrap_pyfunction!(simple_function, py).unwrap();\n#         assert_eq!(simple.getattr(\"__text_signature__\").unwrap().to_string(), \"(a, b, c)\");\n#         let defaulted = wrap_pyfunction!(function_with_defaults, py).unwrap();\n#         assert_eq!(defaulted.getattr(\"__text_signature__\").unwrap().to_string(), \"(a, b=1, c=2)\");\n#     })\n# }\n```\n\n</details>\n\n## from 0.16.* to 0.17\n\n### Type checks have been changed for `PyMapping` and `PySequence` types\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPreviously the type checks for `PyMapping` and `PySequence` (implemented in `PyTryFrom`) used the Python C-API functions `PyMapping_Check` and `PySequence_Check`.\nUnfortunately these functions are not sufficient for distinguishing such types, leading to inconsistent behavior (see [pyo3/pyo3#2072](https://github.com/PyO3/pyo3/issues/2072)).\n\nPyO3 0.17 changes these downcast checks to explicitly test if the type is a subclass of the corresponding abstract base class `collections.abc.Mapping` or `collections.abc.Sequence`.\nNote this requires calling into Python, which may incur a performance penalty over the previous method.\nIf this performance penalty is a problem, you may be able to perform your own checks and use `try_from_unchecked` (unsafe).\n\nAnother side-effect is that a pyclass defined in Rust with PyO3 will need to be _registered_ with the corresponding Python abstract base class for downcasting to succeed.\n`PySequence::register` and `PyMapping:register` have been added to make it easy to do this from Rust code.\nThese are equivalent to calling `collections.abc.Mapping.register(MappingPyClass)` or `collections.abc.Sequence.register(SequencePyClass)` from Python.\n\nFor example, for a mapping class defined in Rust:\n\n```rust,compile_fail\nuse pyo3::prelude::*;\nuse std::collections::HashMap;\n\n#[pyclass(mapping)]\nstruct Mapping {\n    index: HashMap<String, usize>,\n}\n\n#[pymethods]\nimpl Mapping {\n    #[new]\n    fn new(elements: Option<&PyList>) -> PyResult<Self> {\n    // ...\n    // truncated implementation of this mapping pyclass - basically a wrapper around a HashMap\n}\n```\n\nYou must register the class with `collections.abc.Mapping` before the downcast will work:\n\n```rust,compile_fail\nlet m = Py::new(py, Mapping { index }).unwrap();\nassert!(m.as_ref(py).downcast::<PyMapping>().is_err());\nPyMapping::register::<Mapping>(py).unwrap();\nassert!(m.as_ref(py).downcast::<PyMapping>().is_ok());\n```\n\nNote that this requirement may go away in the future when a pyclass is able to inherit from the abstract base class directly (see [pyo3/pyo3#991](https://github.com/PyO3/pyo3/issues/991)).\n</details>\n\n### The `multiple-pymethods` feature now requires Rust 1.62\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nDue to limitations in the `inventory` crate which the `multiple-pymethods` feature depends on, this feature now requires Rust 1.62.\nFor more information see [dtolnay/inventory#32](https://github.com/dtolnay/inventory/issues/32).\n</details>\n\n### Added `impl IntoPy<Py<PyString>> for &str`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThis may cause inference errors.\n\nBefore:\n\n```rust,compile_fail\n# use pyo3::prelude::*;\n#\n# fn main() {\nPython::with_gil(|py| {\n    // Cannot infer either `Py<PyAny>` or `Py<PyString>`\n    let _test = \"test\".into_py(py);\n});\n# }\n```\n\nAfter, some type annotations may be necessary:\n\n```rust,ignore\n# #![allow(deprecated)]\n# use pyo3::prelude::*;\n#\n# fn main() {\nPython::with_gil(|py| {\n    let _test: Py<PyAny> = \"test\".into_py(py);\n});\n# }\n```\n\n</details>\n\n### The `pyproto` feature is now disabled by default\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nIn preparation for removing the deprecated `#[pyproto]` attribute macro in a future PyO3 version, it is now gated behind an opt-in feature flag.\nThis also gives a slight saving to compile times for code which does not use the deprecated macro.\n</details>\n\n### `PyTypeObject` trait has been deprecated\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThe `PyTypeObject` trait already was near-useless; almost all functionality was already on the `PyTypeInfo` trait, which `PyTypeObject` had a blanket implementation based upon.\nIn PyO3 0.17 the final method, `PyTypeObject::type_object` was moved to `PyTypeInfo::type_object`.\n\nTo migrate, update trait bounds and imports from `PyTypeObject` to `PyTypeInfo`.\n\nBefore:\n\n```rust,ignore\nuse pyo3::Python;\nuse pyo3::type_object::PyTypeObject;\nuse pyo3::types::PyType;\n\nfn get_type_object<T: PyTypeObject>(py: Python<'_>) -> &PyType {\n    T::type_object(py)\n}\n```\n\nAfter\n\n```rust,ignore\nuse pyo3::{Python, PyTypeInfo};\nuse pyo3::types::PyType;\n\nfn get_type_object<T: PyTypeInfo>(py: Python<'_>) -> &PyType {\n    T::type_object(py)\n}\n\n# Python::with_gil(|py| { get_type_object::<pyo3::types::PyList>(py); });\n```\n\n</details>\n\n### `impl<T, const N: usize> IntoPy<PyObject> for [T; N]` now requires `T: IntoPy` rather than `T: ToPyObject`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nIf this leads to errors, simply implement `IntoPy`.\nBecause pyclasses already implement `IntoPy`, you probably don't need to worry about this.\n</details>\n\n### Each `#[pymodule]` can now only be initialized once per process\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nTo make PyO3 modules sound in the presence of Python sub-interpreters, for now it has been necessary to explicitly disable the ability to initialize a `#[pymodule]` more than once in the same process.\nAttempting to do this will now raise an `ImportError`.\n</details>\n\n## from 0.15.* to 0.16\n\n### Drop support for older technologies\n\n<!-- rumdl-enable MD024 -->\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPyO3 0.16 has increased minimum Rust version to 1.48 and minimum Python version to 3.7.\nThis enables use of newer language features (enabling some of the other additions in 0.16) and simplifies maintenance of the project.\n</details>\n\n### `#[pyproto]` has been deprecated\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nIn PyO3 0.15, the `#[pymethods]` attribute macro gained support for implementing \"magic methods\" such as `__str__` (aka \"dunder\" methods).\nThis implementation was not quite finalized at the time, with a few edge cases to be decided upon.\nThe existing `#[pyproto]` attribute macro was left untouched, because it covered these edge cases.\n\nIn PyO3 0.16, the `#[pymethods]` implementation has been completed and is now the preferred way to implement magic methods.\nTo allow the PyO3 project to move forward, `#[pyproto]` has been deprecated (with expected removal in PyO3 0.18).\n\nMigration from `#[pyproto]` to `#[pymethods]` is straightforward; copying the existing methods directly from the `#[pyproto]` trait implementation is all that is needed in most cases.\n\nBefore:\n\n```rust,compile_fail\nuse pyo3::prelude::*;\nuse pyo3::class::{PyObjectProtocol, PyIterProtocol};\nuse pyo3::types::PyString;\n\n#[pyclass]\nstruct MyClass {}\n\n#[pyproto]\nimpl PyObjectProtocol for MyClass {\n    fn __str__(&self) -> &'static [u8] {\n        b\"hello, world\"\n    }\n}\n\n#[pyproto]\nimpl PyIterProtocol for MyClass {\n    fn __iter__(slf: PyRef<self>) -> PyResult<&PyAny> {\n        PyString::new(slf.py(), \"hello, world\").iter()\n    }\n}\n```\n\nAfter\n\n```rust,compile_fail\nuse pyo3::prelude::*;\nuse pyo3::types::PyString;\n\n#[pyclass]\nstruct MyClass {}\n\n#[pymethods]\nimpl MyClass {\n    fn __str__(&self) -> &'static [u8] {\n        b\"hello, world\"\n    }\n\n    fn __iter__(slf: PyRef<self>) -> PyResult<&PyAny> {\n        PyString::new(slf.py(), \"hello, world\").iter()\n    }\n}\n```\n\n</details>\n\n### Removed `PartialEq` for object wrappers\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThe Python object wrappers `Py` and `PyAny` had implementations of `PartialEq` so that `object_a == object_b` would compare the Python objects for pointer equality, which corresponds to the `is` operator, not the `==` operator in Python.\nThis has been removed in favor of a new method: use `object_a.is(object_b)`.\nThis also has the advantage of not requiring the same wrapper type for `object_a` and `object_b`; you can now directly compare a `Py<T>` with a `&PyAny` without having to convert.\n\nTo check for Python object equality (the Python `==` operator), use the new method `eq()`.\n</details>\n\n### Container magic methods now match Python behavior\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nIn PyO3 0.15, `__getitem__`, `__setitem__` and `__delitem__` in `#[pymethods]` would generate only the _mapping_ implementation for a `#[pyclass]`.\nTo match the Python behavior, these methods now generate both the _mapping_ **and** _sequence_ implementations.\n\nThis means that classes implementing these `#[pymethods]` will now also be treated as sequences, same as a Python `class` would be.\nSmall differences in behavior may result:\n\n- PyO3 will allow instances of these classes to be cast to `PySequence` as well as `PyMapping`.\n- Python will provide a default implementation of `__iter__` (if the class did not have one) which repeatedly calls `__getitem__` with integers (starting at 0) until an `IndexError` is raised.\n\nTo explain this in detail, consider the following Python class:\n\n```python\nclass ExampleContainer:\n\n    def __len__(self):\n        return 5\n\n    def __getitem__(self, idx: int) -> int:\n        if idx < 0 or idx > 5:\n            raise IndexError()\n        return idx\n```\n\nThis class implements a Python [sequence](https://docs.python.org/3/glossary.html#term-sequence).\n\nThe `__len__` and `__getitem__` methods are also used to implement a Python [mapping](https://docs.python.org/3/glossary.html#term-mapping).\nIn the Python C-API, these methods are not shared: the sequence `__len__` and `__getitem__` are defined by the `sq_length` and `sq_item` slots, and the mapping equivalents are `mp_length` and `mp_subscript`.\nThere are similar distinctions for `__setitem__` and `__delitem__`.\n\nBecause there is no such distinction from Python, implementing these methods will fill the mapping and sequence slots simultaneously.\nA Python class with `__len__` implemented, for example, will have both the `sq_length` and `mp_length` slots filled.\n\nThe PyO3 behavior in 0.16 has been changed to be closer to this Python behavior by default.\n</details>\n\n### `wrap_pymodule!` and `wrap_pyfunction!` now respect privacy correctly\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPrior to PyO3 0.16 the `wrap_pymodule!` and `wrap_pyfunction!` macros could use modules and functions whose defining `fn` was not reachable according Rust privacy rules.\n\nFor example, the following code was legal before 0.16, but in 0.16 is rejected because the `wrap_pymodule!` macro cannot access the `private_submodule` function:\n\n```rust,compile_fail\nmod foo {\n    use pyo3::prelude::*;\n\n    #[pymodule]\n    fn private_submodule(_py: Python<'_>, m: &PyModule) -> PyResult<()> {\n        Ok(())\n    }\n}\n\nuse pyo3::prelude::*;\nuse foo::*;\n\n#[pymodule]\nfn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {\n    m.add_wrapped(wrap_pymodule!(private_submodule))?;\n    Ok(())\n}\n```\n\nTo fix it, make the private submodule visible, e.g. with `pub` or `pub(crate)`.\n\n```rust,ignore\nmod foo {\n    use pyo3::prelude::*;\n\n    #[pymodule]\n    pub(crate) fn private_submodule(_py: Python<'_>, m: &PyModule) -> PyResult<()> {\n        Ok(())\n    }\n}\n\nuse pyo3::prelude::*;\nuse pyo3::wrap_pymodule;\nuse foo::*;\n\n#[pymodule]\nfn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {\n    m.add_wrapped(wrap_pymodule!(private_submodule))?;\n    Ok(())\n}\n```\n\n</details>\n\n## from 0.14.* to 0.15\n\n### Changes in sequence indexing\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nFor all types that take sequence indices (`PyList`, `PyTuple` and `PySequence`), the API has been made consistent to only take `usize` indices, for consistency with Rust's indexing conventions.\nNegative indices, which were only sporadically supported even in APIs that took `isize`, now aren't supported anywhere.\n\nFurther, the `get_item` methods now always return a `PyResult` instead of panicking on invalid indices.\nThe `Index` trait has been implemented instead, and provides the same panic behavior as on Rust vectors.\n\nNote that _slice_ indices (accepted by `PySequence::get_slice` and other) still inherit the Python behavior of clamping the indices to the actual length, and not panicking/returning an error on out of range indices.\n\nAn additional advantage of using Rust's indexing conventions for these types is that these types can now also support Rust's indexing operators as part of a consistent API:\n\n```rust,ignore\n#![allow(deprecated)]\nuse pyo3::{Python, types::PyList};\n\nPython::with_gil(|py| {\n    let list = PyList::new(py, &[1, 2, 3]);\n    assert_eq!(list[0..2].to_string(), \"[1, 2]\");\n});\n```\n\n</details>\n\n## from 0.13.* to 0.14\n\n### `auto-initialize` feature is now opt-in\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nFor projects embedding Python in Rust, PyO3 no longer automatically initializes a Python interpreter on the first call to `Python::with_gil` (or `Python::acquire_gil`) unless the [`auto-initialize` feature](features.md#auto-initialize) is enabled.\n</details>\n\n### New `multiple-pymethods` feature\n\n<details>\n<summary><small>Click to expand</small></summary>\n\n`#[pymethods]` have been reworked with a simpler default implementation which removes the dependency on the `inventory` crate.\nThis reduces dependencies and compile times for the majority of users.\n\nThe limitation of the new default implementation is that it cannot support multiple `#[pymethods]` blocks for the same `#[pyclass]`.\nIf you need this functionality, you must enable the `multiple-pymethods` feature which will switch `#[pymethods]` to the inventory-based implementation.\n</details>\n\n### Deprecated `#[pyproto]` methods\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nSome protocol (aka `__dunder__`) methods such as `__bytes__` and `__format__` have been possible to implement two ways in PyO3 for some time: via a `#[pyproto]` (e.g. `PyObjectProtocol` for the methods listed here), or by writing them directly in `#[pymethods]`.\nThis is only true for a handful of the `#[pyproto]` methods (for technical reasons to do with the way PyO3 currently interacts with the Python C-API).\n\nIn the interest of having only one way to do things, the `#[pyproto]` forms of these methods have been deprecated.\n\nTo migrate just move the affected methods from a `#[pyproto]` to a `#[pymethods]` block.\n\nBefore:\n\n```rust,compile_fail\nuse pyo3::prelude::*;\nuse pyo3::class::basic::PyObjectProtocol;\n\n#[pyclass]\nstruct MyClass {}\n\n#[pyproto]\nimpl PyObjectProtocol for MyClass {\n    fn __bytes__(&self) -> &'static [u8] {\n        b\"hello, world\"\n    }\n}\n```\n\nAfter:\n\n```rust,no_run\nuse pyo3::prelude::*;\n\n#[pyclass]\nstruct MyClass {}\n\n#[pymethods]\nimpl MyClass {\n    fn __bytes__(&self) -> &'static [u8] {\n        b\"hello, world\"\n    }\n}\n```\n\n</details>\n\n## from 0.12.* to 0.13\n\n### Minimum Rust version increased to Rust 1.45\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPyO3 `0.13` makes use of new Rust language features stabilized between Rust 1.40 and Rust 1.45.\nIf you are using a Rust compiler older than Rust 1.45, you will need to update your toolchain to be able to continue using PyO3.\n</details>\n\n### Runtime changes to support the CPython limited API\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nIn PyO3 `0.13` support was added for compiling against the CPython limited API.\nThis had a number of implications for _all_ PyO3 users, described here.\n\nThe largest of these is that all types created from PyO3 are what CPython calls \"heap\" types.\nThe specific implications of this are:\n\n- If you wish to subclass one of these types _from Rust_ you must mark it `#[pyclass(subclass)]`, as you would if you wished to allow subclassing it from Python code.\n- Type objects are now mutable - Python code can set attributes on them.\n- `__module__` on types without `#[pyclass(module=\"mymodule\")]` no longer returns `builtins`, it now raises `AttributeError`.\n</details>\n\n## from 0.11.* to 0.12\n\n### `PyErr` has been reworked\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nIn PyO3 `0.12` the `PyErr` type has been re-implemented to be significantly more compatible with the standard Rust error handling ecosystem.\nSpecifically `PyErr` now implements `Error + Send + Sync`, which are the standard traits used for error types.\n\nWhile this has necessitated the removal of a number of APIs, the resulting `PyErr` type should now be much more easier to work with.\nThe following sections list the changes in detail and how to migrate to the new APIs.\n</details>\n\n#### `PyErr::new` and `PyErr::from_type` now require `Send + Sync` for their argument\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nFor most uses no change will be needed.\nIf you are trying to construct `PyErr` from a value that is not `Send + Sync`, you will need to first create the Python object and then use `PyErr::from_instance`.\n\nSimilarly, any types which implemented `PyErrArguments` will now need to be `Send + Sync`.\n</details>\n\n#### `PyErr`'s contents are now private\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nIt is no longer possible to access the fields `.ptype`, `.pvalue` and `.ptraceback` of a `PyErr`.\nYou should instead now use the new methods `PyErr::ptype`, `PyErr::pvalue` and `PyErr::ptraceback`.\n</details>\n\n#### `PyErrValue` and `PyErr::from_value` have been removed\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nAs these were part the internals of `PyErr` which have been reworked, these APIs no longer exist.\n\nIf you used this API, it is recommended to use `PyException::new_err` (see [the section on Exception types](#exception-types-have-been-reworked)).\n</details>\n\n#### `Into<PyResult<T>>` for `PyErr` has been removed\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThis implementation was redundant.\nJust construct the `Result::Err` variant directly.\n\nBefore:\n\n```rust,compile_fail\nlet result: PyResult<()> = PyErr::new::<TypeError, _>(\"error message\").into();\n```\n\nAfter (also using the new reworked exception types; see the following section):\n\n```rust,no_run\n# use pyo3::{PyResult, exceptions::PyTypeError};\nlet result: PyResult<()> = Err(PyTypeError::new_err(\"error message\"));\n```\n\n</details>\n\n### Exception types have been reworked\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPreviously exception types were zero-sized marker types purely used to construct `PyErr`.\nIn PyO3 0.12, these types have been replaced with full definitions and are usable in the same way as `PyAny`, `PyDict` etc.\nThis makes it possible to interact with Python exception objects.\n\nThe new types also have names starting with the \"Py\" prefix.\nFor example, before:\n\n```rust,ignore\nlet err: PyErr = TypeError::py_err(\"error message\");\n```\n\nAfter:\n\n```rust,ignore\n# use pyo3::{PyErr, PyResult, Python, type_object::PyTypeObject};\n# use pyo3::exceptions::{PyBaseException, PyTypeError};\n# Python::with_gil(|py| -> PyResult<()> {\nlet err: PyErr = PyTypeError::new_err(\"error message\");\n\n// Uses Display for PyErr, new for PyO3 0.12\nassert_eq!(err.to_string(), \"TypeError: error message\");\n\n// Now possible to interact with exception instances, new for PyO3 0.12\nlet instance: &PyBaseException = err.instance(py);\nassert_eq!(\n    instance.getattr(\"__class__\")?,\n    PyTypeError::type_object(py).as_ref()\n);\n# Ok(())\n# }).unwrap();\n```\n\n</details>\n\n### `FromPy` has been removed\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nTo simplify the PyO3 conversion traits, the `FromPy` trait has been removed.\nPreviously there were two ways to define the to-Python conversion for a type: `FromPy<T> for PyObject` and `IntoPy<PyObject> for T`.\n\nNow there is only one way to define the conversion, `IntoPy`, so downstream crates may need to adjust accordingly.\n\nBefore:\n\n```rust,compile_fail\n# use pyo3::prelude::*;\nstruct MyPyObjectWrapper(PyObject);\n\nimpl FromPy<MyPyObjectWrapper> for PyObject {\n    fn from_py(other: MyPyObjectWrapper, _py: Python<'_>) -> Self {\n        other.0\n    }\n}\n```\n\nAfter\n\n```rust,ignore\n# use pyo3::prelude::*;\n# #[allow(dead_code)]\nstruct MyPyObjectWrapper(PyObject);\n\n# #[allow(deprecated)]\nimpl IntoPy<PyObject> for MyPyObjectWrapper {\n    fn into_py(self, _py: Python<'_>) -> PyObject {\n        self.0\n    }\n}\n```\n\nSimilarly, code which was using the `FromPy` trait can be trivially rewritten to use `IntoPy`.\n\nBefore:\n\n```rust,compile_fail\n# use pyo3::prelude::*;\n# Python::with_gil(|py| {\nlet obj = PyObject::from_py(1.234, py);\n# })\n```\n\nAfter:\n\n```rust,ignore\n# #![allow(deprecated)]\n# use pyo3::prelude::*;\n# Python::with_gil(|py| {\nlet obj: PyObject = 1.234.into_py(py);\n# })\n```\n\n</details>\n\n### `PyObject` is now a type alias of `Py<PyAny>`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nThis should change very little from a usage perspective.\nIf you implemented traits for both `PyObject` and `Py<T>`, you may find you can just remove the `PyObject` implementation.\n</details>\n\n### `AsPyRef` has been removed\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nAs `PyObject` has been changed to be just a type alias, the only remaining implementor of `AsPyRef` was `Py<T>`.\nThis removed the need for a trait, so the `AsPyRef::as_ref` method has been moved to `Py::as_ref`.\n\nThis should require no code changes except removing `use pyo3::AsPyRef` for code which did not use `pyo3::prelude::*`.\n\nBefore:\n\n```rust,ignore\nuse pyo3::{AsPyRef, Py, types::PyList};\n# pyo3::Python::with_gil(|py| {\nlet list_py: Py<PyList> = PyList::empty(py).into();\nlet list_ref: &PyList = list_py.as_ref(py);\n# })\n```\n\nAfter:\n\n```rust,ignore\nuse pyo3::{Py, types::PyList};\n# pyo3::Python::with_gil(|py| {\nlet list_py: Py<PyList> = PyList::empty(py).into();\nlet list_ref: &PyList = list_py.as_ref(py);\n# })\n```\n\n</details>\n\n## from 0.10.* to 0.11\n\n### Stable Rust\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPyO3 now supports the stable Rust toolchain.\nThe minimum required version is 1.39.0.\n</details>\n\n### `#[pyclass]` structs must now be `Send` or `unsendable`\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nBecause `#[pyclass]` structs can be sent between threads by the Python interpreter, they must implement `Send` or declared as `unsendable` (by `#[pyclass(unsendable)]`).\nNote that `unsendable` is added in PyO3 `0.11.1` and `Send` is always required in PyO3 `0.11.0`.\n\nThis may \"break\" some code which previously was accepted, even though it could be unsound.\nThere can be two fixes:\n\n1. If you think that your `#[pyclass]` actually must be `Send`able, then let's implement `Send`.\n   A common, safer way is using thread-safe types.\n   E.g., `Arc` instead of `Rc`, `Mutex` instead of `RefCell`, and `Box<dyn Send + T>` instead of `Box<dyn T>`.\n\n   Before:\n\n   ```rust,compile_fail\n   use pyo3::prelude::*;\n   use std::rc::Rc;\n   use std::cell::RefCell;\n\n   #[pyclass]\n   struct NotThreadSafe {\n       shared_bools: Rc<RefCell<Vec<bool>>>,\n       closure: Box<dyn Fn()>,\n   }\n   ```\n\n   After:\n\n   ```rust,ignore\n   # #![allow(dead_code)]\n   use pyo3::prelude::*;\n   use std::sync::{Arc, Mutex};\n\n   #[pyclass]\n   struct ThreadSafe {\n       shared_bools: Arc<Mutex<Vec<bool>>>,\n       closure: Box<dyn Fn() + Send>,\n   }\n   ```\n\n   In situations where you cannot change your `#[pyclass]` to automatically implement `Send` (e.g., when it contains a raw pointer), you can use `unsafe impl Send`.\n   In such cases, care should be taken to ensure the struct is actually thread safe.\n   See [the Rustonomicon](https://doc.rust-lang.org/nomicon/send-and-sync.html) for more.\n\n2. If you think that your `#[pyclass]` should not be accessed by another thread, you can use `unsendable` flag.\n   A class marked with `unsendable` panics when accessed by another thread, making it thread-safe to expose an unsendable object to the Python interpreter.\n\n   Before:\n\n   ```rust,compile_fail\n   use pyo3::prelude::*;\n\n   #[pyclass]\n   struct Unsendable {\n       pointers: Vec<*mut std::ffi::c_char>,\n   }\n   ```\n\n   After:\n\n   ```rust,no_run\n   # #![allow(dead_code)]\n   use pyo3::prelude::*;\n\n   #[pyclass(unsendable)]\n   struct Unsendable {\n       pointers: Vec<*mut std::ffi::c_char>,\n   }\n   ```\n\n</details>\n\n### All `PyObject` and `Py<T>` methods now take `Python` as an argument\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPreviously, a few methods such as `Object::get_refcnt` did not take `Python` as an argument (to ensure that the Python GIL was held by the current thread).\nTechnically, this was not sound.\nTo migrate, just pass a `py` argument to any calls to these methods.\n\nBefore:\n\n```rust,compile_fail\n# pyo3::Python::attach(|py| {\npy.None().get_refcnt();\n# })\n```\n\nAfter:\n\n```rust,ignore\n# pyo3::Python::attach(|py| {\npy.None().get_refcnt(py);\n# })\n```\n\n</details>\n\n## from 0.9.* to 0.10\n\n### `ObjectProtocol` is removed\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nAll methods are moved to [`PyAny`].\nAnd since now all native types (e.g., `PyList`) implements `Deref<Target=PyAny>`, all you need to do is remove `ObjectProtocol` from your code.\nOr if you use `ObjectProtocol` by `use pyo3::prelude::*`, you have to do nothing.\n\nBefore:\n\n```rust,compile_fail,ignore\nuse pyo3::ObjectProtocol;\n\n# pyo3::Python::with_gil(|py| {\nlet obj = py.eval(\"lambda: 'Hi :)'\", None, None).unwrap();\nlet hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap();\nassert_eq!(hi.len().unwrap(), 5);\n# })\n```\n\nAfter:\n\n```rust,ignore\n# pyo3::Python::with_gil(|py| {\nlet obj = py.eval(\"lambda: 'Hi :)'\", None, None).unwrap();\nlet hi: &pyo3::types::PyString = obj.call0().unwrap().downcast().unwrap();\nassert_eq!(hi.len().unwrap(), 5);\n# })\n```\n\n</details>\n\n### No `#![feature(specialization)]` in user code\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nWhile PyO3 itself still requires specialization and nightly Rust, now you don't have to use `#![feature(specialization)]` in your crate.\n</details>\n\n## from 0.8.* to 0.9\n\n### `#[new]` interface\n\n<details>\n<summary><small>Click to expand</small></summary>\n\n[`PyRawObject`](https://docs.rs/pyo3/0.8.5/pyo3/type_object/struct.PyRawObject.html) is now removed and our syntax for constructors has changed.\n\nBefore:\n\n```rust,compile_fail\n#[pyclass]\nstruct MyClass {}\n\n#[pymethods]\nimpl MyClass {\n    #[new]\n    fn new(obj: &PyRawObject) {\n        obj.init(MyClass {})\n    }\n}\n```\n\nAfter:\n\n```rust,no_run\n# use pyo3::prelude::*;\n#[pyclass]\nstruct MyClass {}\n\n#[pymethods]\nimpl MyClass {\n    #[new]\n    fn new() -> Self {\n        MyClass {}\n    }\n}\n```\n\nBasically you can return `Self` or `Result<Self>` directly.\nFor more, see [the constructor section](class.md#constructor) of this guide.\n</details>\n\n### PyCell\n\n<details>\n<summary><small>Click to expand</small></summary>\n\nPyO3 0.9 introduces `PyCell`, which is a [`RefCell`]-like object wrapper for ensuring Rust's rules regarding aliasing of references are upheld.\nFor more detail, see the [Rust Book's section on Rust's rules of references](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references)\n\nFor `#[pymethods]` or `#[pyfunction]`s, your existing code should continue to work without any change.\nPython exceptions will automatically be raised when your functions are used in a way which breaks Rust's rules of references.\n\nHere is an example.\n\n```rust\n# use pyo3::prelude::*;\n\n#[pyclass]\nstruct Names {\n    names: Vec<String>,\n}\n\n#[pymethods]\nimpl Names {\n    #[new]\n    fn new() -> Self {\n        Names { names: vec![] }\n    }\n    fn merge(&mut self, other: &mut Names) {\n        self.names.append(&mut other.names)\n    }\n}\n# Python::attach(|py| {\n#     let names = Py::new(py, Names::new()).unwrap();\n#     pyo3::py_run!(py, names, r\"\n#     try:\n#        names.merge(names)\n#        assert False, 'Unreachable'\n#     except RuntimeError as e:\n#        assert str(e) == 'Already borrowed'\n#     \");\n# })\n```\n\n`Names` has a `merge` method, which takes `&mut self` and another argument of type `&mut Self`.\nGiven this `#[pyclass]`, calling `names.merge(names)` in Python raises a [`PyBorrowMutError`] exception, since it requires two mutable borrows of `names`.\n\nHowever, for `#[pyproto]` and some functions, you need to manually fix the code.\n\n#### Object creation\n\nIn 0.8 object creation was done with `PyRef::new` and `PyRefMut::new`.\nIn 0.9 these have both been removed.\nTo upgrade code, please use `PyCell::new` instead.\nIf you need [`PyRef`] or [`PyRefMut`], just call `.borrow()` or `.borrow_mut()` on the newly-created `PyCell`.\n\nBefore:\n\n```rust,compile_fail\n# use pyo3::prelude::*;\n# #[pyclass]\n# struct MyClass {}\n# Python::with_gil(|py| {\nlet obj_ref = PyRef::new(py, MyClass {}).unwrap();\n# })\n```\n\nAfter:\n\n```rust,ignore\n# use pyo3::prelude::*;\n# #[pyclass]\n# struct MyClass {}\n# Python::with_gil(|py| {\nlet obj = PyCell::new(py, MyClass {}).unwrap();\nlet obj_ref = obj.borrow();\n# })\n```\n\n#### Object extraction\n\nFor `PyClass` types `T`, `&T` and `&mut T` no longer have [`FromPyObject`] implementations.\nInstead you should extract `PyRef<T>` or `PyRefMut<T>`, respectively.\nIf `T` implements `Clone`, you can extract `T` itself.\nIn addition, you can also extract `&PyCell<T>`, though you rarely need it.\n\nBefore:\n\n```compile_fail\nlet obj: &PyAny = create_obj();\nlet obj_ref: &MyClass = obj.extract().unwrap();\nlet obj_ref_mut: &mut MyClass = obj.extract().unwrap();\n```\n\nAfter:\n\n```rust,ignore\n# use pyo3::prelude::*;\n# use pyo3::types::IntoPyDict;\n# #[pyclass] #[derive(Clone)] struct MyClass {}\n# #[pymethods] impl MyClass { #[new]fn new() -> Self { MyClass {} }}\n# Python::with_gil(|py| {\n# let typeobj = py.get_type::<MyClass>();\n# let d = [(\"c\", typeobj)].into_py_dict(py);\n# let create_obj = || py.eval(\"c()\", None, Some(d)).unwrap();\nlet obj: &PyAny = create_obj();\nlet obj_cell: &PyCell<MyClass> = obj.extract().unwrap();\nlet obj_cloned: MyClass = obj.extract().unwrap(); // extracted by cloning the object\n{\n    let obj_ref: PyRef<'_, MyClass> = obj.extract().unwrap();\n    // we need to drop obj_ref before we can extract a PyRefMut due to Rust's rules of references\n}\nlet obj_ref_mut: PyRefMut<'_, MyClass> = obj.extract().unwrap();\n# })\n```\n\n#### `#[pyproto]`\n\nMost of the arguments to methods in `#[pyproto]` impls require a [`FromPyObject`] implementation.\nSo if your protocol methods take `&T` or `&mut T` (where `T: PyClass`), please use [`PyRef`] or [`PyRefMut`] instead.\n\nBefore:\n\n```rust,compile_fail\n# use pyo3::prelude::*;\n# use pyo3::class::PySequenceProtocol;\n#[pyclass]\nstruct ByteSequence {\n    elements: Vec<u8>,\n}\n#[pyproto]\nimpl PySequenceProtocol for ByteSequence {\n    fn __concat__(&self, other: &Self) -> PyResult<Self> {\n        let mut elements = self.elements.clone();\n        elements.extend_from_slice(&other.elements);\n        Ok(Self { elements })\n    }\n}\n```\n\nAfter:\n\n```rust,compile_fail\n# use pyo3::prelude::*;\n# use pyo3::class::PySequenceProtocol;\n#[pyclass]\nstruct ByteSequence {\n    elements: Vec<u8>,\n}\n#[pyproto]\nimpl PySequenceProtocol for ByteSequence {\n    fn __concat__(&self, other: PyRef<'p, Self>) -> PyResult<Self> {\n        let mut elements = self.elements.clone();\n        elements.extend_from_slice(&other.elements);\n        Ok(Self { elements })\n    }\n}\n```\n\n</details>\n\n<style>\n    /* render details immediately below h3 headers */\n\n```text\nh3:has(+ details) {\nmargin-bottom: 0;\n}\n```\n\n```text\n/* make summary text hint that it's clickable and increase the\nsize of the clickable area by padding downwards */\ndetails > summary {\ncursor: pointer;\npadding-bottom: 0.5em;\n}\n```\n\n```text\n/* reduce margin from paragraph directly below the clickable space\nto avoid large gap */\ndetails > summary + p {\nmargin-block-start: 0.5em;\n}\n```\n\n```text\n/* pack headings that aren't expanded slightly closer together */\nh3 + details:not([open]) + h3 {\nmargin-top: 1.5em;\n}\n```\n\n</style>\n\n[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html\n[`PyAny`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html\n[`PyBorrowMutError`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyBorrowMutError.html\n[`PyRef`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html\n[`PyRefMut`]: {{#PYO3_DOCS_URL}}/pyo3/pycell/struct.PyRef.html\n\n[`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html\n"
  },
  {
    "path": "guide/src/module.md",
    "content": "# Python modules\n\nYou can create a module using `#[pymodule]`:\n\n```rust,no_run\n# mod declarative_module_basic_test {\nuse pyo3::prelude::*;\n\n#[pyfunction]\nfn double(x: usize) -> usize {\n    x * 2\n}\n\n/// This module is implemented in Rust.\n#[pymodule]\nmod my_extension {\n    use pyo3::prelude::*;\n\n    #[pymodule_export]\n    use super::double; // The double function is made available from Python, works also with classes\n\n    #[pyfunction] // Inline definition of a pyfunction, also made available to Python\n    fn triple(x: usize) -> usize {\n        x * 3\n    }\n}\n# }\n```\n\nThe `#[pymodule]` procedural macro takes care of creating the initialization function of your module and exposing it to Python.\n\nThe module's name defaults to the name of the Rust module.\nYou can override the module name by using `#[pyo3(name = \"custom_name\")]`:\n\n```rust,no_run\n# mod declarative_module_custom_name_test {\nuse pyo3::prelude::*;\n\n#[pyfunction]\nfn double(x: usize) -> usize {\n    x * 2\n}\n\n#[pymodule(name = \"custom_name\")]\nmod my_extension {\n    #[pymodule_export]\n    use super::double;\n}\n# }\n```\n\nThe name of the module must match the name of the `.so` or `.pyd` file.\nOtherwise, you will get an import error in Python with the following message: `ImportError: dynamic module does not define module export function (PyInit_name_of_your_module)`\n\nTo import the module, either:\n\n- copy the shared library as described in [Manual builds](building-and-distribution.md#manual-builds), or\n- use a tool, e.g. `maturin develop` with [maturin](https://github.com/PyO3/maturin) or\n`python setup.py develop` with [setuptools-rust](https://github.com/PyO3/setuptools-rust).\n\n## Documentation\n\nThe [Rust doc comments](https://doc.rust-lang.org/stable/book/ch03-04-comments.html) of the Rust module will be applied automatically as the Python docstring of your module.\n\nFor example, building off of the above code, this will print `This module is implemented in Rust.`:\n\n```python\nimport my_extension\n\nprint(my_extension.__doc__)\n```\n\n## Python submodules\n\nYou can create a module hierarchy within a single extension module by just `use`ing modules like functions or classes.\nFor example, you could define the modules `parent_module` and `parent_module.child_module`:\n\n```rust\nuse pyo3::prelude::*;\n\n#[pymodule]\nmod parent_module {\n    #[pymodule_export]\n    use super::child_module;\n}\n\n#[pymodule]\nmod child_module {\n    #[pymodule_export]\n    use super::func;\n}\n\n#[pyfunction]\nfn func() -> String {\n    \"func\".to_string()\n}\n#\n# fn main() {\n#   Python::attach(|py| {\n#       use pyo3::wrap_pymodule;\n#       use pyo3::types::IntoPyDict;\n#       let parent_module = wrap_pymodule!(parent_module)(py);\n#       let ctx = [(\"parent_module\", parent_module)].into_py_dict(py).unwrap();\n#\n#      py.run(c\"assert parent_module.child_module.func() == 'func'\", None, Some(&ctx)).unwrap();\n#   })\n# }\n```\n\nNote that this does not define a package, so this won’t allow Python code to directly import submodules by using `from parent_module import child_module`.\nFor more information, see [#759](https://github.com/PyO3/pyo3/issues/759) and [#1517](https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021).\n\nYou can provide the `submodule` argument to `#[pymodule()]` for modules that are not top-level modules in order for them to properly generate the `#[pyclass]` `module` attribute automatically.\n\n## Inline declaration\n\nIt is possible to declare functions, classes, sub-modules and constants inline in a module:\n\nFor example:\n\n```rust,no_run\n# mod declarative_module_test {\n#[pyo3::pymodule]\nmod my_extension {\n    use pyo3::prelude::*;\n\n    #[pymodule_export]\n    const PI: f64 = std::f64::consts::PI; // Exports PI constant as part of the module\n\n    #[pyfunction] // This will be part of the module\n    fn double(x: usize) -> usize {\n        x * 2\n    }\n\n    #[pyclass] // This will be part of the module\n    struct Unit;\n\n    #[pymodule]\n    mod submodule {\n        // This is a submodule\n        use pyo3::prelude::*;\n\n        #[pyclass]\n        struct Nested;\n    }\n}\n# }\n```\n\nIn this case, `#[pymodule]` macro automatically sets the `module` attribute of the `#[pyclass]` macros declared inside of it with its name.\nFor nested modules, the name of the parent module is automatically added.\nIn the previous example, the `Nested` class will have for `module` `my_extension.submodule`.\n\n## Procedural initialization\n\nIf the macros provided by PyO3 are not enough, it is possible to run code at the module initialization:\n\n```rust,no_run\n# mod procedural_module_test {\n#[pyo3::pymodule]\nmod my_extension {\n    use pyo3::prelude::*;\n\n    #[pyfunction]\n    fn double(x: usize) -> usize {\n        x * 2\n    }\n\n    #[pymodule_init]\n    fn init(m: &Bound<'_, PyModule>) -> PyResult<()> {\n        // Arbitrary code to run at the module initialization\n        m.add(\"double2\", m.getattr(\"double\")?)\n    }\n}\n# }\n```\n"
  },
  {
    "path": "guide/src/parallelism.md",
    "content": "# Parallelism\n\nHistorically, CPython was limited by the [global interpreter lock](https://docs.python.org/3/glossary.html#term-global-interpreter-lock) (GIL), which only allowed a single thread to drive the Python interpreter at a time.\nThis made threading in Python a bad fit for [CPU-bound](https://en.wikipedia.org/wiki/CPU-bound) tasks and often forced developers to accept the overhead of multiprocessing.\n\nRust is well-suited to multithreaded code, and libraries like [`rayon`] can help you leverage safe parallelism with minimal effort.\nThe [`Python::detach`] method can be used to allow the Python interpreter to do other work while the Rust work is ongoing.\n\nTo enable full parallelism in your application, consider also using [free-threaded Python](./free-threading.md) which is supported since Python 3.14.\n\n## Parallelism under the Python GIL\n\nLet's take a look at our [word-count](https://github.com/PyO3/pyo3/blob/main/examples/word-count/src/lib.rs) example, where we have a `search` function that utilizes the [`rayon`] crate to count words in parallel.\n\n```rust,no_run\n# #![allow(dead_code)]\nuse pyo3::prelude::*;\n\n// These traits let us use `par_lines` and `map`.\nuse rayon::str::ParallelString;\nuse rayon::iter::ParallelIterator;\n\n/// Count the occurrences of needle in line, case insensitive\nfn count_line(line: &str, needle: &str) -> usize {\n    let mut total = 0;\n    for word in line.split(' ') {\n        if word == needle {\n            total += 1;\n        }\n    }\n    total\n}\n\n#[pyfunction]\nfn search(contents: &str, needle: &str) -> usize {\n    contents\n        .par_lines()\n        .map(|line| count_line(line, needle))\n        .sum()\n}\n```\n\nBut let's assume you have a long running Rust function which you would like to execute several times in parallel.\nFor the sake of example let's take a sequential version of the word count:\n\n```rust,no_run\n# #![allow(dead_code)]\n# fn count_line(line: &str, needle: &str) -> usize {\n#     let mut total = 0;\n#     for word in line.split(' ') {\n#         if word == needle {\n#             total += 1;\n#         }\n#     }\n#     total\n# }\n#\nfn search_sequential(contents: &str, needle: &str) -> usize {\n    contents.lines().map(|line| count_line(line, needle)).sum()\n}\n```\n\nTo enable parallel execution of this function, the [`Python::detach`] method can be used to temporarily release the GIL, thus allowing other Python threads to run.\nWe then have a function exposed to the Python runtime which calls `search_sequential` inside a closure passed to [`Python::detach`] to enable true parallelism:\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n#\n# fn count_line(line: &str, needle: &str) -> usize {\n#     let mut total = 0;\n#     for word in line.split(' ') {\n#         if word == needle {\n#             total += 1;\n#         }\n#     }\n#     total\n# }\n#\n# fn search_sequential(contents: &str, needle: &str) -> usize {\n#    contents.lines().map(|line| count_line(line, needle)).sum()\n# }\n#[pyfunction]\nfn search_sequential_detached(py: Python<'_>, contents: &str, needle: &str) -> usize {\n    py.detach(|| search_sequential(contents, needle))\n}\n```\n\nNow Python threads can use more than one CPU core, resolving the limitation which usually makes multi-threading in Python only good for IO-bound tasks:\n\n```Python\nfrom concurrent.futures import ThreadPoolExecutor\nfrom word_count import search_sequential_detached\n\nexecutor = ThreadPoolExecutor(max_workers=2)\n\nfuture_1 = executor.submit(\n    word_count.search_sequential_detached, contents, needle\n)\nfuture_2 = executor.submit(\n    word_count.search_sequential_detached, contents, needle\n)\nresult_1 = future_1.result()\nresult_2 = future_2.result()\n```\n\n## Benchmark\n\nLet's benchmark the `word-count` example to verify that we really did unlock parallelism with PyO3.\n\nWe are using `pytest-benchmark` to benchmark four word count functions:\n\n1. Pure Python version\n2. Rust parallel version\n3. Rust sequential version\n4. Rust sequential version executed twice with two Python threads\n\nThe benchmark script can be found [in the PyO3 GitHub repository](https://github.com/PyO3/pyo3/blob/main/examples/word-count/tests/test_word_count.py), and we can run `nox` in the `word-count` folder to benchmark these functions.\n\nWhile the results of the benchmark of course depend on your machine, the relative results should be similar to this (mid 2020):\n\n```text\n-------------------------------------------------------------------------------------------------- benchmark: 4 tests -------------------------------------------------------------------------------------------------\nName (time in ms)                                          Min                Max               Mean            StdDev             Median               IQR            Outliers       OPS            Rounds  Iterations\n-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\ntest_word_count_rust_parallel                           1.7315 (1.0)       4.6495 (1.0)       1.9972 (1.0)      0.4299 (1.0)       1.8142 (1.0)      0.2049 (1.0)         40;46  500.6943 (1.0)         375           1\ntest_word_count_rust_sequential                         7.3348 (4.24)     10.3556 (2.23)      8.0035 (4.01)     0.7785 (1.81)      7.5597 (4.17)     0.8641 (4.22)         26;5  124.9457 (0.25)        121           1\ntest_word_count_rust_sequential_twice_with_threads      7.9839 (4.61)     10.3065 (2.22)      8.4511 (4.23)     0.4709 (1.10)      8.2457 (4.55)     0.3927 (1.92)        17;17  118.3274 (0.24)        114           1\ntest_word_count_python_sequential                      27.3985 (15.82)    45.4527 (9.78)     28.9604 (14.50)    4.1449 (9.64)     27.5781 (15.20)    0.4638 (2.26)          3;5   34.5299 (0.07)         35           1\n-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n```\n\nYou can see that the Python threaded version is not much slower than the Rust sequential version, which means compared to an execution on a single CPU core the speed has doubled.\n\n## Sharing Python objects between Rust threads\n\nIn the example above we made a Python interface to a low-level rust function, and then leveraged the python `threading` module to run the low-level function in parallel.\nIt is also possible to spawn threads in Rust that acquire the GIL and operate on Python objects.\nHowever, care must be taken to avoid writing code that deadlocks with the GIL in these cases.\n\n- Note: This example is meant to illustrate how to drop and re-acquire the GIL\n        to avoid creating deadlocks. Unless the spawned threads subsequently\n        release the GIL or you are using the free-threaded build of CPython, you\n        will not see any speedups due to multi-threaded parallelism using `rayon`\n        to parallelize code that acquires and holds the GIL for the entire\n        execution of the spawned thread.\n\nIn the example below, we share a `Vec` of User ID objects defined using the `pyclass` macro and spawn threads to process the collection of data into a `Vec` of booleans based on a predicate using a `rayon` parallel iterator:\n\n```rust,no_run\nuse pyo3::prelude::*;\n\n// These traits let us use int_par_iter and map\nuse rayon::iter::{IntoParallelRefIterator, ParallelIterator};\n\n#[pyclass]\nstruct UserID {\n    id: i64,\n}\n\nlet allowed_ids: Vec<bool> = Python::attach(|outer_py| {\n    let instances: Vec<Py<UserID>> = (0..10).map(|x| Py::new(outer_py, UserID { id: x }).unwrap()).collect();\n    outer_py.detach(|| {\n        instances.par_iter().map(|instance| {\n            Python::attach(|inner_py| {\n                instance.borrow(inner_py).id > 5\n            })\n        }).collect()\n    })\n});\nassert!(allowed_ids.into_iter().filter(|b| *b).count() == 4);\n```\n\nIt's important to note that there is an `outer_py` Python token as well as an `inner_py` token.\nSharing Python tokens between threads is not allowed and threads must individually attach to the interpreter to access data wrapped by a Python object.\n\nIt's also important to see that this example uses [`Python::detach`] to wrap the code that spawns OS threads via `rayon`.\nIf this example didn't use `detach`, a `rayon` worker thread would block on acquiring the GIL while a thread that owns the GIL spins forever waiting for the result of the `rayon` thread.\nCalling `detach` allows the GIL to be released in the thread collecting the results from the worker threads.\nYou should always call `detach` in situations that spawn worker threads, but especially so in cases where worker threads need to acquire the GIL, to prevent deadlocks.\n\n[`Python::detach`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.detach\n[`rayon`]: https://github.com/rayon-rs/rayon\n"
  },
  {
    "path": "guide/src/performance.md",
    "content": "# Performance\n\nTo achieve the best possible performance, it is useful to be aware of several tricks and sharp edges concerning PyO3's API.\n\n## `extract` versus `cast`\n\nPythonic API implemented using PyO3 are often polymorphic, i.e. they will accept `&Bound<'_, PyAny>` and try to turn this into multiple more concrete types to which the requested operation is applied.\nThis often leads to chains of calls to `extract`, e.g.\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use pyo3::{exceptions::PyTypeError, types::PyList};\n\nfn frobnicate_list<'py>(list: &Bound<'_, PyList>) -> PyResult<Bound<'py, PyAny>> {\n    todo!()\n}\n\nfn frobnicate_vec<'py>(vec: Vec<Bound<'py, PyAny>>) -> PyResult<Bound<'py, PyAny>> {\n    todo!()\n}\n\n#[pyfunction]\nfn frobnicate<'py>(value: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> {\n    if let Ok(list) = value.extract::<Bound<'_, PyList>>() {\n        frobnicate_list(&list)\n    } else if let Ok(vec) = value.extract::<Vec<Bound<'_, PyAny>>>() {\n        frobnicate_vec(vec)\n    } else {\n        Err(PyTypeError::new_err(\"Cannot frobnicate that type.\"))\n    }\n}\n```\n\nThis suboptimal as the `FromPyObject<T>` trait requires `extract` to have a `Result<T, PyErr>` return type.\nFor native types like `PyList`, it faster to use `cast` (which `extract` calls internally) when the error value is ignored.\nThis avoids the costly conversion of a `PyDowncastError` to a `PyErr` required to fulfil the `FromPyObject` contract, i.e.\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use pyo3::{exceptions::PyTypeError, types::PyList};\n# fn frobnicate_list<'py>(list: &Bound<'_, PyList>) -> PyResult<Bound<'py, PyAny>> { todo!() }\n# fn frobnicate_vec<'py>(vec: Vec<Bound<'py, PyAny>>) -> PyResult<Bound<'py, PyAny>> { todo!() }\n#\n#[pyfunction]\nfn frobnicate<'py>(value: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> {\n    // Use `cast` instead of `extract` as turning `PyDowncastError` into `PyErr` is quite costly.\n    if let Ok(list) = value.cast::<PyList>() {\n        frobnicate_list(list)\n    } else if let Ok(vec) = value.extract::<Vec<Bound<'_, PyAny>>>() {\n        frobnicate_vec(vec)\n    } else {\n        Err(PyTypeError::new_err(\"Cannot frobnicate that type.\"))\n    }\n}\n```\n\n## Access to Bound implies access to Python token\n\nCalling `Python::attach` is effectively a no-op when we're already attached to the interpreter, but checking that this is the case still has a cost.\nIf an existing Python token can not be accessed, for example when implementing a pre-existing trait, but a Python-bound reference is available, this cost can be avoided by exploiting that access to Python-bound reference gives zero-cost access to a Python token via `Bound::py`.\n\nFor example, instead of writing\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use pyo3::types::PyList;\n\nstruct Foo(Py<PyList>);\n\nstruct FooBound<'py>(Bound<'py, PyList>);\n\nimpl PartialEq<Foo> for FooBound<'_> {\n    fn eq(&self, other: &Foo) -> bool {\n        Python::attach(|py| {\n            let len = other.0.bind(py).len();\n            self.0.len() == len\n        })\n    }\n}\n```\n\nuse the more efficient\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use pyo3::types::PyList;\n# struct Foo(Py<PyList>);\n# struct FooBound<'py>(Bound<'py, PyList>);\n#\nimpl PartialEq<Foo> for FooBound<'_> {\n    fn eq(&self, other: &Foo) -> bool {\n        // Access to `&Bound<'py, PyAny>` implies access to `Python<'py>`.\n        let py = self.0.py();\n        let len = other.0.bind(py).len();\n        self.0.len() == len\n    }\n}\n```\n\n## Calling Python callables (`__call__`)\n\nCPython support multiple calling protocols: [`tp_call`] and [`vectorcall`].\n[`vectorcall`] is a more efficient protocol unlocking faster calls.\nPyO3 will try to dispatch Python `call`s using the [`vectorcall`] calling convention to archive maximum performance if possible and falling back to [`tp_call`] otherwise.\nThis is implemented using the (internal) `PyCallArgs` trait.\nIt defines how Rust types can be used as Python `call` arguments.\nThis trait is currently implemented for\n\n- Rust tuples, where each member implements `IntoPyObject`,\n- `Bound<'_, PyTuple>`\n- `Py<PyTuple>`\n\nRust tuples may make use of [`vectorcall`] where as `Bound<'_, PyTuple>` and `Py<PyTuple>` can only use [`tp_call`].\nFor maximum performance prefer using Rust tuples as arguments.\n\n[`tp_call`]: https://docs.python.org/3/c-api/call.html#the-tp-call-protocol\n[`vectorcall`]: https://docs.python.org/3/c-api/call.html#the-vectorcall-protocol\n\n## Detach from the interpreter for long-running Rust-only work\n\nWhen executing Rust code which does not need to interact with the Python interpreter, use [`Python::detach`] to allow the Python interpreter to proceed without waiting for the current thread.\n\nOn the GIL-enabled build, this is crucial for best performance as only a single thread may ever be attached at a time.\n\nOn the free-threaded build, this is still best practice as there are several \"stop the world\" events (such as garbage collection) where all threads attached to the Python interpreter are forced to wait.\n\nAs a rule of thumb, attaching and detaching from the Python interpreter takes less than a millisecond, so any work which is expected to take multiple milliseconds can likely benefit from detaching from the interpreter.\n\n[`Python::detach`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.detach\n\n## Disable the global reference pool\n\nPyO3 uses global mutable state to keep track of deferred reference count updates implied by `impl<T> Drop for Py<T>` being called without being attached to the interpreter.\nThe necessary synchronization to obtain and apply these reference count updates when PyO3-based code next attaches to the interpreter is somewhat expensive and can become a significant part of the cost of crossing the Python-Rust boundary.\n\nThis functionality can be avoided by setting the `pyo3_disable_reference_pool` conditional compilation flag.\nThis removes the global reference pool and the associated costs completely.\nHowever, it does _not_ remove the `Drop` implementation for `Py<T>` which is necessary to interoperate with existing Rust code written without PyO3-based code in mind.\nTo stay compatible with the wider Rust ecosystem in these cases, we keep the implementation but abort when `Drop` is called without being attached to the interpreter.\nIf `pyo3_leak_on_drop_without_reference_pool` is additionally enabled, objects dropped without being attached to Python will be leaked instead which is always sound but might have determinal effects like resource exhaustion in the long term.\n\nThis limitation is important to keep in mind when this setting is used, especially when embedding Python code into a Rust application as it is quite easy to accidentally drop a `Py<T>` (or types containing it like `PyErr`, `PyBackedStr` or `PyBackedBytes`) returned from `Python::attach` without making sure to re-attach beforehand.\nFor example, the following code\n\n```rust,ignore\n# use pyo3::prelude::*;\n# use pyo3::types::PyList;\nlet numbers: Py<PyList> = Python::attach(|py| PyList::empty(py).unbind());\n\nPython::attach(|py| {\n    numbers.bind(py).append(23).unwrap();\n});\n\nPython::attach(|py| {\n    numbers.bind(py).append(42).unwrap();\n});\n```\n\nwill abort if the list not explicitly disposed via\n\n```rust\n# use pyo3::prelude::*;\n# use pyo3::types::PyList;\nlet numbers: Py<PyList> = Python::attach(|py| PyList::empty(py).unbind());\n\nPython::attach(|py| {\n    numbers.bind(py).append(23).unwrap();\n});\n\nPython::attach(|py| {\n    numbers.bind(py).append(42).unwrap();\n});\n\nPython::attach(move |py| {\n    drop(numbers);\n});\n```\n"
  },
  {
    "path": "guide/src/python-from-rust/calling-existing-code.md",
    "content": "# Executing existing Python code\n\nIf you already have some existing Python code that you need to execute from Rust, the following FAQs can help you select the right PyO3 functionality for your situation:\n\n## Want to access Python APIs? Then use `PyModule::import`\n\n[`PyModule::import`] can be used to get handle to a Python module from Rust.\nYou can use this to import and use any Python module available in your environment.\n\n```rust\nuse pyo3::prelude::*;\n\nfn main() -> PyResult<()> {\n    Python::attach(|py| {\n        let builtins = PyModule::import(py, \"builtins\")?;\n        let total: i32 = builtins\n            .getattr(\"sum\")?\n            .call1((vec![1, 2, 3],))?\n            .extract()?;\n        assert_eq!(total, 6);\n        Ok(())\n    })\n}\n```\n\n[`PyModule::import`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.import\n\n## Want to run just an expression? Then use `eval`\n\n[`Python::eval`]({{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.eval) is a method to execute a [Python expression](https://docs.python.org/3/reference/expressions.html) and return the evaluated value as a `Bound<'py, PyAny>` object.\n\n```rust\nuse pyo3::prelude::*;\n\n# fn main() -> Result<(), ()> {\nPython::attach(|py| {\n    let result = py\n        .eval(c\"[i * 10 for i in range(5)]\", None, None)\n        .map_err(|e| {\n            e.print_and_set_sys_last_vars(py);\n        })?;\n    let res: Vec<i64> = result.extract().unwrap();\n    assert_eq!(res, vec![0, 10, 20, 30, 40]);\n    Ok(())\n})\n# }\n```\n\n## Want to run statements? Then use `run`\n\n[`Python::run`] is a method to execute one or more [Python statements](https://docs.python.org/3/reference/simple_stmts.html).\nThis method returns nothing (like any Python statement), but you can get access to manipulated objects via the `locals` dict.\n\nYou can also use the [`py_run!`] macro, which is a shorthand for [`Python::run`].\nSince [`py_run!`] panics on exceptions, we recommend you use this macro only for quickly testing your Python extensions.\n\n```rust\nuse pyo3::prelude::*;\nuse pyo3::py_run;\n\n# fn main() {\n#[pyclass]\nstruct UserData {\n    id: u32,\n    name: String,\n}\n\n#[pymethods]\nimpl UserData {\n    fn as_tuple(&self) -> (u32, String) {\n        (self.id, self.name.clone())\n    }\n\n    fn __repr__(&self) -> PyResult<String> {\n        Ok(format!(\"User {}(id: {})\", self.name, self.id))\n    }\n}\n\nPython::attach(|py| {\n    let userdata = UserData {\n        id: 34,\n        name: \"Yu\".to_string(),\n    };\n    let userdata = Py::new(py, userdata).unwrap();\n    let userdata_as_tuple = (34, \"Yu\");\n    py_run!(py, userdata userdata_as_tuple, r#\"\nassert repr(userdata) == \"User Yu(id: 34)\"\nassert userdata.as_tuple() == userdata_as_tuple\n    \"#);\n})\n# }\n```\n\n## You have a Python file or code snippet? Then use `PyModule::from_code`\n\n[`PyModule::from_code`]({{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.from_code) can be used to generate a Python module which can then be used just as if it was imported with `PyModule::import`.\n\n**Warning**: This will compile and execute code.\n**Never** pass untrusted code to this function!\n\n```rust\nuse pyo3::{prelude::*, types::IntoPyDict};\n\n# fn main() -> PyResult<()> {\nPython::attach(|py| {\n    let activators = PyModule::from_code(\n        py,\n        cr#\"\ndef relu(x):\n    \"\"\"see https://en.wikipedia.org/wiki/Rectifier_(neural_networks)\"\"\"\n    return max(0.0, x)\n\ndef leaky_relu(x, slope=0.01):\n    return x if x >= 0 else x * slope\n    \"#,\n        c\"activators.py\",\n        c\"activators\",\n    )?;\n\n    let relu_result: f64 = activators.getattr(\"relu\")?.call1((-1.0,))?.extract()?;\n    assert_eq!(relu_result, 0.0);\n\n    let kwargs = [(\"slope\", 0.2)].into_py_dict(py)?;\n    let lrelu_result: f64 = activators\n        .getattr(\"leaky_relu\")?\n        .call((-1.0,), Some(&kwargs))?\n        .extract()?;\n    assert_eq!(lrelu_result, -0.2);\n#    Ok(())\n})\n# }\n```\n\n## Want to embed Python in Rust with additional modules?\n\nPython maintains the `sys.modules` dict as a cache of all imported modules.\nAn import in Python will first attempt to lookup the module from this dict, and if not present will use various strategies to attempt to locate and load the module.\n\nThe [`append_to_inittab`]({{#PYO3_DOCS_URL}}/pyo3/macro.append_to_inittab.html) macro can be used to add additional `#[pymodule]` modules to an embedded Python interpreter.\nThe macro **must** be invoked _before_ initializing Python.\n\nAs an example, the below adds the module `foo` to the embedded interpreter:\n\n```rust\nuse pyo3::prelude::*;\n\n#[pymodule]\nmod foo {\n    use pyo3::prelude::*;\n\n    #[pyfunction]\n    fn add_one(x: i64) -> i64 {\n        x + 1\n    }\n}\n\nfn main() -> PyResult<()> {\n    pyo3::append_to_inittab!(foo);\n    Python::attach(|py| Python::run(py, c\"import foo; foo.add_one(6)\", None, None))\n}\n```\n\nIf `append_to_inittab` cannot be used due to constraints in the program, an alternative is to create a module using [`PyModule::new`] and insert it manually into `sys.modules`:\n\n```rust\nuse pyo3::prelude::*;\nuse pyo3::types::PyDict;\n\n#[pyfunction]\npub fn add_one(x: i64) -> i64 {\n    x + 1\n}\n\nfn main() -> PyResult<()> {\n    Python::attach(|py| {\n        // Create new module\n        let foo_module = PyModule::new(py, \"foo\")?;\n        foo_module.add_function(wrap_pyfunction!(add_one, &foo_module)?)?;\n\n        // Import and get sys.modules\n        let sys = PyModule::import(py, \"sys\")?;\n        let py_modules: Bound<'_, PyDict> = sys.getattr(\"modules\")?.cast_into()?;\n\n        // Insert foo into sys.modules\n        py_modules.set_item(\"foo\", foo_module)?;\n\n        // Now we can import + run our python code\n        Python::run(py, c\"import foo; foo.add_one(6)\", None, None)\n    })\n}\n```\n\n## Include multiple Python files\n\nYou can include a file at compile time by using [`std::include_str`](https://doc.rust-lang.org/std/macro.include_str.html) macro.\n\nOr you can load a file at runtime by using [`std::fs::read_to_string`](https://doc.rust-lang.org/std/fs/fn.read_to_string.html) function.\n\nMany Python files can be included and loaded as modules.\nIf one file depends on another you must preserve correct order while declaring `PyModule`.\n\nExample directory structure:\n\n```text\n.\n├── Cargo.lock\n├── Cargo.toml\n├── python_app\n│   ├── app.py\n│   └── utils\n│       └── foo.py\n└── src\n    └── main.rs\n```\n\n`python_app/app.py`:\n\n```python\nfrom utils.foo import bar\n\n\ndef run():\n    return bar()\n```\n\n`python_app/utils/foo.py`:\n\n```python\ndef bar():\n    return \"baz\"\n```\n\nThe example below shows:\n\n- how to include content of `app.py` and `utils/foo.py` into your rust binary\n- how to call function `run()` (declared in `app.py`) that needs function\n  imported from `utils/foo.py`\n\n`src/main.rs`:\n\n```rust,ignore\nuse pyo3::prelude::*;\nuse pyo3_ffi::c_str;\n\nfn main() -> PyResult<()> {\n    let py_foo = c_str!(include_str!(concat!(\n        env!(\"CARGO_MANIFEST_DIR\"),\n        \"/python_app/utils/foo.py\"\n    )));\n    let py_app = c_str!(include_str!(concat!(env!(\"CARGO_MANIFEST_DIR\"), \"/python_app/app.py\")));\n    let from_python = Python::attach(|py| -> PyResult<Py<PyAny>> {\n        PyModule::from_code(py, py_foo, c\"foo.py\", c\"utils.foo\")?;\n        let app: Py<PyAny> = PyModule::from_code(py, py_app, c\"app.py\", c\"\")?\n            .getattr(\"run\")?\n            .into();\n        app.call0(py)\n    });\n\n    println!(\"py: {}\", from_python?);\n    Ok(())\n}\n```\n\nThe example below shows:\n\n- how to load content of `app.py` at runtime so that it sees its dependencies\n  automatically\n- how to call function `run()` (declared in `app.py`) that needs function\n  imported from `utils/foo.py`\n\nIt is recommended to use absolute paths because then your binary can be run from anywhere as long as your `app.py` is in the expected directory (in this example that directory is `/usr/share/python_app`).\n\n`src/main.rs`:\n\n```rust,no_run\nuse pyo3::prelude::*;\nuse pyo3::types::PyList;\nuse std::fs;\nuse std::path::Path;\nuse std::ffi::CString;\n\nfn main() -> PyResult<()> {\n    let path = Path::new(\"/usr/share/python_app\");\n    let py_app = CString::new(fs::read_to_string(path.join(\"app.py\"))?)?;\n    let from_python = Python::attach(|py| -> PyResult<Py<PyAny>> {\n        let syspath = py\n            .import(\"sys\")?\n            .getattr(\"path\")?\n            .cast_into::<PyList>()?;\n        syspath.insert(0, path)?;\n        let app: Py<PyAny> = PyModule::from_code(py, py_app.as_c_str(), c\"app.py\", c\"\")?\n            .getattr(\"run\")?\n            .into();\n        app.call0(py)\n    });\n\n    println!(\"py: {}\", from_python?);\n    Ok(())\n}\n```\n\n## Need to use a context manager from Rust?\n\nUse context managers by directly invoking `__enter__` and `__exit__`.\n\n```rust\nuse pyo3::prelude::*;\n\nfn main() {\n    Python::attach(|py| {\n        let custom_manager = PyModule::from_code(\n            py,\n            cr#\"\nclass House(object):\n    def __init__(self, address):\n        self.address = address\n    def __enter__(self):\n        print(f\"Welcome to {self.address}!\")\n    def __exit__(self, type, value, traceback):\n        if type:\n            print(f\"Sorry you had {type} trouble at {self.address}\")\n        else:\n            print(f\"Thank you for visiting {self.address}, come again soon!\")\n\n        \"#,\n            c\"house.py\",\n            c\"house\",\n        )\n        .unwrap();\n\n        let house_class = custom_manager.getattr(\"House\").unwrap();\n        let house = house_class.call1((\"123 Main Street\",)).unwrap();\n\n        house.call_method0(\"__enter__\").unwrap();\n\n        let result = py.eval(c\"undefined_variable + 1\", None, None);\n\n        // If the eval threw an exception we'll pass it through to the context manager.\n        // Otherwise, __exit__  is called with empty arguments (Python \"None\").\n        match result {\n            Ok(_) => {\n                let none = py.None();\n                house\n                    .call_method1(\"__exit__\", (&none, &none, &none))\n                    .unwrap();\n            }\n            Err(e) => {\n                house\n                    .call_method1(\n                        \"__exit__\",\n                        (\n                            e.get_type(py),\n                            e.value(py),\n                            e.traceback(py),\n                        ),\n                    )\n                    .unwrap();\n            }\n        }\n    })\n}\n```\n\n## Handling system signals/interrupts (Ctrl-C)\n\nThe best way to handle system signals when running Rust code is to periodically call `Python::check_signals` to handle any signals captured by Python's signal handler.\nSee also [the FAQ entry](../faq.md#ctrl-c-doesnt-do-anything-while-my-rust-code-is-executing).\n\nAlternatively, set Python's `signal` module to take the default action for a signal:\n\n```rust\nuse pyo3::prelude::*;\n\n# fn main() -> PyResult<()> {\nPython::attach(|py| -> PyResult<()> {\n    let signal = py.import(\"signal\")?;\n    // Set SIGINT to have the default action\n    signal\n        .getattr(\"signal\")?\n        .call1((signal.getattr(\"SIGINT\")?, signal.getattr(\"SIG_DFL\")?))?;\n    Ok(())\n})\n# }\n```\n\n[`py_run!`]: {{#PYO3_DOCS_URL}}/pyo3/macro.py_run.html\n[`Python::run`]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.run\n[`PyModule::new`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.new\n"
  },
  {
    "path": "guide/src/python-from-rust/function-calls.md",
    "content": "# Calling Python functions\n\nThe `Bound<'py, T>` smart pointer (such as `Bound<'py, PyAny>`, `Bound<'py, PyList>`, or `Bound<'py, MyClass>`) can be used to call Python functions.\n\nPyO3 offers two APIs to make function calls:\n\n- [`call`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call) - call any callable Python object.\n- [`call_method`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method) - call a method on the Python object.\n\nBoth of these APIs take `args` and `kwargs` arguments (for positional and keyword arguments respectively).\nThere are variants for less complex calls:\n\n- [`call1`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call1) and [`call_method1`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method1) to call only with positional `args`.\n- [`call0`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call0) and [`call_method0`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.call_method0) to call with no arguments.\n\nFor convenience the [`Py<T>`](../types.md#pyt) smart pointer also exposes these same six API methods, but needs a `Python` token as an additional first argument to prove the thread is attached to the Python interpreter.\n\nThe example below calls a Python function behind a `Py<PyAny>` reference:\n\n```rust\nuse pyo3::prelude::*;\nuse pyo3::types::PyTuple;\n\nfn main() -> PyResult<()> {\n    let arg1 = \"arg1\";\n    let arg2 = \"arg2\";\n    let arg3 = \"arg3\";\n\n    Python::attach(|py| {\n        let fun: Py<PyAny> = PyModule::from_code(\n            py,\n            c\"def example(*args, **kwargs):\n                if args != ():\n                    print('called with args', args)\n                if kwargs != {}:\n                    print('called with kwargs', kwargs)\n                if args == () and kwargs == {}:\n                    print('called with no arguments')\",\n            c\"example.py\",\n            c\"\",\n        )?\n        .getattr(\"example\")?\n        .into();\n\n        // call object without any arguments\n        fun.call0(py)?;\n\n        // pass object with Rust tuple of positional arguments\n        let args = (arg1, arg2, arg3);\n        fun.call1(py, args)?;\n\n        // call object with Python tuple of positional arguments\n        let args = PyTuple::new(py, &[arg1, arg2, arg3])?;\n        fun.call1(py, args)?;\n        Ok(())\n    })\n}\n```\n\n## Creating keyword arguments\n\nFor the `call` and `call_method` APIs, `kwargs` are `Option<&Bound<'py, PyDict>>`, so can either be `None` or `Some(&dict)`.\nYou can use the [`IntoPyDict`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.IntoPyDict.html) trait to convert other dict-like containers, e.g. `HashMap` or `BTreeMap`, as well as tuples with up to 10 elements and `Vec`s where each element is a two-element tuple.\nTo pass keyword arguments of different types, construct a `PyDict` object.\n\n```rust\nuse pyo3::prelude::*;\nuse pyo3::types::{PyDict, IntoPyDict};\nuse std::collections::HashMap;\n\nfn main() -> PyResult<()> {\n    let key1 = \"key1\";\n    let val1 = 1;\n    let key2 = \"key2\";\n    let val2 = 2;\n\n    Python::attach(|py| {\n        let fun: Py<PyAny> = PyModule::from_code(\n            py,\n            c\"def example(*args, **kwargs):\n                if args != ():\n                    print('called with args', args)\n                if kwargs != {}:\n                    print('called with kwargs', kwargs)\n                if args == () and kwargs == {}:\n                    print('called with no arguments')\",\n            c\"example.py\",\n            c\"\",\n        )?\n        .getattr(\"example\")?\n        .into();\n\n        // call object with PyDict\n        let kwargs = [(key1, val1)].into_py_dict(py)?;\n        fun.call(py, (), Some(&kwargs))?;\n\n        // pass arguments as Vec\n        let kwargs = vec![(key1, val1), (key2, val2)];\n        fun.call(py, (), Some(&kwargs.into_py_dict(py)?))?;\n\n        // pass arguments as HashMap\n        let mut kwargs = HashMap::<&str, i32>::new();\n        kwargs.insert(key1, 1);\n        fun.call(py, (), Some(&kwargs.into_py_dict(py)?))?;\n\n        // pass arguments of different types as PyDict\n        let kwargs = PyDict::new(py);\n        kwargs.set_item(key1, val1)?;\n        kwargs.set_item(key2, \"string\")?;\n        fun.call(py, (), Some(&kwargs))?;\n\n        Ok(())\n    })\n}\n```\n"
  },
  {
    "path": "guide/src/python-from-rust.md",
    "content": "# Calling Python in Rust code\n\nThis chapter of the guide documents some ways to interact with Python code from Rust.\n\nBelow is an introduction to the `'py` lifetime and some general remarks about how PyO3's API reasons about Python code.\n\nThe subchapters also cover the following topics:\n\n- Python object types available in PyO3's API\n- How to work with Python exceptions\n- How to call Python functions\n- How to execute existing Python code\n\n## The `'py` lifetime\n\nTo safely interact with the Python interpreter a Rust thread must be [attached] to the Python interpreter.\nPyO3 has a `Python<'py>` token that is used to prove that these conditions are met.\nIts lifetime `'py` is a central part of PyO3's API.\n\nThe `Python<'py>` token serves three purposes:\n\n- It provides global APIs for the Python interpreter, such as [`py.eval()`][eval] and [`py.import()`][import].\n- It can be passed to functions that require a proof of attachment, such as [`Py::clone_ref`][clone_ref].\n- Its lifetime `'py` is used to bind many of PyO3's types to the Python interpreter, such as [`Bound<'py, T>`][Bound].\n\nPyO3's types that are bound to the `'py` lifetime, for example `Bound<'py, T>`, all contain a `Python<'py>` token.\nThis means they have full access to the Python interpreter and offer a complete API for interacting with Python objects.\n\nConsult [PyO3's API documentation][obtaining-py] to learn how to acquire one of these tokens.\n\n### The Global Interpreter Lock\n\nPrior to the introduction of free-threaded Python (first available in 3.13, fully supported in 3.14), the Python interpreter was made thread-safe by the [global interpreter lock].\nThis ensured that only one Python thread can use the Python interpreter and its API at the same time.\nHistorically, Rust code was able to use the GIL as a synchronization guarantee, but the introduction of free-threaded Python removed this possibility.\n\nThe [`pyo3::sync`] module offers synchronization tools which abstract over both Python builds.\n\nTo enable any parallelism on the GIL-enabled build, and best throughput on the free-threaded build, non-Python operations (system calls and native Rust code) should consider detaching from the Python interpreter to allow other work to proceed.\nSee [the section on parallelism](parallelism.md) for how to do that using PyO3's API.\n\n## Python's memory model\n\nPython's memory model differs from Rust's memory model in two key ways:\n\n- There is no concept of ownership; all Python objects are shared and usually implemented via reference counting\n- There is no concept of exclusive (`&mut`) references; any reference can mutate a Python object\n\nPyO3's API reflects this by providing [smart pointer][smart-pointers] types, `Py<T>`, `Bound<'py, T>`, and (the very rarely used) `Borrowed<'a, 'py, T>`.\nThese smart pointers all use Python reference counting.\nSee the [subchapter on types](./types.md) for more detail on these types.\n\nBecause of the lack of exclusive `&mut` references, PyO3's APIs for Python objects, for example [`PyListMethods::append`], use shared references.\nThis is safe because Python objects have internal mechanisms to prevent data races (as of time of writing, the Python GIL).\n\n[attached]: https://docs.python.org/3.14/glossary.html#term-attached-thread-state\n[global interpreter lock]: https://docs.python.org/3/c-api/threads.html#threads\n[smart-pointers]: https://doc.rust-lang.org/book/ch15-00-smart-pointers.html\n[obtaining-py]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#obtaining-a-python-token\n[`pyo3::sync`]: {{#PYO3_DOCS_URL}}/pyo3/sync/index.html\n[eval]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.eval\n[import]: {{#PYO3_DOCS_URL}}/pyo3/marker/struct.Python.html#method.import\n[clone_ref]: {{#PYO3_DOCS_URL}}/pyo3/prelude/struct.Py.html#method.clone_ref\n[Bound]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html\n[`PyListMethods::append`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyListMethods.html#tymethod.append\n"
  },
  {
    "path": "guide/src/python-typing-hints.md",
    "content": "# Typing and IDE hints for your Python package\n\nPyO3 provides an easy to use interface to code native Python libraries in Rust.\nThe accompanying Maturin allows you to build and publish them as a package.\nYet, for a better user experience, Python libraries should provide typing hints and documentation for all public entities, so that IDEs can show them during development and type analyzing tools such as `mypy` can use them to properly verify the code.\n\nCurrently the best solution for the problem is to manually maintain `*.pyi` files and ship them along with the package.\n\nPyO3 is working on automated their generation.\nSee the [type stub generation](type-stub.md) documentation for a description of the current state of automated generation.\n\n## Introduction to `pyi` files\n\n`pyi` files (an abbreviation for `Python Interface`) are called \"stub files\" in most of the documentation related to them.\nA very good definition of what it is can be found in [old MyPy documentation](https://github.com/python/mypy/wiki/Creating-Stubs-For-Python-Modules):\n\n> A stubs file only contains a description of the public interface of the module without any implementations.\n\nThere is also [extensive documentation on type stubs on the official Python typing documentation](https://typing.readthedocs.io/en/latest/source/stubs.html).\n\nMost Python developers probably already encountered them when trying to use their IDE's \"Go to Definition\" function on any builtin type.\nFor example, the definitions of a few standard exceptions look like this:\n\n```python\nclass BaseException(object):\n    args: Tuple[Any, ...]\n    __cause__: BaseException | None\n    __context__: BaseException | None\n    __suppress_context__: bool\n    __traceback__: TracebackType | None\n    def __init__(self, *args: object) -> None: ...\n    def __str__(self) -> str: ...\n    def __repr__(self) -> str: ...\n    def with_traceback(self: _TBE, tb: TracebackType | None) -> _TBE: ...\n\nclass SystemExit(BaseException):\n    code: int\n\nclass Exception(BaseException): ...\n\nclass StopIteration(Exception):\n    value: Any\n```\n\nAs we can see, those are not full definitions containing implementation, but just a description of the interface.\nIt is usually all that the user of the library needs.\n\n### What do the PEPs say?\n\nAt the time of writing this documentation, the `pyi` files are referenced in four PEPs.\n\n[PEP8 - Style Guide for Python Code - #Function Annotations](https://www.python.org/dev/peps/pep-0008/#function-annotations) (last point) recommends all third party library creators to provide stub files as the source of knowledge about the package for type checker tools.\n\n> (...) it is expected that users of third party library packages may want to run type checkers over those packages. For this purpose [PEP 484](https://www.python.org/dev/peps/pep-0484) recommends the use of stub files: .pyi files that are read by the type checker in preference of the corresponding .py files. (...)\n\n[PEP484 - Type Hints - #Stub Files](https://www.python.org/dev/peps/pep-0484/#stub-files) defines stub files as follows.\n\n> Stub files are files containing type hints that are only for use by the type checker, not at runtime.\n\nIt contains a specification for them (highly recommended reading, since it contains at least one thing that is not used in normal Python code) and also some general information about where to store the stub files.\n\n[PEP561 - Distributing and Packaging Type Information](https://www.python.org/dev/peps/pep-0561/) describes in detail how to build packages that will enable type checking.\nIn particular it contains information about how the stub files must be distributed in order for type checkers to use them.\n\n[PEP560 - Core support for typing module and generic types](https://www.python.org/dev/peps/pep-0560/) describes the details on how Python's type system internally supports generics, including both runtime behavior and integration with static type checkers.\n\n## How to do it?\n\n[PEP561](https://www.python.org/dev/peps/pep-0561/) recognizes three ways of distributing type information:\n\n- `inline` - the typing is placed directly in source (`py`) files;\n- `separate package with stub files` - the typing is placed in `pyi` files distributed in their own, separate package;\n- `in-package stub files` - the typing is placed in `pyi` files distributed in the same package as source files.\n\nThe first way is tricky with PyO3 since we do not have `py` files.\nWhen it has been investigated and necessary changes are implemented, this document will be updated.\n\nThe second way is easy to do, and the whole work can be fully separated from the main library code.\nThe example repo for the package with stub files can be found in [PEP561 references section](https://www.python.org/dev/peps/pep-0561/#references): [Stub package repository](https://github.com/ethanhs/stub-package)\n\nThe third way is described below.\n\n### Including `pyi` files in your PyO3/Maturin build package\n\nWhen source files are in the same package as stub files, they should be placed next to each other.\nWe need a way to do that with Maturin.\nAlso, in order to mark our package as typing-enabled we need to add an empty file named `py.typed` to the package.\n\n#### If you do not have other Python files\n\nIf you do not need to add any other Python files apart from `pyi` to the package, Maturin provides a way to do most of the work for you.\nAs documented in the [Maturin Guide](https://github.com/PyO3/maturin/#mixed-rustpython-projects), the only thing you need to do is to create a stub file for your module named `<module_name>.pyi` in your project root and Maturin will do the rest.\n\n```text\nmy-rust-project/\n├── Cargo.toml\n├── my_project.pyi  # <<< add type stubs for Rust functions in the my_project module here\n├── pyproject.toml\n└── src\n    └── lib.rs\n```\n\nFor an example `pyi` file see the [`my_project.pyi` content](#my_projectpyi-content) section.\n\n#### If you need other Python files\n\nIf you need to add other Python files apart from `pyi` to the package, you can do it also, but that requires some more work.\nMaturin provides an easy way to add files to a package ([documentation](https://github.com/PyO3/maturin/blob/0dee40510083c03607834c821eea76964140a126/Readme.md#mixed-rustpython-projects)).\nYou just need to create a folder with the name of your module next to the `Cargo.toml` file (for customization see documentation linked above).\n\nThe folder structure would be:\n\n```text\nmy-project\n├── Cargo.toml\n├── my_project\n│   ├── __init__.py\n│   ├── my_project.pyi\n│   ├── other_python_file.py\n│   └── py.typed\n├── pyproject.toml\n├── Readme.md\n└── src\n    └── lib.rs\n```\n\nLet's go a little bit more into detail regarding the files inside the package folder.\n\n##### `__init__.py` content\n\nAs we now specify our own package content, we have to provide the `__init__.py` file, so the folder is treated as a package and we can import things from it.\nWe can always use the same content that Maturin creates for us if we do not specify a Python source folder.\nFor PyO3 bindings it would be:\n\n```python\nfrom .my_project import *\n```\n\nThat way everything that is exposed by our native module can be imported directly from the package.\n\n##### `py.typed` requirement\n\nAs stated in [PEP561](https://www.python.org/dev/peps/pep-0561/):\n> Package maintainers who wish to support type checking of their code MUST add a marker file named py.typed to their package supporting typing. This marker applies recursively: if a top-level package includes it, all its sub-packages MUST support type checking as well.\n\nIf we do not include that file, some IDEs might still use our `pyi` files to show hints, but the type checkers might not.\nMyPy will raise an error in this situation:\n\n```text\nerror: Skipping analyzing \"my_project\": found module but no type hints or library stubs\n```\n\nThe file is just a marker file, so it should be empty.\n\n##### `my_project.pyi` content\n\nOur module stub file.\nThis document does not aim at describing how to write them, since you can find a lot of documentation on it, starting from the already quoted [PEP484](https://www.python.org/dev/peps/pep-0484/#stub-files).\n\nThe example can look like this:\n\n```python\nclass Car:\n    \"\"\"\n    A class representing a car.\n\n    :param body_type: the name of body type, e.g. hatchback, sedan\n    :param horsepower: power of the engine in horsepower\n    \"\"\"\n    def __init__(self, body_type: str, horsepower: int) -> None: ...\n\n    @classmethod\n    def from_unique_name(cls, name: str) -> 'Car':\n        \"\"\"\n        Creates a Car based on unique name\n\n        :param name: model name of a car to be created\n        :return: a Car instance with default data\n        \"\"\"\n\n    def best_color(self) -> str:\n        \"\"\"\n        Gets the best color for the car.\n\n        :return: the name of the color our great algorithm thinks is the best for this car\n        \"\"\"\n```\n\n### Supporting Generics\n\nType annotations can also be made generic in Python.\nThey are useful for working with different types while maintaining type safety.\nUsually, generic classes inherit from the `typing.Generic` metaclass.\n\nTake for example the following `.pyi` file that specifies a `Car` that can accept multiple types of wheels:\n\n```python\nfrom typing import Generic, TypeVar\n\nW = TypeVar('W')\n\nclass Car(Generic[W]):\n    def __init__(self, wheels: list[W]) -> None: ...\n\n    def get_wheels(self) -> list[W]: ...\n\n    def change_wheel(self, wheel_number: int, wheel: W) -> None: ...\n```\n\nThis way, the end-user can specify the type with variables such as `truck: Car[SteelWheel] = ...` and `f1_car: Car[AlloyWheel] = ...`.\n\nThere is also a special syntax for specifying generic types in Python 3.12+:\n\n```python\nclass Car[W]:\n    def __init__(self, wheels: list[W]) -> None: ...\n\n    def get_wheels(self) -> list[W]: ...\n```\n\n#### Runtime Behaviour\n\nStub files (`pyi`) are only useful for static type checkers and ignored at runtime.\nTherefore, PyO3 classes do not inherit from `typing.Generic` even if specified in the stub files.\n\nThis can cause some runtime issues, as annotating a variable like `f1_car: Car[AlloyWheel] = ...` can make Python call magic methods that are not defined.\n\nTo overcome this limitation, implementers can pass the `generic` parameter to `pyclass` in Rust:\n\n```rust ignore\n#[pyclass(generic)]\n```\n\n#### Advanced Users\n\n`#[pyclass(generic)]` implements a very simple runtime behavior that accepts any generic argument.\nAdvanced users can opt to manually implement [`__class_getitem__`](https://docs.python.org/3/reference/datamodel.html#emulating-generic-types) for the generic class to have more control.\n\n```rust ignore\nimpl MyClass {\n    #[classmethod]\n    #[pyo3(signature = (key, /))]\n    pub fn __class_getitem__(\n        cls: &Bound<'_, PyType>,\n        key: &Bound<'_, PyAny>,\n    ) -> PyResult<Py<PyAny>> {\n        /* implementation details */\n    }\n}\n```\n\nNote that [`pyo3::types::PyGenericAlias`][pygenericalias] can be helpful when implementing `__class_getitem__` as it can create [`types.GenericAlias`][genericalias] objects from Rust.\n\n[pygenericalias]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyGenericAlias.html\n[genericalias]: https://docs.python.org/3/library/types.html#types.GenericAlias\n"
  },
  {
    "path": "guide/src/rust-from-python.md",
    "content": "# Using Rust from Python\n\nThis chapter of the guide is dedicated to explaining how to wrap Rust code into Python objects.\n\nPyO3 uses Rust's \"procedural macros\" to provide a powerful yet simple API to denote what Rust code should map into Python objects.\n\nPyO3 can create three types of Python objects:\n\n- Python modules, via the `#[pymodule]` macro\n- Python functions, via the `#[pyfunction]` macro\n- Python classes, via the `#[pyclass]` macro (plus `#[pymethods]` to define methods for those classes)\n\nThe following subchapters go through each of these in turn.\n"
  },
  {
    "path": "guide/src/trait-bounds.md",
    "content": "# Using in Python a Rust function with trait bounds\n\nPyO3 allows for easy conversion from Rust to Python for certain functions and classes (see the [conversion table](conversions/tables.md)).\nHowever, it is not always straightforward to convert Rust code that requires a given trait implementation as an argument.\n\nThis tutorial explains how to convert a Rust function that takes a trait as argument for use in Python with classes implementing the same methods as the trait.\n\nWhy is this useful?\n\n## Pros\n\n- Make your Rust code available to Python users\n- Code complex algorithms in Rust with the help of the borrow checker\n\n### Cons\n\n- Not as fast as native Rust (type conversion has to be performed and one part of the code runs in Python)\n- You need to adapt your code to expose it\n\n## Example\n\nLet's work with the following basic example of an implementation of a optimization solver operating on a given model.\n\nLet's say we have a function `solve` that operates on a model and mutates its state.\nThe argument of the function can be any model that implements the `Model` trait :\n\n```rust,no_run\n# #![allow(dead_code)]\npub trait Model {\n    fn set_variables(&mut self, inputs: &Vec<f64>);\n    fn compute(&mut self);\n    fn get_results(&self) -> Vec<f64>;\n}\n\npub fn solve<T: Model>(model: &mut T) {\n    println!(\"Magic solver that mutates the model into a resolved state\");\n}\n```\n\nLet's assume we have the following constraints:\n\n- We cannot change that code as it runs on many Rust models.\n- We also have many Python models that cannot be solved as this solver is not available in that language.\n\nRewriting it in Python would be cumbersome and error-prone, as everything is already available in Rust.\n\nHow could we expose this solver to Python thanks to PyO3 ?\n\n## Implementation of the trait bounds for the Python class\n\nIf a Python class implements the same three methods as the `Model` trait, it seems logical it could be adapted to use the solver.\nHowever, it is not possible to pass a `Py<PyAny>` to it as it does not implement the Rust trait (even if the Python model has the required methods).\n\nIn order to implement the trait, we must write a wrapper around the calls in Rust to the Python model.\nThe method signatures must be the same as the trait, keeping in mind that the Rust trait cannot be changed for the purpose of making the code available in Python.\n\nThe Python model we want to expose is the following one, which already contains all the required methods:\n\n```python\nclass Model:\n    def set_variables(self, inputs):\n        self.inputs = inputs\n    def compute(self):\n        self.results = [elt**2 - 3 for elt in self.inputs]\n    def get_results(self):\n        return self.results\n```\n\nThe following wrapper will call the Python model from Rust, using a struct to hold the model as a `PyAny` object:\n\n```rust,no_run\n# #![allow(dead_code)]\nuse pyo3::prelude::*;\nuse pyo3::types::PyList;\n\n# pub trait Model {\n#   fn set_variables(&mut self, inputs: &Vec<f64>);\n#   fn compute(&mut self);\n#   fn get_results(&self) -> Vec<f64>;\n# }\n\nstruct UserModel {\n    model: Py<PyAny>,\n}\n\nimpl Model for UserModel {\n    fn set_variables(&mut self, var: &Vec<f64>) {\n        println!(\"Rust calling Python to set the variables\");\n        Python::attach(|py| {\n            self.model\n                .bind(py)\n                .call_method(\"set_variables\", (PyList::new(py, var).unwrap(),), None)\n                .unwrap();\n        })\n    }\n\n    fn get_results(&self) -> Vec<f64> {\n        println!(\"Rust calling Python to get the results\");\n        Python::attach(|py| {\n            self.model\n                .bind(py)\n                .call_method(\"get_results\", (), None)\n                .unwrap()\n                .extract()\n                .unwrap()\n        })\n    }\n\n    fn compute(&mut self) {\n        println!(\"Rust calling Python to perform the computation\");\n        Python::attach(|py| {\n            self.model\n                .bind(py)\n                .call_method(\"compute\", (), None)\n                .unwrap();\n        })\n    }\n}\n```\n\nNow that this bit is implemented, let's expose the model wrapper to Python.\nLet's add the PyO3 annotations and add a constructor:\n\n```rust,no_run\n# #![allow(dead_code)]\n# fn main() {}\n# pub trait Model {\n#   fn set_variables(&mut self, inputs: &Vec<f64>);\n#   fn compute(&mut self);\n#   fn get_results(&self) -> Vec<f64>;\n# }\n# use pyo3::prelude::*;\n\n#[pyclass]\nstruct UserModel {\n    model: Py<PyAny>,\n}\n\n#[pymethods]\nimpl UserModel {\n    #[new]\n    pub fn new(model: Py<PyAny>) -> Self {\n        UserModel { model }\n    }\n}\n\n#[pymodule]\nmod trait_exposure {\n    #[pymodule_export]\n    use super::UserModel;\n}\n```\n\nNow we add the PyO3 annotations to the trait implementation:\n\n```rust,ignore\n#[pymethods]\nimpl Model for UserModel {\n    // the previous trait implementation\n}\n```\n\nHowever, the previous code will not compile.\nThe compilation error is the following one: `error: #[pymethods] cannot be used on trait impl blocks`\n\nThat's a bummer!\nHowever, we can write a second wrapper around these functions to call them directly.\nThis wrapper will also perform the type conversions between Python and Rust.\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use pyo3::types::PyList;\n#\n# pub trait Model {\n#   fn set_variables(&mut self, inputs: &Vec<f64>);\n#   fn compute(&mut self);\n#   fn get_results(&self) -> Vec<f64>;\n# }\n#\n# #[pyclass]\n# struct UserModel {\n#     model: Py<PyAny>,\n# }\n#\n# impl Model for UserModel {\n#  fn set_variables(&mut self, var: &Vec<f64>) {\n#      println!(\"Rust calling Python to set the variables\");\n#      Python::attach(|py| {\n#          self.model.bind(py)\n#              .call_method(\"set_variables\", (PyList::new(py, var).unwrap(),), None)\n#              .unwrap();\n#      })\n#  }\n#\n#  fn get_results(&self) -> Vec<f64> {\n#      println!(\"Rust calling Python to get the results\");\n#      Python::attach(|py| {\n#          self.model\n#              .bind(py)\n#              .call_method(\"get_results\", (), None)\n#              .unwrap()\n#              .extract()\n#              .unwrap()\n#      })\n#  }\n#\n#  fn compute(&mut self) {\n#      println!(\"Rust calling Python to perform the computation\");\n#      Python::attach(|py| {\n#          self.model\n#              .bind(py)\n#              .call_method(\"compute\", (), None)\n#              .unwrap();\n#      })\n#\n#  }\n# }\n\n#[pymethods]\nimpl UserModel {\n    pub fn set_variables(&mut self, var: Vec<f64>) {\n        println!(\"Set variables from Python calling Rust\");\n        Model::set_variables(self, &var)\n    }\n\n    pub fn get_results(&mut self) -> Vec<f64> {\n        println!(\"Get results from Python calling Rust\");\n        Model::get_results(self)\n    }\n\n    pub fn compute(&mut self) {\n        println!(\"Compute from Python calling Rust\");\n        Model::compute(self)\n    }\n}\n```\n\nThis wrapper handles the type conversion between the PyO3 requirements and the trait.\nIn order to meet PyO3 requirements, this wrapper must:\n\n- return an object of type `PyResult`\n- use only values, not references in the method signatures\n\nLet's run the file python file:\n\n```python\nclass Model:\n    def set_variables(self, inputs):\n        self.inputs = inputs\n    def compute(self):\n        self.results = [elt**2 - 3 for elt in self.inputs]\n    def get_results(self):\n        return self.results\n\nif __name__==\"__main__\":\n  import trait_exposure\n\n  myModel = Model()\n  my_rust_model = trait_exposure.UserModel(myModel)\n  my_rust_model.set_variables([2.0])\n  print(\"Print value from Python: \", myModel.inputs)\n  my_rust_model.compute()\n  print(\"Print value from Python through Rust: \", my_rust_model.get_results())\n  print(\"Print value directly from Python: \", myModel.get_results())\n```\n\nThis outputs:\n\n```block\nSet variables from Python calling Rust\nSet variables from Rust calling Python\nPrint value from Python:  [2.0]\nCompute from Python calling Rust\nCompute from Rust calling Python\nGet results from Python calling Rust\nGet results from Rust calling Python\nPrint value from Python through Rust:  [1.0]\nPrint value directly from Python:  [1.0]\n```\n\nWe have now successfully exposed a Rust model that implements the `Model` trait to Python!\n\nWe will now expose the `solve` function, but before, let's talk about types errors.\n\n## Type errors in Python\n\nWhat happens if you have type errors when using Python and how can you improve the error messages?\n\n### Wrong types in Python function arguments\n\nLet's assume in the first case that you will use in your Python file `my_rust_model.set_variables(2.0)` instead of `my_rust_model.set_variables([2.0])`.\n\nThe Rust signature expects a vector, which corresponds to a list in Python.\nWhat happens if instead of a vector, we pass a single value ?\n\nAt the execution of Python, we get :\n\n```block\nFile \"main.py\", line 15, in <module>\n   my_rust_model.set_variables(2)\nTypeError\n```\n\nIt is a type error and Python points to it, so it's easy to identify and solve.\n\n### Wrong types in Python method signatures\n\nLet's assume now that the return type of one of the methods of our Model class is wrong, for example the `get_results` method that is expected to return a `Vec<f64>` in Rust, a list in Python.\n\n```python\nclass Model:\n    def set_variables(self, inputs):\n        self.inputs = inputs\n    def compute(self):\n        self.results = [elt**2 -3 for elt in self.inputs]\n    def get_results(self):\n        return self.results[0]\n        #return self.results <-- this is the expected output\n```\n\nThis call results in the following panic:\n\n```block\npyo3_runtime.PanicException: called `Result::unwrap()` on an `Err` value: PyErr { type: Py(0x10dcf79f0, PhantomData) }\n```\n\nThis error code is not helpful for a Python user that does not know anything about Rust, or someone that does not know PyO3 was used to interface the Rust code.\n\nHowever, as we are responsible for making the Rust code available to Python, we can do something about it.\n\nThe issue is that we called `unwrap` anywhere we could, and therefore any panic from PyO3 will be directly forwarded to the end user.\n\nLet's modify the code performing the type conversion to give a helpful error message to the Python user:\n\nWe used in our `get_results` method the following call that performs the type conversion:\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use pyo3::types::PyList;\n#\n# pub trait Model {\n#   fn set_variables(&mut self, inputs: &Vec<f64>);\n#   fn compute(&mut self);\n#   fn get_results(&self) -> Vec<f64>;\n# }\n#\n# #[pyclass]\n# struct UserModel {\n#     model: Py<PyAny>,\n# }\n\nimpl Model for UserModel {\n    fn get_results(&self) -> Vec<f64> {\n        println!(\"Rust calling Python to get the results\");\n        Python::attach(|py| {\n            self.model\n                .bind(py)\n                .call_method(\"get_results\", (), None)\n                .unwrap()\n                .extract()\n                .unwrap()\n        })\n    }\n#     fn set_variables(&mut self, var: &Vec<f64>) {\n#         println!(\"Rust calling Python to set the variables\");\n#         Python::attach(|py| {\n#             self.model.bind(py)\n#                 .call_method(\"set_variables\", (PyList::new(py, var).unwrap(),), None)\n#                 .unwrap();\n#         })\n#     }\n#\n#     fn compute(&mut self) {\n#         println!(\"Rust calling Python to perform the computation\");\n#         Python::attach(|py| {\n#             self.model\n#                 .bind(py)\n#                 .call_method(\"compute\", (), None)\n#                 .unwrap();\n#         })\n#     }\n}\n```\n\nLet's break it down in order to perform better error handling:\n\n```rust,no_run\n# #![allow(dead_code)]\n# use pyo3::prelude::*;\n# use pyo3::types::PyList;\n#\n# pub trait Model {\n#   fn set_variables(&mut self, inputs: &Vec<f64>);\n#   fn compute(&mut self);\n#   fn get_results(&self) -> Vec<f64>;\n# }\n#\n# #[pyclass]\n# struct UserModel {\n#     model: Py<PyAny>,\n# }\n\nimpl Model for UserModel {\n    fn get_results(&self) -> Vec<f64> {\n        println!(\"Get results from Rust calling Python\");\n        Python::attach(|py| {\n            let py_result: Bound<'_, PyAny> = self\n                .model\n                .bind(py)\n                .call_method(\"get_results\", (), None)\n                .unwrap();\n\n            if py_result.get_type().name().unwrap() != \"list\" {\n                panic!(\n                    \"Expected a list for the get_results() method signature, got {}\",\n                    py_result.get_type().name().unwrap()\n                );\n            }\n            py_result.extract()\n        })\n        .unwrap()\n    }\n#     fn set_variables(&mut self, var: &Vec<f64>) {\n#         println!(\"Rust calling Python to set the variables\");\n#         Python::attach(|py| {\n#             let py_model = self.model.bind(py)\n#                 .call_method(\"set_variables\", (PyList::new(py, var).unwrap(),), None)\n#                 .unwrap();\n#         })\n#     }\n#\n#     fn compute(&mut self) {\n#         println!(\"Rust calling Python to perform the computation\");\n#         Python::attach(|py| {\n#             self.model\n#                 .bind(py)\n#                 .call_method(\"compute\", (), None)\n#                 .unwrap();\n#         })\n#     }\n}\n```\n\nBy doing so, you catch the result of the Python computation and check its type in order to be able to deliver a better error message before performing the unwrapping.\n\nOf course, it does not cover all the possible wrong outputs: the user could return a list of strings instead of a list of floats.\nIn this case, a runtime panic would still occur due to PyO3, but with an error message much more difficult to decipher for non-rust user.\n\nIt is up to the developer exposing the rust code to decide how much effort to invest into Python type error handling and improved error messages.\n\n## The final code\n\nNow let's expose the `solve()` function to make it available from Python.\n\nIt is not possible to directly expose the `solve` function to Python, as the type conversion cannot be performed.\nIt requires an object implementing the `Model` trait as input.\n\nHowever, the `UserModel` already implements this trait.\nBecause of this, we can write a function wrapper that takes the `UserModel`--which has already been exposed to Python--as an argument in order to call the core function `solve`.\n\nIt is also required to make the struct public.\n\n```rust,no_run\n# #![allow(dead_code)]\n# fn main() {}\nuse pyo3::prelude::*;\nuse pyo3::types::PyList;\n\npub trait Model {\n    fn set_variables(&mut self, var: &Vec<f64>);\n    fn get_results(&self) -> Vec<f64>;\n    fn compute(&mut self);\n}\n\npub fn solve<T: Model>(model: &mut T) {\n    println!(\"Magic solver that mutates the model into a resolved state\");\n}\n\n#[pyfunction]\n#[pyo3(name = \"solve\")]\npub fn solve_wrapper(model: &mut UserModel) {\n    solve(model);\n}\n\n#[pyclass]\npub struct UserModel {\n    model: Py<PyAny>,\n}\n\n#[pymethods]\nimpl UserModel {\n    #[new]\n    pub fn new(model: Py<PyAny>) -> Self {\n        UserModel { model }\n    }\n\n    pub fn set_variables(&mut self, var: Vec<f64>) {\n        println!(\"Set variables from Python calling Rust\");\n        Model::set_variables(self, &var)\n    }\n\n    pub fn get_results(&mut self) -> Vec<f64> {\n        println!(\"Get results from Python calling Rust\");\n        Model::get_results(self)\n    }\n\n    pub fn compute(&mut self) {\n        Model::compute(self)\n    }\n}\n\n#[pymodule]\nmod trait_exposure {\n    #[pymodule_export]\n    use super::{UserModel, solve_wrapper};\n}\n\nimpl Model for UserModel {\n    fn set_variables(&mut self, var: &Vec<f64>) {\n        println!(\"Rust calling Python to set the variables\");\n        Python::attach(|py| {\n            self.model\n                .bind(py)\n                .call_method(\"set_variables\", (PyList::new(py, var).unwrap(),), None)\n                .unwrap();\n        })\n    }\n\n    fn get_results(&self) -> Vec<f64> {\n        println!(\"Get results from Rust calling Python\");\n        Python::attach(|py| {\n            let py_result: Bound<'_, PyAny> = self\n                .model\n                .bind(py)\n                .call_method(\"get_results\", (), None)\n                .unwrap();\n\n            if py_result.get_type().name().unwrap() != \"list\" {\n                panic!(\n                    \"Expected a list for the get_results() method signature, got {}\",\n                    py_result.get_type().name().unwrap()\n                );\n            }\n            py_result.extract()\n        })\n        .unwrap()\n    }\n\n    fn compute(&mut self) {\n        println!(\"Rust calling Python to perform the computation\");\n        Python::attach(|py| {\n            self.model\n                .bind(py)\n                .call_method(\"compute\", (), None)\n                .unwrap();\n        })\n    }\n}\n```\n"
  },
  {
    "path": "guide/src/type-stub.md",
    "content": "# Type stub generation (`*.pyi` files) and introspection\n\n*This feature is still in active development.*\n*See [the related issue](https://github.com/PyO3/pyo3/issues/5137).*\n\n*For documentation on type stubs and how to use them with stable PyO3, refer to [this page](python-typing-hints.md)*\n\nPyO3 has a work in progress support to generate [type stub files](https://typing.python.org/en/latest/spec/distributing.html#stub-files).\n\nIt works using:\n\n1. PyO3 macros (`#[pyclass]`) that generate constant JSON strings that are then included in the built binaries by rustc if the `experimental-inspect` feature is enabled.\n2. The `pyo3-introspection` crate that can parse the generated binaries, extract the JSON strings and build stub files from it.\n3. \\[Not done yet\\] Build tools like `maturin` exposing `pyo3-introspection` features in their CLI API.\n\nFor example, the following Rust code\n\n```rust\n#[pymodule]\npub mod example {\n    use pyo3::prelude::*;\n\n    #[pymodule_export]\n    pub const CONSTANT: &str = \"FOO\";\n\n    #[pyclass(eq)]\n    #[derive(Eq)]\n    struct Class {\n        value: usize\n    }\n\n    #[pymethods]\n    impl Class {\n        #[new]\n        fn new(value: usize) -> Self {\n            Self { value }\n        }\n\n        #[getter]\n        fn value(&self) -> usize {\n            self.value\n        }\n    }\n\n    #[pyfunction]\n    #[pyo3(signature = (arg: \"list[int]\") -> \"list[int]\")]\n    fn list_of_int_identity(arg: Bound<'_, PyAny>) -> Bound<'_, PyAny> {\n        arg\n    }\n}\n```\n\nwill generate the following stub file:\n\n```python\nimport typing\n\nCONSTANT: typing.Final = \"FOO\"\n\nclass Class:\n    def __init__(self, value: int) -> None: ...\n\n    @property\n    def value(self) -> int: ...\n\n    def __eq__(self, other: Class) -> bool: ...\n    def __ne__(self, other: Class) -> bool: ...\n\ndef list_of_int_identity(arg: list[int]) -> list[int]: ...\n```\n\nThe only piece of added syntax is that the `#[pyo3(signature = ...)]` attribute can now contain type annotations like `#[pyo3(signature = (arg: \"list[int]\") -> \"list[int]\")]` (note the `\"\"` around type annotations).\nThis is useful when PyO3 is not able to derive proper type annotations by itself.\n\n## Constraints and limitations\n\n- The `experimental-inspect` feature is required to generate the introspection fragments.\n- Lots of features are not implemented yet.\n  See [the related issue](https://github.com/PyO3/pyo3/issues/5137) for a list of them.\n- Introspection only works with Python modules declared with an inline Rust module.\n  Modules declared using a function are not supported.\n- `FromPyObject::INPUT_TYPE` and `IntoPyObject::OUTPUT_TYPE` must be implemented for PyO3 to get the proper input/output type annotations to use.\n- PyO3 is not able to introspect the content of `#[pymodule]` and `#[pymodule_init]` functions.\n  If they are present, the module is tagged as incomplete using a fake `def __getattr__(name: str) -> Incomplete: ...` function [following best practices](https://typing.python.org/en/latest/guides/writing_stubs.html#incomplete-stubs).\n"
  },
  {
    "path": "guide/src/types.md",
    "content": "# Python object types\n\nPyO3 offers two main sets of types to interact with Python objects.\nThis section of the guide expands into detail about these types and how to choose which to use.\n\nThe first set of types are the [smart pointers][smart-pointers] which all Python objects are wrapped in.\nThese are `Py<T>`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`.\nThe [first section below](#pyo3s-smart-pointers) expands on each of these in detail and why there are three of them.\n\nThe second set of types are types which fill in the generic parameter `T` of the smart pointers.\nThe most common is `PyAny`, which represents any Python object (similar to Python's `typing.Any`).\nThere are also concrete types for many Python built-in types, such as `PyList`, `PyDict`, and `PyTuple`.\nUser defined `#[pyclass]` types also fit this category.\nThe [second section below](#concrete-python-types) expands on how to use these types.\n\n## PyO3's smart pointers\n\nPyO3's API offers three generic smart pointers: `Py<T>`, `Bound<'py, T>` and `Borrowed<'a, 'py, T>`.\nFor each of these the type parameter `T` will be filled by a [concrete Python type](#concrete-python-types).\nFor example, a Python list object can be represented by `Py<PyList>`, `Bound<'py, PyList>`, and `Borrowed<'a, 'py, PyList>`.\n\nThese smart pointers behave differently due to their lifetime parameters. `Py<T>` has no lifetime parameters, `Bound<'py, T>` has [the `'py` lifetime](./python-from-rust.md#the-py-lifetime) as a parameter, and `Borrowed<'a, 'py, T>` has the `'py` lifetime plus an additional lifetime `'a` to denote the lifetime it is borrowing data for. (You can read more about these lifetimes in the subsections below).\n\nPython objects are reference counted, like [`std::sync::Arc`](https://doc.rust-lang.org/stable/std/sync/struct.Arc.html).\nA major reason for these smart pointers is to bring Python's reference counting to a Rust API.\n\nThe recommendation of when to use each of these smart pointers is as follows:\n\n- Use `Bound<'py, T>` for as much as possible, as it offers the most efficient and complete API.\n- Use `Py<T>` mostly just for storage inside Rust `struct`s which do not want to or can't add a lifetime parameter for `Bound<'py, T>`.\n- `Borrowed<'a, 'py, T>` is almost never used.\n  It is occasionally present at the boundary between Rust and the Python interpreter, for example when borrowing data from Python tuples (which is safe because they are immutable).\n\nThe sections below also explain these smart pointers in a little more detail.\n\n### `Py<T>`\n\n[`Py<T>`][Py] is the foundational smart pointer in PyO3's API.\nThe type parameter `T` denotes the type of the Python object.\nVery frequently this is `PyAny`, meaning any Python object.\n\nBecause `Py<T>` is not bound to [the `'py` lifetime](./python-from-rust.md#the-py-lifetime), it is the type to use when storing a Python object inside a Rust `struct` or `enum` which do not want to have a lifetime parameter.\nIn particular, [`#[pyclass]`][pyclass] types are not permitted to have a lifetime, so `Py<T>` is the correct type to store Python objects inside them.\n\nThe lack of binding to the `'py` lifetime also carries drawbacks:\n\n- Almost all methods on `Py<T>` require a `Python<'py>` token as the first argument\n- Other functionality, such as [`Drop`][Drop], needs to check at runtime for attachment to the Python interpreter, at a small performance cost\n\nBecause of the drawbacks `Bound<'py, T>` is preferred for many of PyO3's APIs.\nIn particular, `Bound<'py, T>` is better for function arguments.\n\nTo convert a `Py<T>` into a `Bound<'py, T>`, the `Py::bind` and `Py::into_bound` methods are available. `Bound<'py, T>` can be converted back into `Py<T>` using [`Bound::unbind`].\n\n### `Bound<'py, T>`\n\n[`Bound<'py, T>`][Bound] is the counterpart to `Py<T>` which is also bound to the `'py` lifetime.\nIt can be thought of as equivalent to the Rust tuple `(Python<'py>, Py<T>)`.\n\nBy having the binding to the `'py` lifetime, `Bound<'py, T>` can offer the complete PyO3 API at maximum efficiency.\nThis means that `Bound<'py, T>` should usually be used whenever carrying this lifetime is acceptable, and `Py<T>` otherwise.\n\n`Bound<'py, T>` engages in Python reference counting.\nThis means that `Bound<'py, T>` owns a Python object.\nRust code which just wants to borrow a Python object should use a shared reference `&Bound<'py, T>`.\nJust like `std::sync::Arc`, using `.clone()` and `drop()` will cheaply increment and decrement the reference count of the object (just in this case, the reference counting is implemented by the Python interpreter itself).\n\nTo give an example of how `Bound<'py, T>` is PyO3's primary API type, consider the following Python code:\n\n```python\ndef example():\n    x = list()   # create a Python list\n    x.append(1)  # append the integer 1 to it\n    y = x        # create a second reference to the list\n    del x        # delete the original reference\n```\n\nUsing PyO3's API, and in particular `Bound<'py, PyList>`, this code translates into the following Rust code:\n\n```rust\nuse pyo3::prelude::*;\nuse pyo3::types::PyList;\n\nfn example<'py>(py: Python<'py>) -> PyResult<()> {\n    let x: Bound<'py, PyList> = PyList::empty(py);\n    x.append(1)?;\n    let y: Bound<'py, PyList> = x.clone(); // y is a new reference to the same list\n    drop(x); // release the original reference x\n    Ok(())\n}\n# Python::attach(example).unwrap();\n```\n\nOr, without the type annotations:\n\n```rust\nuse pyo3::prelude::*;\nuse pyo3::types::PyList;\n\nfn example(py: Python<'_>) -> PyResult<()> {\n    let x = PyList::empty(py);\n    x.append(1)?;\n    let y = x.clone();\n    drop(x);\n    Ok(())\n}\n# Python::attach(example).unwrap();\n```\n\n#### Function argument lifetimes\n\nBecause the `'py` lifetime often appears in many function arguments as part of the `Bound<'py, T>` smart pointer, the Rust compiler will often require annotations of input and output lifetimes.\nThis occurs when the function output has at least one lifetime, and there is more than one lifetime present on the inputs.\n\nTo demonstrate, consider this function which takes accepts Python objects and applies the [Python `+` operation][PyAnyMethods::add] to them:\n\n```rust,compile_fail\n# use pyo3::prelude::*;\nfn add(left: &'_ Bound<'_, PyAny>, right: &'_ Bound<'_, PyAny>) -> PyResult<Bound<'_, PyAny>> {\n    left.add(right)\n}\n```\n\nBecause the Python `+` operation might raise an exception, this function returns `PyResult<Bound<'_, PyAny>>`.\nIt doesn't need ownership of the inputs, so it takes `&Bound<'_, PyAny>` shared references.\nTo demonstrate the point, all lifetimes have used the wildcard `'_` to allow the Rust compiler to attempt to infer them.\nBecause there are four input lifetimes (two lifetimes of the shared references, and two `'py` lifetimes unnamed inside the `Bound<'_, PyAny>` pointers), the compiler cannot reason about which must be connected to the output.\n\nThe correct way to solve this is to add the `'py` lifetime as a parameter for the function, and name all the `'py` lifetimes inside the `Bound<'py, PyAny>` smart pointers.\nFor the shared references, it's also fine to reduce `&'_` to just `&`.\nThe working end result is below:\n\n```rust\n# use pyo3::prelude::*;\nfn add<'py>(\n    left: &Bound<'py, PyAny>,\n    right: &Bound<'py, PyAny>,\n) -> PyResult<Bound<'py, PyAny>> {\n    left.add(right)\n}\n# Python::attach(|py| {\n#     let s = pyo3::types::PyString::new(py, \"s\");\n#     assert!(add(&s, &s).unwrap().eq(\"ss\").unwrap());\n# })\n```\n\nIf naming the `'py` lifetime adds unwanted complexity to the function signature, it is also acceptable to return `Py<PyAny>`, which has no lifetime.\nThe cost is instead paid by a slight increase in implementation complexity, as seen by the introduction of a call to [`Bound::unbind`]:\n\n```rust\n# use pyo3::prelude::*;\nfn add(left: &Bound<'_, PyAny>, right: &Bound<'_, PyAny>) -> PyResult<Py<PyAny>> {\n    let output: Bound<'_, PyAny> = left.add(right)?;\n    Ok(output.unbind())\n}\n# Python::attach(|py| {\n#     let s = pyo3::types::PyString::new(py, \"s\");\n#     assert!(add(&s, &s).unwrap().bind(py).eq(\"ss\").unwrap());\n# })\n```\n\n### `Borrowed<'a, 'py, T>`\n\n[`Borrowed<'a, 'py, T>`][Borrowed] is an advanced type used just occasionally at the edge of interaction with the Python interpreter.\nIt can be thought of as analogous to the shared reference `&'a Bound<'py, T>`.\nThe difference is that `Borrowed<'a, 'py, T>` is just a smart pointer rather than a reference-to-a-smart-pointer, which is a helpful reduction in indirection in specific interactions with the Python interpreter.\n\n`Borrowed<'a, 'py, T>` dereferences to `Bound<'py, T>`, so all methods on `Bound<'py, T>` are available on `Borrowed<'a, 'py, T>`.\n\nAn example where `Borrowed<'a, 'py, T>` is used is in [`PyTupleMethods::get_borrowed_item`]({{#PYO3_DOCS_URL}}/pyo3/types/trait.PyTupleMethods.html#tymethod.get_item):\n\n```rust\nuse pyo3::prelude::*;\nuse pyo3::types::PyTuple;\n\n# fn example<'py>(py: Python<'py>) -> PyResult<()> {\n// Create a new tuple with the elements (0, 1, 2)\nlet t = PyTuple::new(py, [0, 1, 2])?;\nfor i in 0..=2 {\n    let entry: Borrowed<'_, 'py, PyAny> = t.get_borrowed_item(i)?;\n    // `PyAnyMethods::extract` is available on `Borrowed`\n    // via the dereference to `Bound`\n    let value: usize = entry.extract()?;\n    assert_eq!(i, value);\n}\n# Ok(())\n# }\n# Python::attach(example).unwrap();\n```\n\n### Casting between smart pointer types\n\nTo convert between `Py<T>` and `Bound<'py, T>` use the `bind()` / `into_bound()` methods.\nUse the `as_unbound()` / `unbind()` methods to go back from `Bound<'py, T>` to `Py<T>`.\n\n```rust,ignore\nlet obj: Py<PyAny> = ...;\nlet bound: &Bound<'py, PyAny> = obj.bind(py);\nlet bound: Bound<'py, PyAny> = obj.into_bound(py);\n\nlet obj: &Py<PyAny> = bound.as_unbound();\nlet obj: Py<PyAny> = bound.unbind();\n```\n\nTo convert between `Bound<'py, T>` and `Borrowed<'a, 'py, T>` use the `as_borrowed()` method.\n`Borrowed<'a, 'py, T>` has a deref coercion to `Bound<'py, T>`.\nUse the `to_owned()` method to increment the Python reference count and to create a new `Bound<'py, T>` from the `Borrowed<'a, 'py, T>`.\n\n```rust,ignore\nlet bound: Bound<'py, PyAny> = ...;\nlet borrowed: Borrowed<'_, 'py, PyAny> = bound.as_borrowed();\n\n// deref coercion\nlet bound: &Bound<'py, PyAny> = &borrowed;\n\n// create a new Bound by increase the Python reference count\nlet bound: Bound<'py, PyAny> = borrowed.to_owned();\n```\n\nTo convert between `Py<T>` and `Borrowed<'a, 'py, T>` use the `bind_borrowed()` method.\nUse either `as_unbound()` or `.to_owned().unbind()` to go back to `Py<T>` from `Borrowed<'a, 'py, T>`, via `Bound<'py, T>`.\n\n```rust,ignore\nlet obj: Py<PyAny> = ...;\nlet borrowed: Borrowed<'_, 'py, PyAny> = bound.as_borrowed();\n\n// via deref coercion to Bound and then using Bound::as_unbound\nlet obj: &Py<PyAny> = borrowed.as_unbound();\n\n// via a new Bound by increasing the Python reference count, and unbind it\nlet obj: Py<PyAny> = borrowed.to_owned().unbind().\n```\n\n## Concrete Python types\n\nIn all of `Py<T>`, `Bound<'py, T>`, and `Borrowed<'a, 'py, T>`, the type parameter `T` denotes the type of the Python object referred to by the smart pointer.\n\nThis parameter `T` can be filled by:\n\n- [`PyAny`][PyAny], which represents any Python object,\n- Native Python types such as `PyList`, `PyTuple`, and `PyDict`, and\n- [`#[pyclass]`][pyclass] types defined from Rust\n\nThe following subsections covers some further detail about how to work with these types:\n\n- the APIs that are available for these concrete types,\n- how to cast `Bound<'py, T>` to a specific concrete type, and\n- how to get Rust data out of a `Bound<'py, T>`.\n\n### Using APIs for concrete Python types\n\nEach concrete Python type such as `PyAny`, `PyTuple` and `PyDict` exposes its API on the corresponding bound smart pointer `Bound<'py, PyAny>`, `Bound<'py, PyTuple>` and `Bound<'py, PyDict>`.\n\nEach type's API is exposed as a trait: [`PyAnyMethods`], [`PyTupleMethods`], [`PyDictMethods`], and so on for all concrete types.\nUsing traits rather than associated methods on the `Bound` smart pointer is done for a couple of reasons:\n\n- Clarity of documentation: each trait gets its own documentation page in the PyO3 API docs.\n  If all methods were on the `Bound` smart pointer directly, the vast majority of PyO3's API would be on a single, extremely long, documentation page.\n- Consistency: downstream code implementing Rust APIs for existing Python types can also follow this pattern of using a trait.\n  Downstream code would not be allowed to add new associated methods directly on the `Bound` type.\n- Future design: it is hoped that a future Rust with [arbitrary self types](https://github.com/rust-lang/rust/issues/44874) will remove the need for these traits in favour of placing the methods directly on `PyAny`, `PyTuple`, `PyDict`, and so on.\n\nThese traits are all included in the `pyo3::prelude` module, so with the glob import `use pyo3::prelude::*` the full PyO3 API is made available to downstream code.\n\nThe following function accesses the first item in the input Python list, using the `.get_item()` method from the `PyListMethods` trait:\n\n```rust\nuse pyo3::prelude::*;\nuse pyo3::types::PyList;\n\nfn get_first_item<'py>(list: &Bound<'py, PyList>) -> PyResult<Bound<'py, PyAny>> {\n    list.get_item(0)\n}\n# Python::attach(|py| {\n#     let l = PyList::new(py, [\"hello world\"]).unwrap();\n#     assert!(get_first_item(&l).unwrap().eq(\"hello world\").unwrap());\n# })\n```\n\n### Casting between Python object types\n\nTo cast `Bound<'py, T>` smart pointers to some other type, use the [`.cast()`][Bound::cast] family of functions.\nThis converts `&Bound<'py, T>` to a different `&Bound<'py, U>`, without transferring ownership.\nThere is also [`.cast_into()`][Bound::cast_into] to convert `Bound<'py, T>` to `Bound<'py, U>` with transfer of ownership.\nThese methods are available for all types `T` which implement the [`PyTypeCheck`] trait.\n\nCasting to `Bound<'py, PyAny>` can be done with `.as_any()` or `.into_any()`.\n\nFor example, the following snippet shows how to cast `Bound<'py, PyAny>` to `Bound<'py, PyTuple>`:\n\n```rust\n# use pyo3::prelude::*;\n# use pyo3::types::PyTuple;\n# fn example<'py>(py: Python<'py>) -> PyResult<()> {\n// create a new Python `tuple`, and use `.into_any()` to erase the type\nlet obj: Bound<'py, PyAny> = PyTuple::empty(py).into_any();\n\n// use `.cast()` to cast to `PyTuple` without transferring ownership\nlet _: &Bound<'py, PyTuple> = obj.cast()?;\n\n// use `.cast_into()` to cast to `PyTuple` with transfer of ownership\nlet _: Bound<'py, PyTuple> = obj.cast_into()?;\n# Ok(())\n# }\n# Python::attach(example).unwrap()\n```\n\nCustom [`#[pyclass]`][pyclass] types implement [`PyTypeCheck`], so `.cast()` also works for these types.\nThe snippet below is the same as the snippet above casting instead to a custom type `MyClass`:\n\n```rust\nuse pyo3::prelude::*;\n\n#[pyclass]\nstruct MyClass {}\n\n# fn example<'py>(py: Python<'py>) -> PyResult<()> {\n// create a new Python `tuple`, and use `.into_any()` to erase the type\nlet obj: Bound<'py, PyAny> = Bound::new(py, MyClass {})?.into_any();\n\n// use `.cast()` to cast to `MyClass` without transferring ownership\nlet _: &Bound<'py, MyClass> = obj.cast()?;\n\n// use `.cast_into()` to cast to `MyClass` with transfer of ownership\nlet _: Bound<'py, MyClass> = obj.cast_into()?;\n# Ok(())\n# }\n# Python::attach(example).unwrap()\n```\n\n### Extracting Rust data from Python objects\n\nTo extract Rust data from Python objects, use [`.extract()`][PyAnyMethods::extract] instead of `.cast()`.\nThis method is available for all types which implement the [`FromPyObject`] trait.\n\nFor example, the following snippet extracts a Rust tuple of integers from a Python tuple:\n\n```rust\n# use pyo3::prelude::*;\n# use pyo3::types::PyTuple;\n# fn example<'py>(py: Python<'py>) -> PyResult<()> {\n// create a new Python `tuple`, and use `.into_any()` to erase the type\nlet obj: Bound<'py, PyAny> = PyTuple::new(py, [1, 2, 3])?.into_any();\n\n// extracting the Python `tuple` to a rust `(i32, i32, i32)` tuple\nlet (x, y, z) = obj.extract::<(i32, i32, i32)>()?;\nassert_eq!((x, y, z), (1, 2, 3));\n# Ok(())\n# }\n# Python::attach(example).unwrap()\n```\n\nTo avoid copying data, [`#[pyclass]`][pyclass] types can directly reference Rust data stored within the Python objects without needing to `.extract()`.\nSee the [corresponding documentation in the class section of the guide](./class.md#bound-and-interior-mutability) for more detail.\n\n[Bound]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html\n[`Bound::unbind`]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html#method.unbind\n[Py]: {{#PYO3_DOCS_URL}}/pyo3/struct.Py.html\n[PyAnyMethods::add]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.add\n[PyAnyMethods::extract]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html#tymethod.extract\n[Bound::cast]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html#method.cast\n[Bound::cast_into]: {{#PYO3_DOCS_URL}}/pyo3/struct.Bound.html#method.cast_into\n[`PyTypeCheck`]: {{#PYO3_DOCS_URL}}/pyo3/type_object/trait.PyTypeCheck.html\n[`PyAnyMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyAnyMethods.html\n[`PyDictMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyDictMethods.html\n[`PyTupleMethods`]: {{#PYO3_DOCS_URL}}/pyo3/types/trait.PyTupleMethods.html\n[pyclass]: class.md\n[Borrowed]: {{#PYO3_DOCS_URL}}/pyo3/struct.Borrowed.html\n[Drop]: https://doc.rust-lang.org/std/ops/trait.Drop.html\n[PyAny]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyAny.html\n[smart-pointers]: https://doc.rust-lang.org/book/ch15-00-smart-pointers.html\n[`FromPyObject`]: {{#PYO3_DOCS_URL}}/pyo3/conversion/trait.FromPyObject.html\n"
  },
  {
    "path": "guide/theme/tabs.css",
    "content": ".mdbook-tabs {\n    display: flex;\n}\n\n.mdbook-tab {\n    background-color: var(--table-alternate-bg);\n    padding: 0.5rem 1rem;\n    cursor: pointer;\n    border: none;\n    font-size: 1.6rem;\n    line-height: 1.45em;\n}\n\n.mdbook-tab.active {\n    background-color: var(--table-header-bg);\n    font-weight: bold;\n}\n\n.mdbook-tab-content {\n    padding: 1rem 0rem;\n}\n\n.mdbook-tab-content table {\n    margin: unset;\n}\n"
  },
  {
    "path": "guide/theme/tabs.js",
    "content": "/**\n * Change active tab of tabs.\n *\n * @param {Element} container\n * @param {string} name\n */\nconst changeTab = (container, name) => {\n    for (const child of container.children) {\n        if (!(child instanceof HTMLElement)) {\n            continue;\n        }\n\n        if (child.classList.contains('mdbook-tabs')) {\n            for (const tab of child.children) {\n                if (!(tab instanceof HTMLElement)) {\n                    continue;\n                }\n\n                if (tab.dataset.tabname === name) {\n                    tab.classList.add('active');\n                } else {\n                    tab.classList.remove('active');\n                }\n            }\n        } else if (child.classList.contains('mdbook-tab-content')) {\n            if (child.dataset.tabname === name) {\n                child.classList.remove('hidden');\n            } else {\n                child.classList.add('hidden');\n            }\n        }\n    }\n};\n\ndocument.addEventListener('DOMContentLoaded', () => {\n    const tabs = document.querySelectorAll('.mdbook-tab');\n    for (const tab of tabs) {\n        tab.addEventListener('click', () => {\n            if (!(tab instanceof HTMLElement)) {\n                return;\n            }\n\n            if (!tab.parentElement || !tab.parentElement.parentElement) {\n                return;\n            }\n\n            const container = tab.parentElement.parentElement;\n            const name = tab.dataset.tabname;\n            const global = container.dataset.tabglobal;\n\n            changeTab(container, name);\n\n            if (global) {\n                localStorage.setItem(`mdbook-tabs-${global}`, name);\n\n                const globalContainers = document.querySelectorAll(\n                    `.mdbook-tabs-container[data-tabglobal=\"${global}\"]`\n                );\n                for (const globalContainer of globalContainers) {\n                    changeTab(globalContainer, name);\n                }\n            }\n        });\n    }\n\n    const containers = document.querySelectorAll('.mdbook-tabs-container[data-tabglobal]');\n    for (const container of containers) {\n        const global = container.dataset.tabglobal;\n\n        const name = localStorage.getItem(`mdbook-tabs-${global}`);\n        if (name && document.querySelector(`.mdbook-tab[data-tabname=${name}]`)) {\n            changeTab(container, name);\n        }\n    }\n});\n"
  },
  {
    "path": "newsfragments/.gitignore",
    "content": ""
  },
  {
    "path": "newsfragments/5349.added.md",
    "content": "Added `PyErr::set_traceback` to set the traceback of an exception object"
  },
  {
    "path": "newsfragments/5349.changed.md",
    "content": "Changed exception remapping on argument extraction error to use `add_note` for enhancing the error message instead."
  },
  {
    "path": "newsfragments/5668.added.md",
    "content": "Added new `PyUnicodeDecodeError::new_err_from_utf8` API to create a `PyErr` from a `str::Utf8Error`\n"
  },
  {
    "path": "newsfragments/5668.fixed.md",
    "content": "Fixed the implementations of `From<string::FromUtf8Error>` and `From<ffi::IntoStringError>` for `PyErr`.\n"
  },
  {
    "path": "newsfragments/5668.removed.md",
    "content": "Removed the failing implementations of `From<str::Utf8Error>`, `From<string::FromUtf16Error>`, and `From<char::DecodeUtf16Error>` for `PyErr`.\n"
  },
  {
    "path": "newsfragments/5753.changed.md",
    "content": "Module initialization uses the PyModExport and PyABIInfo APIs on python 3.15 and newer."
  },
  {
    "path": "newsfragments/5770.added.md",
    "content": "Introspection: implement `INPUT_TYPE` and `OUTPUT_TYPE` on third party crates conversions"
  },
  {
    "path": "newsfragments/5782.added.md",
    "content": "Introspection: introspect doc comments and emit them in the stubs."
  },
  {
    "path": "newsfragments/5797.changed.md",
    "content": "Deprecate `Py<T>::get_refcnt` and `PyAnyMethods::get_refcnt` in favor of `pyo3::ffi::Py_REFCNT(obj.as_ptr())`\n\n"
  },
  {
    "path": "newsfragments/5803.changed.md",
    "content": "`PyEnvironmentError`, `PyIOError`, and `PyWindowsError` are now type aliases of `PyOSError` (as is the case in Python since 3.3).\n"
  },
  {
    "path": "newsfragments/5809.packaging.md",
    "content": "`pyo3-macros-backend` no longer depends on `pyo3-build-config`.\n"
  },
  {
    "path": "newsfragments/5824.changed.md",
    "content": "Deprecate and remove `Py_TRACE_REFS` support (unsupported from Python 3.13)."
  },
  {
    "path": "newsfragments/5828.added.md",
    "content": "Added FFI wrappers for the following PyUnstable APIs available in Python 3.14: `PyUnstable_Object_IsUniquelyReferenced`, `PyUnstable_Object_IsUniquelyReferencedTemporary`, `PyUnstable_EnableTryIncref`, `PyUnstable_TryIncref`\n"
  },
  {
    "path": "newsfragments/5830.changed.md",
    "content": "Allow non-`ExactSizeIterator` in `PyList::new`\n"
  },
  {
    "path": "newsfragments/5837.fixed.md",
    "content": "Allow pyclass named `Probe` with `get_all` fields.\n"
  },
  {
    "path": "newsfragments/5839.changed.md",
    "content": "Stubs: emit `#[classattribute]` as plain Python class attributes and not functions annotated with `@classattribute` and `@property` (not supported since 3.13)"
  },
  {
    "path": "newsfragments/5841.changed.md",
    "content": "Stubs: use `object` as the input annotation type of magic methods returning `NonImplemented` if the input value is not of the correct type"
  },
  {
    "path": "newsfragments/5847.fixed.md",
    "content": "Fix type resolution error when using `_Py_NegativeRefcount` with Python < 3.12.\n"
  },
  {
    "path": "newsfragments/5849.added.md",
    "content": "Add `Borrowed::get` as an equivalent to `Bound::get` and `Py::get`.\n"
  },
  {
    "path": "newsfragments/5857.added.md",
    "content": "Add `PyFrame::new`, `PyTraceBack::new`, and `PyFrameMethods::line_number`.\n"
  },
  {
    "path": "newsfragments/5865.packaging.md",
    "content": "Drop support for Python 3.13t (3.14t and above continue to be supported in alignment with CPython declaring free-threading supported starting with Python 3.14).\n"
  },
  {
    "path": "newsfragments/5866.changed.md",
    "content": "pyo3-ffi: use raw-dylib for Windows linking, eliminating import libraries.\n"
  },
  {
    "path": "newsfragments/5883.changed.md",
    "content": "`PyMappingProxy`: allow subclasses during type checking\n`PyWeakrefReference`: always allow subclasses during type checking"
  },
  {
    "path": "newsfragments/5887.added.md",
    "content": "Add `PyErr::set_context`, `PyErr::context`, `ffi::PyErr_GetHandledException` and `ffi::PyErr_SetHandledException`."
  },
  {
    "path": "newsfragments/5891.added.md",
    "content": "Add `Py_HASH_SIPHASH13` to Rust binding\n"
  },
  {
    "path": "newsfragments/5893.removed.md",
    "content": "Remove the `TypeInfo` enum and the `FromPyObject::type_input` and `IntoPyObject::type_output` functions. They are replaced by the `PyStaticExpr` enum and the `FromPyObject::INPUT_TYPE` and the `IntoPyObject::OUTPUT_TYPE` associated constants."
  },
  {
    "path": "newsfragments/5896.changed.md",
    "content": "`PyDate::from_timestamp` argument is now a `f64` (the Python API expects a float and not an integer)"
  },
  {
    "path": "newsfragments/5897.changed.md",
    "content": "Change `PathBuf::extract` input type hint from `str | os.PathLike` to `str | os.PathLike[str]`"
  },
  {
    "path": "noxfile.py",
    "content": "import io\nimport json\nimport os\nimport re\nimport shutil\nimport subprocess\nimport sys\nimport sysconfig\nimport tarfile\nimport tempfile\nfrom contextlib import ExitStack, contextmanager\nfrom functools import lru_cache\nfrom glob import glob\nfrom pathlib import Path\nfrom shlex import quote\nfrom typing import (\n    Any,\n    Callable,\n    Dict,\n    Iterable,\n    Iterator,\n    List,\n    Optional,\n    Set,\n    Tuple,\n)\n\nimport nox.command\n\ntry:\n    import tomllib as toml\nexcept ImportError:\n    try:\n        import toml\n    except ImportError:\n        toml = None\n\ntry:\n    import requests\nexcept ImportError:\n    requests = None\n\nnox.options.sessions = [\"test\", \"clippy\", \"rustfmt\", \"ruff\", \"rumdl\", \"docs\"]\n\nPYO3_DIR = Path(__file__).parent\nPYO3_TARGET = Path(os.environ.get(\"CARGO_TARGET_DIR\", PYO3_DIR / \"target\")).absolute()\nPYO3_GUIDE_SRC = PYO3_DIR / \"guide\" / \"src\"\nPYO3_GUIDE_TARGET = PYO3_TARGET / \"guide\"\nPYO3_DOCS_TARGET = PYO3_TARGET / \"doc\"\nFREE_THREADED_BUILD = bool(sysconfig.get_config_var(\"Py_GIL_DISABLED\"))\n\n\ndef _get_output(*args: str) -> str:\n    return subprocess.run(args, capture_output=True, text=True, check=True).stdout\n\n\ndef _parse_supported_interpreter_version(\n    python_impl: str,  # Literal[\"cpython\", \"pypy\"], TODO update after 3.7 dropped\n) -> Tuple[str, str]:\n    output = _get_output(\"cargo\", \"metadata\", \"--format-version=1\", \"--no-deps\")\n    cargo_packages = json.loads(output)[\"packages\"]\n    # Check Python interpreter version support in package metadata\n    package = \"pyo3-ffi\"\n    metadata = next(pkg[\"metadata\"] for pkg in cargo_packages if pkg[\"name\"] == package)\n    version_info = metadata[python_impl]\n    assert \"min-version\" in version_info, f\"missing min-version for {python_impl}\"\n    assert \"max-version\" in version_info, f\"missing max-version for {python_impl}\"\n    return version_info[\"min-version\"], version_info[\"max-version\"]\n\n\ndef _supported_interpreter_versions(\n    python_impl: str,  # Literal[\"cpython\", \"pypy\"], TODO update after 3.7 dropped\n) -> List[str]:\n    min_version, max_version = _parse_supported_interpreter_version(python_impl)\n    major = int(min_version.split(\".\")[0])\n    assert major == 3, f\"unsupported Python major version {major}\"\n    min_minor = int(min_version.split(\".\")[1])\n    max_minor = int(max_version.split(\".\")[1])\n    versions = [f\"{major}.{minor}\" for minor in range(min_minor, max_minor + 1)]\n    # Add free-threaded builds for 3.13+\n    if python_impl == \"cpython\":\n        versions += [f\"{major}.{minor}t\" for minor in range(14, max_minor + 1)]\n    return versions\n\n\nPY_VERSIONS = _supported_interpreter_versions(\"cpython\")\n# We don't yet support abi3-py315 but do support cp315 and cp315t\n# version-specific builds\nABI3_PY_VERSIONS = [p for p in PY_VERSIONS if not p.endswith(\"t\")]\nABI3_PY_VERSIONS.remove(\"3.15\")\nPYPY_VERSIONS = _supported_interpreter_versions(\"pypy\")\n\n\n@nox.session(venv_backend=\"none\")\ndef test(session: nox.Session) -> None:\n    test_rust(session)\n    test_py(session)\n\n\n@nox.session(name=\"test-rust\", venv_backend=\"none\")\ndef test_rust(session: nox.Session):\n    _run_cargo_test(session, package=\"pyo3-build-config\")\n    _run_cargo_test(session, package=\"pyo3-macros-backend\")\n    _run_cargo_test(session, package=\"pyo3-macros\")\n\n    extra_flags = []\n    # pypy and graalpy don't have Py_Initialize APIs, so we can only\n    # build the main tests, not run them\n    if sys.implementation.name in (\"pypy\", \"graalpy\"):\n        extra_flags.append(\"--no-run\")\n\n    _run_cargo_test(session, package=\"pyo3-ffi\", extra_flags=extra_flags)\n\n    extra_flags.append(\"--no-default-features\")\n\n    for feature_set in _get_feature_sets():\n        flags = extra_flags.copy()\n\n        if feature_set is None or \"full\" not in feature_set:\n            # doctests require at least the macros feature, which is\n            # activated by the full feature set\n            #\n            # using `--all-targets` makes cargo run everything except doctests\n            flags.append(\"--all-targets\")\n\n        # We need to pass the feature set to the test command\n        # so that it can be used in the test code\n        # (e.g. for `#[cfg(feature = \"abi3-py37\")]`)\n        if feature_set and \"abi3\" in feature_set and FREE_THREADED_BUILD:\n            # free-threaded builds don't support abi3 yet\n            continue\n\n        _run_cargo_test(session, features=feature_set, extra_flags=flags)\n\n        if (\n            feature_set\n            and \"abi3\" in feature_set\n            and \"full\" in feature_set\n            and sys.version_info >= (3, 7)\n        ):\n            # run abi3-py37 tests to check abi3 forward compatibility\n            _run_cargo_test(\n                session,\n                features=feature_set.replace(\"abi3\", \"abi3-py37\"),\n                extra_flags=flags,\n            )\n\n\n@nox.session(name=\"test-py\", venv_backend=\"none\")\ndef test_py(session: nox.Session) -> None:\n    _run(session, \"nox\", \"-f\", \"pytests/noxfile.py\", external=True)\n    for example in glob(\"examples/*/noxfile.py\"):\n        _run(session, \"nox\", \"-f\", example, external=True)\n    for example in glob(\"pyo3-ffi/examples/*/noxfile.py\"):\n        _run(session, \"nox\", \"-f\", example, external=True)\n\n\n@nox.session(venv_backend=\"none\")\ndef coverage(session: nox.Session) -> None:\n    session.env.update(_get_coverage_env())\n    _run_cargo(session, \"llvm-cov\", \"clean\", \"--workspace\")\n    test(session)\n    generate_coverage_report(session)\n\n\n@nox.session(name=\"set-coverage-env\", venv_backend=\"none\")\ndef set_coverage_env(session: nox.Session) -> None:\n    \"\"\"For use in GitHub Actions to set coverage environment variables.\"\"\"\n    with open(os.environ[\"GITHUB_ENV\"], \"a\") as env_file:\n        for k, v in _get_coverage_env().items():\n            print(f\"{k}={v}\", file=env_file)\n\n\n@nox.session(name=\"generate-coverage-report\", venv_backend=\"none\")\ndef generate_coverage_report(session: nox.Session) -> None:\n    cov_format = \"codecov\"\n    output_file = \"coverage.json\"\n\n    if \"lcov\" in session.posargs:\n        cov_format = \"lcov\"\n        output_file = \"lcov.info\"\n\n    _run_cargo(\n        session,\n        \"llvm-cov\",\n        \"--package=pyo3\",\n        \"--package=pyo3-build-config\",\n        \"--package=pyo3-macros-backend\",\n        \"--package=pyo3-macros\",\n        \"--package=pyo3-ffi\",\n        \"report\",\n        f\"--{cov_format}\",\n        \"--output-path\",\n        output_file,\n    )\n\n\n@nox.session(venv_backend=\"none\")\ndef rustfmt(session: nox.Session):\n    _run_cargo(session, \"fmt\", \"--all\", \"--check\")\n    _run_cargo(session, \"fmt\", _FFI_CHECK, \"--all\", \"--check\")\n    _format_ffi_extern(session, check=True)\n\n\n@nox.session(name=\"ruff\")\ndef ruff(session: nox.Session):\n    session.install(\"ruff\")\n    _run(session, \"ruff\", \"format\", \".\", \"--check\")\n    _run(session, \"ruff\", \"check\", \".\")\n\n\n@nox.session(name=\"rumdl\", venv_backend=\"none\")\ndef rumdl(session: nox.Session):\n    \"\"\"Run rumdl to check markdown formatting in the guide.\n\n    Can also run with uv directly, e.g. `uv run rumdl check guide`.\n    \"\"\"\n    _run(\n        session, \"uv\", \"run\", \"rumdl\", \"check\", \"guide\", *session.posargs, external=True\n    )\n\n\n@nox.session(name=\"clippy\", venv_backend=\"none\")\ndef clippy(session: nox.Session) -> bool:\n    if not (_clippy(session) and _clippy_additional_workspaces(session)):\n        session.error(\"one or more jobs failed\")\n\n\ndef _clippy(session: nox.Session, *, env: Dict[str, str] = None) -> bool:\n    success = True\n    env = env or os.environ\n    for feature_set in _get_feature_sets():\n        try:\n            _run_cargo(\n                session,\n                \"clippy\",\n                \"--no-default-features\",\n                *((f\"--features={feature_set}\",) if feature_set else ()),\n                \"--all-targets\",\n                \"--workspace\",\n                \"--\",\n                \"--deny=warnings\",\n                env=env,\n            )\n        except nox.command.CommandFailed:\n            success = False\n    return success\n\n\ndef _clippy_additional_workspaces(session: nox.Session) -> bool:\n    # pyo3-benches and pyo3-ffi-check are in isolated workspaces so that their\n    # dependencies do not interact with MSRV\n\n    success = True\n    try:\n        _run_cargo(session, \"clippy\", _BENCHES)\n    except Exception:\n        success = False\n\n    # Run pyo3-ffi-check only on when not cross-compiling, because it needs to\n    # have Python headers to feed to bindgen which gets messy when cross-compiling.\n    target = os.environ.get(\"CARGO_BUILD_TARGET\")\n    if target is None or _get_rust_default_target() == target:\n        try:\n            _build_docs_for_ffi_check(session)\n            _run_cargo(session, \"clippy\", _FFI_CHECK, \"--workspace\", \"--all-targets\")\n        except Exception:\n            success = False\n    return success\n\n\n@nox.session(venv_backend=\"none\")\ndef bench(session: nox.Session) -> bool:\n    _run_cargo(session, \"bench\", _BENCHES, *session.posargs)\n\n\n@nox.session()\ndef codspeed(session: nox.Session) -> bool:\n    # rust benchmarks\n    os.chdir(PYO3_DIR / \"pyo3-benches\")\n    _run_cargo(session, \"codspeed\", \"build\")\n    _run_cargo(session, \"codspeed\", \"run\")\n    # python benchmarks\n    os.chdir(PYO3_DIR / \"pytests\")\n    session.install(\".[dev]\", \"pytest-codspeed\")\n    _run(session, \"pytest\", \"--codspeed\", external=True)\n\n\n@nox.session(name=\"clippy-all\", venv_backend=\"none\")\ndef clippy_all(session: nox.Session) -> None:\n    success = True\n\n    def _clippy_with_config(env: Dict[str, str]) -> None:\n        nonlocal success\n        success &= _clippy(session, env=env)\n\n    _for_all_version_configs(session, _clippy_with_config)\n    success &= _clippy_additional_workspaces(session)\n\n    if not success:\n        session.error(\"one or more jobs failed\")\n\n\n@nox.session(name=\"check-all\", venv_backend=\"none\")\ndef check_all(session: nox.Session) -> None:\n    success = True\n\n    def _check(env: Dict[str, str]) -> None:\n        nonlocal success\n        for feature_set in _get_feature_sets():\n            try:\n                _run_cargo(\n                    session,\n                    \"check\",\n                    \"--no-default-features\",\n                    *((f\"--features={feature_set}\",) if feature_set else ()),\n                    \"--all-targets\",\n                    \"--workspace\",\n                    env=env,\n                )\n            except Exception:\n                success = False\n\n    _for_all_version_configs(session, _check)\n\n    if not success:\n        session.error(\"one or more jobs failed\")\n\n\n@nox.session(venv_backend=\"none\")\ndef publish(session: nox.Session) -> None:\n    _run_cargo_publish(session, package=\"pyo3-build-config\")\n    _run_cargo_publish(session, package=\"pyo3-macros-backend\")\n    _run_cargo_publish(session, package=\"pyo3-macros\")\n    _run_cargo_publish(session, package=\"pyo3-ffi\")\n    _run_cargo_publish(session, package=\"pyo3\")\n    _run_cargo_publish(session, package=\"pyo3-introspection\")\n\n\n@nox.session(venv_backend=\"none\")\ndef contributors(session: nox.Session) -> None:\n    import requests\n\n    if len(session.posargs) < 1:\n        raise Exception(\"base commit positional argument missing\")\n\n    base = session.posargs[0]\n    page = 1\n\n    head = \"HEAD\"\n    if len(session.posargs) == 2:\n        head = session.posargs[1]\n\n    if len(session.posargs) > 2:\n        raise Exception(\"too many arguments\")\n\n    authors = set()\n\n    while True:\n        resp = requests.get(\n            f\"https://api.github.com/repos/PyO3/pyo3/compare/{base}...{head}\",\n            params={\"page\": page, \"per_page\": 100},\n        )\n\n        body = resp.json()\n\n        if resp.status_code != 200:\n            raise Exception(\n                f\"failed to retrieve commits: {resp.status_code} {body['message']}\"\n            )\n\n        for commit in body[\"commits\"]:\n            try:\n                authors.add(commit[\"author\"][\"login\"])\n            except Exception:\n                continue\n\n        if \"next\" in resp.links:\n            page += 1\n        else:\n            break\n\n    authors = sorted(list(authors), key=lambda author: author.lower())\n\n    for author in authors:\n        print(f\"@{author}\")\n\n\nclass EmscriptenInfo:\n    def __init__(self):\n        self.emscripten_dir = PYO3_DIR / \"emscripten\"\n        self.builddir = PYO3_DIR / \".nox/emscripten\"\n        self.builddir.mkdir(exist_ok=True, parents=True)\n\n        self.pyversion = sys.version.split()[0]\n        self.pymajor, self.pyminor, self.pymicro = self.pyversion.split(\".\")\n        self.pymicro, self.pydev = re.match(\n            \"([0-9]*)([^0-9].*)?\", self.pymicro\n        ).groups()\n        if self.pydev is None:\n            self.pydev = \"\"\n\n        self.pymajorminor = f\"{self.pymajor}.{self.pyminor}\"\n        self.pymajorminormicro = f\"{self.pymajorminor}.{self.pymicro}\"\n\n\n@nox.session(name=\"build-emscripten\", venv_backend=\"none\")\ndef build_emscripten(session: nox.Session):\n    info = EmscriptenInfo()\n    _run(\n        session,\n        \"make\",\n        \"-C\",\n        str(info.emscripten_dir),\n        f\"PYTHON={sys.executable}\",\n        f\"BUILDROOT={info.builddir}\",\n        f\"PYMAJORMINORMICRO={info.pymajorminormicro}\",\n        f\"PYPRERELEASE={info.pydev}\",\n        external=True,\n    )\n\n\n@nox.session(name=\"test-emscripten\", venv_backend=\"none\")\ndef test_emscripten(session: nox.Session):\n    info = EmscriptenInfo()\n\n    libdir = info.builddir / f\"install/Python-{info.pyversion}/lib\"\n    pythonlibdir = libdir / f\"python{info.pymajorminor}\"\n\n    target = \"wasm32-unknown-emscripten\"\n\n    session.env[\"CARGO_TARGET_WASM32_UNKNOWN_EMSCRIPTEN_RUNNER\"] = \"python \" + str(\n        info.emscripten_dir / \"runner.py\"\n    )\n    session.env[\"RUSTFLAGS\"] = \" \".join(\n        [\n            f\"-L native={libdir}\",\n            \"-C link-arg=--preload-file\",\n            f\"-C link-arg={pythonlibdir}@/lib/python{info.pymajorminor}\",\n            f\"-C link-arg=-lpython{info.pymajorminor}\",\n            \"-C link-arg=-lexpat\",\n            \"-C link-arg=-lffi\",\n            \"-C link-arg=-lmpdec\",\n            \"-C link-arg=-lhacl\",\n            \"-C link-arg=-sUSE_SQLITE3\",\n            \"-C link-arg=-sUSE_ZLIB\",\n            \"-C link-arg=-sUSE_BZIP2\",\n            \"-C link-arg=-sEXPORTED_FUNCTIONS=_main,__PyRuntime\",\n            \"-C link-arg=-sALLOW_MEMORY_GROWTH=1\",\n            \"-C link-arg=-sSTACK_SIZE=262144\",\n        ]\n    )\n    session.env[\"RUSTDOCFLAGS\"] = session.env[\"RUSTFLAGS\"]\n    session.env[\"CARGO_BUILD_TARGET\"] = target\n    session.env[\"PYO3_CROSS_LIB_DIR\"] = pythonlibdir\n    _run(session, \"rustup\", \"target\", \"add\", target, \"--toolchain\", \"stable\")\n\n    emsdk_env = next(info.builddir.glob(\"**/emsdk-cache/**/emsdk_env.sh\"))\n\n    _run(\n        session,\n        \"bash\",\n        \"-c\",\n        f\"source {emsdk_env} && cargo test {' '.join(quote(arg) for arg in session.posargs)}\",\n    )\n\n\n@nox.session(name=\"test-cross-compilation-windows\")\ndef test_cross_compilation_windows(session: nox.Session):\n    session.install(\"cargo-xwin\")\n\n    env = os.environ.copy()\n    env[\"XWIN_ARCH\"] = \"x86_64\"\n\n    # abi3\n    _run_cargo(\n        session,\n        \"build\",\n        \"--manifest-path\",\n        \"examples/maturin-starter/Cargo.toml\",\n        \"--features\",\n        \"abi3\",\n        \"--target\",\n        \"x86_64-pc-windows-gnu\",\n        env=env,\n    )\n    _run_cargo(\n        session,\n        \"xwin\",\n        \"build\",\n        \"--cross-compiler\",\n        \"clang\",\n        \"--manifest-path\",\n        \"examples/maturin-starter/Cargo.toml\",\n        \"--features\",\n        \"abi3\",\n        \"--target\",\n        \"x86_64-pc-windows-msvc\",\n        env=env,\n    )\n\n    # non-abi3\n    env[\"PYO3_CROSS_PYTHON_VERSION\"] = \"3.13\"\n    _run_cargo(\n        session,\n        \"build\",\n        \"--manifest-path\",\n        \"examples/maturin-starter/Cargo.toml\",\n        \"--features\",\n        \"pyo3/generate-import-lib\",\n        \"--target\",\n        \"x86_64-pc-windows-gnu\",\n        env=env,\n    )\n    _run_cargo(\n        session,\n        \"xwin\",\n        \"build\",\n        \"--cross-compiler\",\n        \"clang\",\n        \"--manifest-path\",\n        \"examples/maturin-starter/Cargo.toml\",\n        \"--features\",\n        \"pyo3/generate-import-lib\",\n        \"--target\",\n        \"x86_64-pc-windows-msvc\",\n        env=env,\n    )\n\n\n@nox.session(venv_backend=\"none\")\ndef docs(session: nox.Session, nightly: bool = False, internal: bool = False) -> None:\n    rustdoc_flags = [\"-Dwarnings\"]\n    toolchain_flags = []\n    cargo_flags = []\n\n    nightly = nightly or (\"nightly\" in session.posargs)\n    internal = internal or (\"internal\" in session.posargs)\n\n    if \"open\" in session.posargs:\n        cargo_flags.append(\"--open\")\n\n    if nightly:\n        rustdoc_flags.append(\"--cfg docsrs\")\n        toolchain_flags.append(\"+nightly\")\n        cargo_flags.extend([\"-Z\", \"unstable-options\", \"-Z\", \"rustdoc-scrape-examples\"])\n\n    if internal:\n        rustdoc_flags.append(\"--Z unstable-options\")\n        rustdoc_flags.append(\"--document-hidden-items\")\n        rustdoc_flags.extend((\"--html-after-content\", \".netlify/internal_banner.html\"))\n        cargo_flags.append(\"--document-private-items\")\n    else:\n        cargo_flags.extend([\"--exclude=pyo3-macros\", \"--exclude=pyo3-macros-backend\"])\n\n    rustdoc_flags.append(session.env.get(\"RUSTDOCFLAGS\", \"\"))\n    session.env[\"RUSTDOCFLAGS\"] = \" \".join(rustdoc_flags)\n\n    features = \"full\"\n\n    shutil.rmtree(PYO3_DOCS_TARGET, ignore_errors=True)\n    _run_cargo(\n        session,\n        *toolchain_flags,\n        \"doc\",\n        \"--lib\",\n        \"--no-default-features\",\n        f\"--features={features}\",\n        \"--no-deps\",\n        \"--workspace\",\n        *cargo_flags,\n    )\n\n\n@nox.session(name=\"build-guide\", venv_backend=\"none\")\ndef build_guide(session: nox.Session):\n    shutil.rmtree(PYO3_GUIDE_TARGET, ignore_errors=True)\n    _run(\n        session,\n        \"mdbook\",\n        \"build\",\n        \"-d\",\n        str(PYO3_GUIDE_TARGET),\n        \"guide\",\n        *session.posargs,\n        external=True,\n    )\n    for license in (\"LICENSE-APACHE\", \"LICENSE-MIT\"):\n        target_file = PYO3_GUIDE_TARGET / license\n        target_file.unlink(missing_ok=True)\n        shutil.copy(PYO3_DIR / license, target_file)\n\n\n@nox.session(name=\"build-netlify-site\")\ndef build_netlify_site(session: nox.Session):\n    # Remove netlify_build directory if it exists\n    netlify_build = Path(\"netlify_build\")\n    if netlify_build.exists():\n        shutil.rmtree(netlify_build)\n\n    url = \"https://github.com/PyO3/pyo3/archive/gh-pages.tar.gz\"\n    response = requests.get(url, stream=True)\n    response.raise_for_status()\n    with tarfile.open(fileobj=io.BytesIO(response.content), mode=\"r:gz\") as tar:\n        tar.extractall()\n    shutil.move(\"pyo3-gh-pages\", \"netlify_build\")\n\n    preview = \"--preview\" in session.posargs\n    if preview:\n        session.posargs.remove(\"--preview\")\n\n    session.install(\"towncrier\")\n    # Save a copy of the changelog to restore later\n    changelog = (PYO3_DIR / \"CHANGELOG.md\").read_text()\n\n    # Build the changelog\n    session.run(\n        \"towncrier\", \"build\", \"--keep\", \"--version\", \"Unreleased\", \"--date\", \"TBC\"\n    )\n\n    # Build the guide\n    build_guide(session)\n    PYO3_GUIDE_TARGET.rename(\"netlify_build/main\")\n\n    # Restore the original changelog\n    (PYO3_DIR / \"CHANGELOG.md\").write_text(changelog)\n    session.run(\"git\", \"restore\", \"--staged\", \"CHANGELOG.md\", external=True)\n\n    # Build the main branch docs\n    docs(session)\n    PYO3_DOCS_TARGET.rename(\"netlify_build/main/doc\")\n\n    Path(\"netlify_build/main/doc/index.html\").write_text(\n        \"<meta http-equiv=refresh content=0;url=pyo3/>\"\n    )\n\n    # Build the internal docs\n    docs(session, nightly=True, internal=True)\n    PYO3_DOCS_TARGET.rename(\"netlify_build/internal\")\n\n    _build_netlify_redirects(preview)\n\n\ndef _build_netlify_redirects(preview: bool) -> None:\n    current_version = os.environ.get(\"PYO3_VERSION\")\n\n    with ExitStack() as stack:\n        redirects_file = stack.enter_context(open(\"netlify_build/_redirects\", \"w\"))\n        headers_file = stack.enter_context(open(\"netlify_build/_headers\", \"w\"))\n        for d in glob(\"netlify_build/v*\"):\n            version = d.removeprefix(\"netlify_build/v\")\n            redirects_file.write(\n                f\"/v{version}/doc/* https://docs.rs/pyo3/{version}/:splat\\n\"\n            )\n\n            # for versions other than the current version, set noindex\n            if version != current_version:\n                headers_file.write(f\"/v{version}/*\\n  X-Robots-Tag: noindex\\n\")\n                continue\n\n            # for the current version, index all files and set canonical links where possible\n            for file in glob(f\"{d}/**\", recursive=True):\n                file_path = file.removeprefix(\"netlify_build\")\n                url_path = _url_path_from_file_path(file_path)\n\n                for path in _url_and_file_paths(url_path, file_path):\n                    headers_file.write(\n                        f'{path}\\n  Link: <https://pyo3.rs{url_path}>; rel=\"canonical\"\\n'\n                    )\n\n        # main files should be indexed and canonical\n        for file in glob(\"netlify_build/main/**\", recursive=True):\n            file_path = file.removeprefix(\"netlify_build\")\n            url_path = _url_path_from_file_path(file_path)\n\n            for path in _url_and_file_paths(url_path, file_path):\n                headers_file.write(\n                    f'{path}\\n  Link: <https://pyo3.rs{url_path}>; rel=\"canonical\"\\n'\n                )\n\n        # for internal docs, set noindex for all files\n        headers_file.write(\"/internal/*\\n  X-Robots-Tag: noindex\\n\")\n\n        # Add latest redirect\n        if current_version is not None:\n            redirects_file.write(f\"/latest/* /v{current_version}/:splat 302\\n\")\n\n        # some backwards compatbiility redirects\n        redirects_file.write(\n            \"\"\"\\\n/latest/building_and_distribution/* /latest/building-and-distribution/:splat 302\n/latest/building_and_distribution/multiple_python_versions/* /latest/building-and-distribution/multiple-python-versions:splat 302\n/latest/function/error_handling/* /latest/function/error-handling/:splat 302\n/latest/getting_started/* /latest/getting-started/:splat 302\n/latest/python_from_rust/* /latest/python-from-rust/:splat 302\n/latest/python_typing_hints/* /latest/python-typing-hints/:splat 302\n/latest/trait_bounds/* /latest/trait-bounds/:splat 302\n\"\"\"\n        )\n\n        # Add landing page redirect\n        if preview:\n            redirects_file.write(\"/ /main/ 302\\n\")\n        else:\n            redirects_file.write(f\"/ /v{current_version}/ 302\\n\")\n\n\ndef _url_path_from_file_path(file_path: str) -> str:\n    \"\"\"Removes index.html and/or .html suffix to match the page URL on the final netlify site\"\"\"\n    url_path = file_path\n    if url_path.endswith(\"index.html\"):\n        url_path = url_path[: -len(\"index.html\")]\n    elif url_path.endswith(\".html\"):\n        url_path = url_path[: -len(\".html\")]\n    return url_path\n\n\ndef _url_and_file_paths(url_path: str, file_path: str) -> Tuple[str, str]:\n    \"\"\"Returns all combinations of url and file paths with and without index.html suffix\"\"\"\n    if url_path == file_path:\n        return (url_path,)\n    else:\n        return (url_path, file_path)\n\n\n@nox.session(name=\"check-guide\")\ndef check_guide(session: nox.Session):\n    # reuse other sessions, but with default args\n    posargs = [*session.posargs]\n    del session.posargs[:]\n    build_guide(session)\n    docs(session)\n    session.posargs.extend(posargs)\n\n    if toml is None:\n        session.error(\"requires Python 3.11 or `toml` to be installed\")\n    pyo3_version = toml.loads((PYO3_DIR / \"Cargo.toml\").read_text())[\"package\"][\n        \"version\"\n    ]\n\n    remaps = {\n        f\"file://{PYO3_GUIDE_SRC}/([^/]*/)*?%7B%7B#PYO3_DOCS_URL}}}}\": f\"file://{PYO3_DOCS_TARGET}\",\n        f\"https://pyo3.rs/v{pyo3_version}\": f\"file://{PYO3_GUIDE_TARGET}\",\n        \"https://pyo3.rs/main/\": f\"file://{PYO3_GUIDE_TARGET}/\",\n        \"https://pyo3.rs/latest/\": f\"file://{PYO3_GUIDE_TARGET}/\",\n        \"%7B%7B#PYO3_DOCS_VERSION}}\": \"latest\",\n        # bypass fragments for edge cases\n        # blob links\n        \"(https://github.com/[^/]+/[^/]+/blob/[^#]+)#[a-zA-Z0-9._-]*\": \"$1\",\n        # issue comments\n        \"(https://github.com/[^/]+/[^/]+/issues/[0-9]+)#issuecomment-[0-9]*\": \"$1\",\n        # rust docs\n        \"(https://docs.rs/[^#]+)#[a-zA-Z0-9._-]*\": \"$1\",\n    }\n    remap_args = []\n    for key, value in remaps.items():\n        remap_args.extend((\"--remap\", f\"{key} {value}\"))\n\n    # check all links in the guide\n    _run(\n        session,\n        \"lychee\",\n        \"--include-fragments\",\n        str(PYO3_GUIDE_SRC),\n        *remap_args,\n        \"--accept=200,429\",\n        \"--cache\",\n        \"--max-cache-age=7d\",\n        *session.posargs,\n        external=True,\n    )\n    # check external links in the docs\n    # (intra-doc links are checked by rustdoc)\n    _run(\n        session,\n        \"lychee\",\n        str(PYO3_DOCS_TARGET),\n        *remap_args,\n        f\"--exclude=file://{PYO3_DOCS_TARGET}\",\n        # exclude some old http links from copyright notices, known to fail\n        \"--exclude=http://www.adobe.com/\",\n        \"--exclude=http://www.nhncorp.com/\",\n        \"--accept=200,429\",\n        # reduce the concurrency to avoid rate-limit from `pyo3.rs`\n        \"--max-concurrency=32\",\n        \"--cache\",\n        \"--max-cache-age=7d\",\n        *session.posargs,\n        external=True,\n    )\n\n\n@nox.session(name=\"format-guide\", venv_backend=\"none\")\ndef format_guide(session: nox.Session):\n    fence_line = \"//! ```\\n\"\n\n    for path in Path(\"guide\").glob(\"**/*.md\"):\n        session.log(\"Working on %s\", path)\n        lines = iter(path.read_text().splitlines(True))\n        new_lines = []\n\n        for line in lines:\n            new_lines.append(line)\n            if not re.search(\"```rust(,.*)?$\", line):\n                continue\n\n            # Found a code block fence, gobble up its lines and write to temp. file\n            prefix = line[: line.index(\"```\")]\n            with tempfile.NamedTemporaryFile(\"w\", delete=False) as file:\n                tempname = file.name\n                file.write(fence_line)\n                for line in lines:\n                    if line == prefix + \"```\\n\":\n                        break\n                    file.write((\"//! \" + line[len(prefix) :]).rstrip() + \"\\n\")\n                file.write(fence_line)\n\n            # Format it (needs nightly rustfmt for `format_code_in_doc_comments`)\n            _run(\n                session,\n                \"rustfmt\",\n                \"+nightly\",\n                \"--config\",\n                \"format_code_in_doc_comments=true\",\n                \"--config\",\n                \"reorder_imports=false\",\n                tempname,\n            )\n\n            # Re-read the formatted file, add its lines, and delete it\n            with open(tempname, \"r\") as file:\n                for line in file:\n                    if line == fence_line:\n                        continue\n                    new_lines.append((prefix + line[4:]).rstrip() + \"\\n\")\n            os.unlink(tempname)\n\n            new_lines.append(prefix + \"```\\n\")\n\n        path.write_text(\"\".join(new_lines))\n\n\ndef _format_ffi_extern(session: nox.Session, *, check: bool = False):\n    \"\"\"Format extern blocks inside extern_libpython! macros in pyo3-ffi.\n\n    rustfmt cannot format inside macro invocations, so this temporarily\n    replaces `extern_libpython!` with plain `extern \"C\"` blocks, runs rustfmt,\n    and then restores the macro invocations.\n\n    When check=True, errors out if any file would change (CI mode).\n    \"\"\"\n    ffi_src = PYO3_DIR / \"pyo3-ffi\" / \"src\"\n    # Pattern for default ABI: `extern_libpython! {`\n    default_re = re.compile(r\"^(\\s*)extern_libpython!\\s*\\{\", re.MULTILINE)\n    # Pattern for explicit ABI: `extern_libpython! { \"C-unwind\" {`\n    explicit_re = re.compile(\n        r'^(\\s*)extern_libpython!\\s*\\{\\s*\"([^\"]+)\"\\s*\\{', re.MULTILINE\n    )\n    # Use #[doc] attributes as sentinels instead of /* */ comments to avoid\n    # rustfmt re-indenting them (rustfmt aligns block comments with nearby\n    # trailing comments, but leaves #[doc] attributes in place).\n    SENTINEL_DEFAULT = '#[doc = \"__extern_libpython_default__\"]'\n    SENTINEL_EXPLICIT = '#[doc = \"__extern_libpython_explicit__:'\n    SENTINEL_EXPLICIT_CLOSE = \"/* __extern_libpython_explicit_close__ */\"\n\n    def replace_explicit(m):\n        indent = m.group(1)\n        abi = m.group(2)\n        return f'{indent}{SENTINEL_EXPLICIT}{abi}__\"]\\n{indent}extern \"{abi}\" {{'\n\n    def replace_default(m):\n        indent = m.group(1)\n        return f'{indent}{SENTINEL_DEFAULT}\\n{indent}extern \"C\" {{'\n\n    # Pattern for the double closing brace of explicit ABI blocks:\n    # `extern_libpython! { \"abi\" { ... }}` has two closing braces, but after\n    # replacing the opening we only have one opening brace, so we need to\n    # remove the extra closing brace before running rustfmt.\n    explicit_close_re = re.compile(r\"\\}\\}\", re.MULTILINE)\n\n    originals = {}\n    files_to_format = []\n    for path in sorted(ffi_src.rglob(\"*.rs\")):\n        if path.name == \"macros.rs\":\n            continue\n        content = path.read_text()\n        if \"extern_libpython!\" not in content:\n            continue\n\n        # Replace explicit ABI first (more specific pattern)\n        new_content = explicit_re.sub(replace_explicit, content)\n        # Fix double closing braces for explicit ABI blocks: the explicit\n        # pattern `extern_libpython! { \"abi\" { ... }}` has an outer `}` for\n        # the macro invocation that must be removed after we replaced the\n        # opening with a plain `extern \"abi\" {`.\n        if SENTINEL_EXPLICIT in new_content:\n            new_content = explicit_close_re.sub(\n                f\"}} {SENTINEL_EXPLICIT_CLOSE}\", new_content\n            )\n        # Replace default ABI\n        new_content = default_re.sub(replace_default, new_content)\n\n        if new_content != content:\n            originals[path] = content\n            path.write_text(new_content)\n            files_to_format.append(path)\n\n    if not files_to_format:\n        session.log(\"No extern_libpython! blocks found to format\")\n        return\n\n    # Run rustfmt on the modified files\n    try:\n        _run(\n            session, \"rustfmt\", \"--edition\", \"2021\", *[str(f) for f in files_to_format]\n        )\n    except Exception:\n        # Restore originals on failure\n        for path, content in originals.items():\n            path.write_text(content)\n        raise\n\n    # Restore the macro invocations\n    sentinel_default_re = re.compile(\n        r'^(\\s*)#\\[doc = \"__extern_libpython_default__\"\\]\\n\\s*extern \"C\" \\{',\n        re.MULTILINE,\n    )\n    sentinel_explicit_re = re.compile(\n        r'^(\\s*)#\\[doc = \"__extern_libpython_explicit__:([^_]+)__\"\\]\\n\\s*extern \"[^\"]*\" \\{',\n        re.MULTILINE,\n    )\n\n    changed = []\n    for path in files_to_format:\n        content = path.read_text()\n\n        content = sentinel_explicit_re.sub(\n            lambda m: f'{m.group(1)}extern_libpython! {{ \"{m.group(2)}\" {{', content\n        )\n        # Restore the double closing brace for explicit ABI blocks\n        content = content.replace(f\"}} {SENTINEL_EXPLICIT_CLOSE}\", \"}}\")\n        content = sentinel_default_re.sub(\n            lambda m: f\"{m.group(1)}extern_libpython! {{\", content\n        )\n\n        if check and content != originals[path]:\n            changed.append(path)\n            # Restore original so we don't leave dirty files in CI\n            path.write_text(originals[path])\n        else:\n            path.write_text(content)\n\n    if check and changed:\n        session.error(\n            \"extern_libpython! blocks are not formatted:\\n\"\n            + \"\\n\".join(f\"  {p}\" for p in changed)\n            + \"\\n\\nRun `nox -s format-ffi-extern` to fix.\"\n        )\n\n    session.log(f\"Formatted extern_libpython! blocks in {len(files_to_format)} files ✓\")\n\n\n@nox.session(name=\"format-ffi-extern\", venv_backend=\"none\")\ndef format_ffi_extern(session: nox.Session):\n    _format_ffi_extern(session)\n\n\n@nox.session(name=\"address-sanitizer\", venv_backend=\"none\")\ndef address_sanitizer(session: nox.Session):\n    _run_cargo(\n        session,\n        \"+nightly\",\n        \"test\",\n        \"--release\",\n        \"-Zbuild-std\",\n        f\"--target={_get_rust_default_target()}\",\n        \"--\",\n        \"--test-threads=1\",\n        env={\n            \"RUSTFLAGS\": \"-Zsanitizer=address\",\n            \"RUSTDOCFLAGS\": \"-Zsanitizer=address\",\n            \"ASAN_OPTIONS\": \"detect_leaks=0\",\n        },\n    )\n\n\n_IGNORE_CHANGELOG_PR_CATEGORIES = (\n    \"release\",\n    \"docs\",\n    \"ci\",\n)\n\n\n@nox.session(name=\"check-changelog\")\ndef check_changelog(session: nox.Session):\n    if not _is_github_actions():\n        session.error(\"Can only check changelog on github actions\")\n\n    event_path = os.environ[\"GITHUB_EVENT_PATH\"]\n\n    with open(event_path) as event_file:\n        event = json.load(event_file)\n\n    for category in _IGNORE_CHANGELOG_PR_CATEGORIES:\n        if event[\"pull_request\"][\"title\"].startswith(f\"{category}:\"):\n            session.skip(f\"PR title starts with {category}\")\n\n    for label in event[\"pull_request\"][\"labels\"]:\n        if label[\"name\"] == \"CI-skip-changelog\":\n            session.skip(\"CI-skip-changelog label applied\")\n\n    issue_number = event[\"pull_request\"][\"number\"]\n\n    newsfragments = PYO3_DIR / \"newsfragments\"\n\n    fragments = tuple(\n        filter(\n            Path.exists,\n            (\n                newsfragments / f\"{issue_number}.{change_type}.md\"\n                for change_type in (\"packaging\", \"added\", \"changed\", \"removed\", \"fixed\")\n            ),\n        )\n    )\n\n    if not fragments:\n        session.error(\n            \"Changelog entry not found, please add one (or more) to the `newsfragments` directory.\\n\"\n            \"Alternatively, start the PR title with `docs:` if this PR is a docs-only PR.\\n\"\n            \"See https://github.com/PyO3/pyo3/blob/main/Contributing.md#documenting-changes for more information.\"\n        )\n\n    print(\"Found newsfragments:\")\n    for fragment in fragments:\n        print(fragment.name)\n\n\n@nox.session(name=\"set-msrv-package-versions\", venv_backend=\"none\")\ndef set_msrv_package_versions(session: nox.Session):\n    from collections import defaultdict\n\n    projects = (\n        PYO3_DIR,\n        *(Path(p).parent for p in glob(\"examples/*/Cargo.toml\")),\n        *(Path(p).parent for p in glob(\"pyo3-ffi/examples/*/Cargo.toml\")),\n    )\n    min_pkg_versions = {}\n\n    # run cargo update first to ensure that everything is at highest\n    # possible version, so that this matches what CI will resolve to.\n    for project in projects:\n        _run_cargo(\n            session,\n            \"+stable\",\n            \"update\",\n            f\"--manifest-path={project}/Cargo.toml\",\n            env=os.environ | {\"CARGO_RESOLVER_INCOMPATIBLE_RUST_VERSIONS\": \"fallback\"},\n        )\n\n        lock_file = project / \"Cargo.lock\"\n\n        def load_pkg_versions():\n            cargo_lock = toml.loads(lock_file.read_text())\n            # Cargo allows to depends on multiple versions of the same package\n            pkg_versions = defaultdict(list)\n            for pkg in cargo_lock[\"package\"]:\n                name = pkg[\"name\"]\n                if name not in min_pkg_versions:\n                    continue\n                pkg_versions[name].append(pkg[\"version\"])\n            return pkg_versions\n\n        pkg_versions = load_pkg_versions()\n        for pkg_name, min_version in min_pkg_versions.items():\n            versions = pkg_versions.get(pkg_name, [])\n            for version in versions:\n                if version != min_version:\n                    pkg_id = pkg_name + \":\" + version\n                    _run_cargo_set_package_version(\n                        session, pkg_id, min_version, project=project\n                    )\n                    # assume `_run_cargo_set_package_version` has changed something\n                    # and re-read `Cargo.lock`\n                    pkg_versions = load_pkg_versions()\n\n        # As a smoke test, cargo metadata solves all dependencies, so\n        # will break if any crates rely on cargo features not\n        # supported on MSRV\n        _run_cargo(\n            session,\n            \"metadata\",\n            f\"--manifest-path={project}/Cargo.toml\",\n            silent=True,\n        )\n\n\n@nox.session(name=\"ffi-check\")\ndef ffi_check(session: nox.Session):\n    _build_docs_for_ffi_check(session)\n    _run_cargo(session, \"run\", _FFI_CHECK)\n    _check_raw_dylib_macro(session)\n\n\n@nox.session(name=\"test-version-limits\")\ndef test_version_limits(session: nox.Session):\n    env = os.environ.copy()\n    with _config_file() as config_file:\n        env[\"PYO3_CONFIG_FILE\"] = config_file.name\n\n        assert \"3.6\" not in PY_VERSIONS\n        config_file.set(\"CPython\", \"3.6\")\n        _run_cargo(session, \"check\", env=env, expect_error=True)\n\n        assert \"3.16\" not in PY_VERSIONS\n        config_file.set(\"CPython\", \"3.16\")\n        _run_cargo(session, \"check\", env=env, expect_error=True)\n\n        # 3.16 CPython should build if abi3 is explicitly requested\n        _run_cargo(session, \"check\", \"--features=pyo3/abi3\", env=env)\n\n        # 3.15 CPython should build with forward compatibility\n        # TODO: check on 3.16 when adding abi3-py315 support\n        config_file.set(\"CPython\", \"3.15\")\n        env[\"PYO3_USE_ABI3_FORWARD_COMPATIBILITY\"] = \"1\"\n        _run_cargo(session, \"check\", env=env)\n\n        assert \"3.10\" not in PYPY_VERSIONS\n        config_file.set(\"PyPy\", \"3.10\")\n        _run_cargo(session, \"check\", env=env, expect_error=True)\n\n        # 3.13t is no longer supported\n        config_file.set(\"CPython\", \"3.13t\")\n        _run_cargo(session, \"check\", env=env, expect_error=True)\n\n        # 3.14t is PyO3's minimum version of free-threaded Python\n        config_file.set(\"CPython\", \"3.14t\")\n        _run_cargo(session, \"check\", env=env)\n\n    # attempt to build with latest version and check that abi3 version\n    # configured matches the feature\n    max_minor_version = max(int(v.split(\".\")[1]) for v in ABI3_PY_VERSIONS)\n    with tempfile.TemporaryFile() as stderr:\n        env = os.environ.copy()\n        env[\"PYO3_PRINT_CONFIG\"] = \"1\"  # get diagnostics from the build\n        env[\"PYO3_NO_PYTHON\"] = \"1\"  # isolate the build from local Python\n        _run_cargo(\n            session,\n            \"check\",\n            f\"--features=pyo3/abi3-py3{max_minor_version}\",\n            env=env,\n            stderr=stderr,\n            expect_error=True,\n        )\n        stderr.seek(0)\n        stderr = stderr.read().decode()\n    # NB if this assertion fails with something like\n    # \"An abi3-py3* feature must be specified when compiling without a Python\n    # interpreter.\"\n    #\n    # then `ABI3_MAX_MINOR` in `pyo3-build-config/src/impl_.rs` is probably outdated.\n    assert f\"version=3.{max_minor_version}\" in stderr, (\n        f\"Expected to see version=3.{max_minor_version}, got: \\n\\n{stderr}\"\n    )\n\n\ndef _check_raw_dylib_macro(session: nox.Session):\n    \"\"\"Check that extern_libpython! macro covers all supported Python DLL names.\"\"\"\n    min_version, max_version = _parse_supported_interpreter_version(\"cpython\")\n    min_minor = int(min_version.split(\".\")[1])\n    max_minor = int(max_version.split(\".\")[1])\n\n    # Build the set of DLL names that default_lib_name_windows can produce\n    expected_dlls = {\"python3\", \"python3_d\"}\n    for minor in range(min_minor, max_minor + 1):\n        expected_dlls.add(f\"python3{minor}\")\n        expected_dlls.add(f\"python3{minor}_d\")\n        if minor >= 13:\n            expected_dlls.add(f\"python3{minor}t\")\n            expected_dlls.add(f\"python3{minor}t_d\")\n\n    # PyPy DLL names (libpypy3.X-c.dll)\n    pypy_min, pypy_max = _parse_supported_interpreter_version(\"pypy\")\n    pypy_min_minor = int(pypy_min.split(\".\")[1])\n    pypy_max_minor = int(pypy_max.split(\".\")[1])\n    for minor in range(pypy_min_minor, pypy_max_minor + 1):\n        expected_dlls.add(f\"libpypy3.{minor}-c\")\n\n    # Parse the DLL name list in the extern_libpython!(@impl ...) invocation\n    lib_rs = (PYO3_DIR / \"pyo3-ffi\" / \"src\" / \"impl_\" / \"macros.rs\").read_text()\n    found_dlls = set(re.findall(r'\"((?:python|libpypy)[^\"]+)\"', lib_rs))\n\n    missing = expected_dlls - found_dlls\n    extra = found_dlls - expected_dlls\n    errors = []\n    if missing:\n        errors.append(\n            f\"Missing DLL names in extern_libpython! macro: {sorted(missing)}\"\n        )\n    if extra:\n        errors.append(f\"Extra DLL names in extern_libpython! macro: {sorted(extra)}\")\n    if errors:\n        session.error(\n            \"\\n\".join(errors)\n            + \"\\n\\nUpdate the extern_libpython! macro in pyo3-ffi/src/impl_/macros.rs\"\n            + \" to match supported Python versions in pyo3-ffi/Cargo.toml\"\n        )\n    session.log(\n        f\"extern_libpython! macro covers all {len(expected_dlls)} expected DLL names ✓\"\n    )\n\n    private_fn_allowlist = set(re.findall(r\"\\[\\s*(_Py[A-Za-z0-9_]*)\\s*\\]\", lib_rs))\n    required_private_fns = _raw_dylib_x86_private_functions()\n\n    missing = required_private_fns - private_fn_allowlist\n    extra = private_fn_allowlist - required_private_fns\n    errors = []\n    if missing:\n        errors.append(\n            \"Missing x86 raw-dylib workaround entries for CPython private functions: \"\n            f\"{sorted(missing)}\"\n        )\n    if extra:\n        errors.append(\n            \"Unexpected x86 raw-dylib workaround entries for non-CPython/private functions: \"\n            f\"{sorted(extra)}\"\n        )\n    if errors:\n        session.error(\n            \"\\n\".join(errors)\n            + \"\\n\\nUpdate extern_libpython_maybe_private_fn! in pyo3-ffi/src/impl_/macros.rs\"\n            + \" to match the CPython `_Py*` function imports declared via extern_libpython!.\"\n        )\n    session.log(\n        \"extern_libpython_maybe_private_fn! covers all required x86 CPython\"\n        f\" private function imports ({len(required_private_fns)}) ✓\"\n    )\n\n\ndef _raw_dylib_x86_private_functions() -> Set[str]:\n    ffi_src = PYO3_DIR / \"pyo3-ffi\" / \"src\"\n    private_fns = set()\n    for path in ffi_src.rglob(\"*.rs\"):\n        for block in _iter_extern_libpython_blocks(path.read_text()):\n            attrs: List[str] = []\n            for line in block.splitlines():\n                stripped = line.strip()\n                if stripped.startswith(\"#[\"):\n                    attrs.append(stripped)\n                    continue\n\n                match = re.search(r\"\\bfn\\s+(_Py[A-Za-z0-9_]*)\\b\", stripped)\n                if match:\n                    if not any(\n                        _cfg_attr_is_non_cpython_only(attr)\n                        for attr in attrs\n                        if attr.startswith(\"#[cfg(\")\n                    ):\n                        private_fns.add(match.group(1))\n                    attrs = []\n                    continue\n\n                if stripped and not stripped.startswith(\"//\"):\n                    attrs = []\n\n    return private_fns\n\n\ndef _iter_extern_libpython_blocks(source: str) -> Iterator[str]:\n    cursor = 0\n    while True:\n        start = source.find(\"extern_libpython!\", cursor)\n        if start == -1:\n            return\n\n        block_start = source.find(\"{\", start)\n        if block_start == -1:\n            return\n\n        depth = 0\n        for idx in range(block_start, len(source)):\n            if source[idx] == \"{\":\n                depth += 1\n            elif source[idx] == \"}\":\n                depth -= 1\n                if depth == 0:\n                    yield source[block_start + 1 : idx]\n                    cursor = idx + 1\n                    break\n        else:\n            return\n\n\ndef _cfg_attr_is_non_cpython_only(attr: str) -> bool:\n    \"\"\"Check if a #[cfg()] attribute targets only non-CPython implementations.\n\n    Functions behind #[cfg(PyPy)] or #[cfg(GraalPy)] are linked against the\n    PyPy/GraalPy runtime, not the CPython DLL, so they don't need the x86\n    raw-dylib underscore workaround.\n    \"\"\"\n    match = re.fullmatch(r\"#\\[cfg\\((.*)\\)\\]\", attr)\n    if match is None:\n        return False\n\n    return bool(\n        re.fullmatch(\n            r\"\\s*(?:any\\()?\\s*(?:PyPy|GraalPy)\\s*(?:,\\s*(?:PyPy|GraalPy)\\s*)*\\)?\\s*\",\n            match.group(1),\n        )\n    )\n\n\n@nox.session(name=\"check-feature-powerset\", venv_backend=\"none\")\ndef check_feature_powerset(session: nox.Session):\n    if toml is None:\n        session.error(\"requires Python 3.11 or `toml` to be installed\")\n\n    cargo_toml = toml.loads((PYO3_DIR / \"Cargo.toml\").read_text())\n\n    # free-threaded builds do not support ABI3 (yet)\n    EXPECTED_ABI3_FEATURES = {\n        f\"abi3-py3{ver.split('.')[1]}\" for ver in ABI3_PY_VERSIONS\n    }\n\n    EXCLUDED_FROM_FULL = {\n        \"nightly\",\n        \"extension-module\",\n        \"full\",\n        \"default\",\n        \"auto-initialize\",\n        \"generate-import-lib\",\n        \"multiple-pymethods\",  # Because it's not supported on wasm\n    }\n\n    features = cargo_toml[\"features\"]\n\n    full_feature = set(features[\"full\"])\n    abi3_features = {feature for feature in features if feature.startswith(\"abi3\")}\n    abi3_version_features = abi3_features - {\"abi3\"}\n\n    unexpected_abi3_features = abi3_version_features - EXPECTED_ABI3_FEATURES\n    if unexpected_abi3_features:\n        session.error(\n            f\"unexpected `abi3` features found in Cargo.toml: {unexpected_abi3_features}\"\n        )\n\n    missing_abi3_features = EXPECTED_ABI3_FEATURES - abi3_version_features\n    if missing_abi3_features:\n        session.error(f\"missing `abi3` features in Cargo.toml: {missing_abi3_features}\")\n\n    expected_full_feature = features.keys() - EXCLUDED_FROM_FULL - abi3_features\n\n    uncovered_features = expected_full_feature - full_feature\n    if uncovered_features:\n        session.error(\n            f\"some features missing from `full` meta feature: {uncovered_features}\"\n        )\n\n    experimental_features = {\n        feature for feature in features if feature.startswith(\"experimental-\")\n    }\n    full_without_experimental = full_feature - experimental_features\n\n    if len(experimental_features) >= 2:\n        # justification: we always assume that feature within these groups are\n        # mutually exclusive to simplify CI\n        features_to_group = [\n            full_without_experimental,\n            experimental_features,\n        ]\n    elif len(experimental_features) == 1:\n        # no need to make an experimental features group\n        features_to_group = [full_without_experimental]\n    else:\n        session.error(\"no experimental features exist; please simplify the noxfile\")\n\n    features_to_skip = [\n        *(EXCLUDED_FROM_FULL),\n        *abi3_version_features,\n    ]\n\n    # deny warnings\n    env = os.environ.copy()\n    rust_flags = env.get(\"RUSTFLAGS\", \"\")\n    env[\"RUSTFLAGS\"] = f\"{rust_flags} -Dwarnings\"\n\n    subcommand = \"hack\"\n    if \"minimal-versions\" in session.posargs:\n        subcommand = \"minimal-versions\"\n\n    comma_join = \",\".join\n    _run_cargo(\n        session,\n        subcommand,\n        \"--feature-powerset\",\n        '--optional-deps=\"\"',\n        f'--skip=\"{comma_join(features_to_skip)}\"',\n        *(f\"--group-features={comma_join(group)}\" for group in features_to_group),\n        \"check\",\n        \"--all-targets\",\n        env=env,\n    )\n\n\n@nox.session(name=\"update-ui-tests\", venv_backend=\"none\")\ndef update_ui_tests(session: nox.Session):\n    env = os.environ.copy()\n    env[\"TRYBUILD\"] = \"overwrite\"\n    command = [\"test\", \"--test\", \"test_compile_error\"]\n    _run_cargo(session, *command, env=env)\n    _run_cargo(session, *command, \"--features=full\", env=env)\n    _run_cargo(session, *command, \"--features=abi3,full\", env=env)\n\n\n@nox.session(name=\"test-introspection\")\ndef test_introspection(session: nox.Session):\n    session.install(\"maturin\")\n    session.install(\"ruff\")\n    options = []\n    target = os.environ.get(\"CARGO_BUILD_TARGET\")\n    if target is not None:\n        options += (\"--target\", target)\n    profile = os.environ.get(\"CARGO_BUILD_PROFILE\")\n    if profile == \"release\":\n        options.append(\"--release\")\n    session.run_always(\n        \"maturin\",\n        \"develop\",\n        \"-m\",\n        \"./pytests/Cargo.toml\",\n        \"--features\",\n        \"experimental-async,experimental-inspect\",\n        *options,\n    )\n    lib_file = session.run(\n        \"python\",\n        \"-c\",\n        \"import pyo3_pytests; print(pyo3_pytests.pyo3_pytests.__file__)\",\n        silent=True,\n    ).strip()\n    _run_cargo_test(\n        session,\n        package=\"pyo3-introspection\",\n        env={\"PYO3_PYTEST_LIB_PATH\": lib_file},\n    )\n\n\ndef _build_docs_for_ffi_check(session: nox.Session) -> None:\n    # pyo3-ffi-check needs to scrape docs of pyo3-ffi\n    env = os.environ.copy()\n    env[\"PYO3_PYTHON\"] = sys.executable\n    _run_cargo(session, \"doc\", _FFI_CHECK, \"-p\", \"pyo3-ffi\", \"--no-deps\", env=env)\n\n\n@lru_cache()\ndef _get_rust_info() -> Tuple[str, ...]:\n    output = _get_output(\"rustc\", \"-vV\")\n\n    return tuple(output.splitlines())\n\n\ndef get_rust_version() -> Tuple[int, int, int, List[str]]:\n    for line in _get_rust_info():\n        if line.startswith(_RELEASE_LINE_START):\n            version = line[len(_RELEASE_LINE_START) :].strip()\n            # e.g. 1.67.0-beta.2\n            (version_number, *extra) = version.split(\"-\", maxsplit=1)\n            return (*map(int, version_number.split(\".\")), extra)\n\n\ndef is_rust_nightly() -> bool:\n    for line in _get_rust_info():\n        if line.startswith(_RELEASE_LINE_START):\n            return line.strip().endswith(\"-nightly\")\n    return False\n\n\ndef _get_rust_default_target() -> str:\n    for line in _get_rust_info():\n        if line.startswith(_HOST_LINE_START):\n            return line[len(_HOST_LINE_START) :].strip()\n\n\n@lru_cache()\ndef _get_feature_sets() -> Tuple[Optional[str], ...]:\n    \"\"\"Returns feature sets to use for Rust jobs\"\"\"\n    cargo_target = os.getenv(\"CARGO_BUILD_TARGET\", \"\")\n\n    features = \"full\"\n\n    if \"wasm32-wasip1\" not in cargo_target:\n        # multiple-pymethods not supported on wasm\n        features += \",multiple-pymethods\"\n\n    if is_rust_nightly():\n        features += \",nightly\"\n\n    return (None, \"abi3\", features, f\"abi3,{features}\")\n\n\n_RELEASE_LINE_START = \"release: \"\n_HOST_LINE_START = \"host: \"\n\n\ndef _get_coverage_env() -> Dict[str, str]:\n    env = {}\n    output = _get_output(\"cargo\", \"llvm-cov\", \"show-env\")\n\n    for line in output.strip().splitlines():\n        (key, value) = line.split(\"=\", maxsplit=1)\n        # Strip single or double quotes from the variable value\n        # - quote used by llvm-cov differs between Windows and Linux\n        if value and value[0] in (\"'\", '\"'):\n            value = value[1:-1]\n        env[key] = value\n\n    # Ensure that examples/ and pytests/ all build to the correct target directory to collect\n    # coverage artifacts.\n    env[\"CARGO_TARGET_DIR\"] = env[\"CARGO_LLVM_COV_TARGET_DIR\"]\n\n    return env\n\n\ndef _run(session: nox.Session, *args: str, **kwargs: Any) -> None:\n    \"\"\"Wrapper for _run(session, which creates nice groups on GitHub Actions.\"\"\"\n    is_github_actions = _is_github_actions()\n    failed = False\n    if is_github_actions:\n        # Insert ::group:: at the start of nox's command line output\n        print(\"::group::\", end=\"\", flush=True, file=sys.stderr)\n    try:\n        session.run(*args, **kwargs)\n    except nox.command.CommandFailed:\n        failed = True\n        raise\n    finally:\n        if is_github_actions:\n            print(\"::endgroup::\", file=sys.stderr)\n            # Defer the error message until after the group to make them easier\n            # to find in the log\n            if failed:\n                command = \" \".join(args)\n                print(f\"::error::`{command}` failed\", file=sys.stderr)\n\n\ndef _run_cargo(\n    session: nox.Session, *args: str, expect_error: bool = False, **kwargs: Any\n) -> None:\n    if expect_error:\n        if \"success_codes\" in kwargs:\n            raise ValueError(\"expect_error overrides success_codes\")\n        kwargs[\"success_codes\"] = [101]\n    _run(session, \"cargo\", *args, **kwargs, external=True)\n\n\ndef _run_cargo_test(\n    session: nox.Session,\n    *,\n    package: Optional[str] = None,\n    features: Optional[str] = None,\n    env: Optional[Dict[str, str]] = None,\n    extra_flags: Optional[List[str]] = None,\n) -> None:\n    command = [\"cargo\"]\n    if \"careful\" in session.posargs:\n        # do explicit setup so failures in setup can be seen\n        _run_cargo(session, \"careful\", \"setup\")\n        command.append(\"careful\")\n\n    command.extend((\"test\", \"--no-fail-fast\"))\n\n    if \"release\" in session.posargs:\n        command.append(\"--release\")\n    if package:\n        command.append(f\"--package={package}\")\n    if features:\n        command.append(f\"--features={features}\")\n    if extra_flags:\n        command.extend(extra_flags)\n\n    _run(session, *command, external=True, env=env or {})\n\n\ndef _run_cargo_publish(session: nox.Session, *, package: str) -> None:\n    _run_cargo(session, \"publish\", f\"--package={package}\")\n\n\ndef _run_cargo_set_package_version(\n    session: nox.Session,\n    pkg_id: str,\n    version: str,\n    *,\n    project: Optional[str] = None,\n) -> None:\n    command = [\"cargo\", \"update\", \"-p\", pkg_id, \"--precise\", version, \"--workspace\"]\n    if project:\n        command.append(f\"--manifest-path={project}/Cargo.toml\")\n    _run(session, *command, external=True)\n\n\ndef _for_all_version_configs(\n    session: nox.Session, job: Callable[[Dict[str, str]], None]\n) -> None:\n    env = os.environ.copy()\n    with _config_file() as config_file:\n        env[\"PYO3_CONFIG_FILE\"] = config_file.name\n\n        def _job_with_config(implementation, version):\n            session.log(f\"{implementation} {version}\")\n            config_file.set(implementation, version)\n            job(env)\n\n        for version in PY_VERSIONS:\n            _job_with_config(\"CPython\", version)\n\n        for version in PYPY_VERSIONS:\n            _job_with_config(\"PyPy\", version)\n\n\nclass _ConfigFile:\n    def __init__(self, config_file) -> None:\n        self._config_file = config_file\n\n    def set(\n        self, implementation: str, version: str, build_flags: Iterable[str] = ()\n    ) -> None:\n        \"\"\"Set the contents of this config file to the given implementation and version.\"\"\"\n        if version.endswith(\"t\"):\n            # Free threaded versions pass the support in config file through a flag\n            version = version[:-1]\n            build_flags = (*build_flags, \"Py_GIL_DISABLED\")\n\n        self._config_file.seek(0)\n        self._config_file.truncate(0)\n        self._config_file.write(\n            f\"\"\"\\\nimplementation={implementation}\nversion={version}\nbuild_flags={\",\".join(build_flags)}\nsuppress_build_script_link_lines=true\n\"\"\"\n        )\n        self._config_file.flush()\n\n    @property\n    def name(self) -> str:\n        return self._config_file.name\n\n\n@contextmanager\ndef _config_file() -> Iterator[_ConfigFile]:\n    \"\"\"Creates a temporary config file which can be repeatedly set to different values.\"\"\"\n    with tempfile.NamedTemporaryFile(\"r+\") as config:\n        yield _ConfigFile(config)\n\n\ndef _is_github_actions() -> bool:\n    return \"GITHUB_ACTIONS\" in os.environ\n\n\n_BENCHES = \"--manifest-path=pyo3-benches/Cargo.toml\"\n_FFI_CHECK = \"--manifest-path=pyo3-ffi-check/Cargo.toml\"\n"
  },
  {
    "path": "pyo3-benches/Cargo.toml",
    "content": "[package]\nname = \"pyo3-benches\"\nversion = \"0.1.0\"\ndescription = \"In-tree benchmarks for the PyO3 project\"\nauthors = [\"PyO3 Project and Contributors <https://github.com/PyO3>\"]\nedition = \"2021\"\npublish = false\n\n[dependencies]\npyo3 = { path = \"../\", features = [\"auto-initialize\", \"full\"] }\n\n[build-dependencies]\npyo3-build-config = { path = \"../pyo3-build-config\" }\n\n[dev-dependencies]\ncodspeed-criterion-compat = \"4.0\"\ncriterion = \"0.8.0\"\nnum-bigint = \"0.4.3\"\nrust_decimal = { version = \"1.0.0\", default-features = false }\nhashbrown = \"0.16\"\n\n[features]\nabi3 = [\"pyo3-build-config/abi3\"]\n\n[[bench]]\nname = \"bench_any\"\nharness = false\n\n[[bench]]\nname = \"bench_attach\"\nharness = false\n\n[[bench]]\nname = \"bench_call\"\nharness = false\n\n[[bench]]\nname = \"bench_comparisons\"\nharness = false\n\n[[bench]]\nname = \"bench_critical_sections\"\nharness = false\n\n[[bench]]\nname = \"bench_err\"\nharness = false\n\n[[bench]]\nname = \"bench_decimal\"\nharness = false\n\n[[bench]]\nname = \"bench_dict\"\nharness = false\n\n[[bench]]\nname = \"bench_frompyobject\"\nharness = false\n\n[[bench]]\nname = \"bench_intopyobject\"\nharness = false\n\n[[bench]]\nname = \"bench_list\"\nharness = false\n\n[[bench]]\nname = \"bench_py\"\nharness = false\n\n[[bench]]\nname = \"bench_pyclass\"\nharness = false\n\n[[bench]]\nname = \"bench_set\"\nharness = false\n\n[[bench]]\nname = \"bench_tuple\"\nharness = false\n\n[[bench]]\nname = \"bench_intern\"\nharness = false\n\n[[bench]]\nname = \"bench_extract\"\nharness = false\n\n[[bench]]\nname = \"bench_bigint\"\nharness = false\n\n[[bench]]\nname = \"bench_pystring_from_fmt\"\nharness = false\n\n[workspace]\n"
  },
  {
    "path": "pyo3-benches/benches/bench_any.rs",
    "content": "use codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::{\n    prelude::*,\n    types::{\n        PyBool, PyByteArray, PyBytes, PyDict, PyFloat, PyFrozenSet, PyInt, PyList, PyMapping,\n        PySequence, PySet, PyString, PyTuple,\n    },\n};\n\n#[derive(PartialEq, Eq, Debug)]\nenum ObjectType {\n    None,\n    Bool,\n    ByteArray,\n    Bytes,\n    Dict,\n    Float,\n    FrozenSet,\n    Int,\n    List,\n    Set,\n    Str,\n    Tuple,\n    Sequence,\n    Mapping,\n    Unknown,\n}\n\nfn find_object_type(obj: &Bound<'_, PyAny>) -> ObjectType {\n    if obj.is_none() {\n        ObjectType::None\n    } else if obj.is_instance_of::<PyBool>() {\n        ObjectType::Bool\n    } else if obj.is_instance_of::<PyByteArray>() {\n        ObjectType::ByteArray\n    } else if obj.is_instance_of::<PyBytes>() {\n        ObjectType::Bytes\n    } else if obj.is_instance_of::<PyDict>() {\n        ObjectType::Dict\n    } else if obj.is_instance_of::<PyFloat>() {\n        ObjectType::Float\n    } else if obj.is_instance_of::<PyFrozenSet>() {\n        ObjectType::FrozenSet\n    } else if obj.is_instance_of::<PyInt>() {\n        ObjectType::Int\n    } else if obj.is_instance_of::<PyList>() {\n        ObjectType::List\n    } else if obj.is_instance_of::<PySet>() {\n        ObjectType::Set\n    } else if obj.is_instance_of::<PyString>() {\n        ObjectType::Str\n    } else if obj.is_instance_of::<PyTuple>() {\n        ObjectType::Tuple\n    } else if obj.cast::<PySequence>().is_ok() {\n        ObjectType::Sequence\n    } else if obj.cast::<PyMapping>().is_ok() {\n        ObjectType::Mapping\n    } else {\n        ObjectType::Unknown\n    }\n}\n\nfn bench_identify_object_type(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let obj = py.eval(c\"object()\", None, None).unwrap();\n\n        b.iter(|| find_object_type(&obj));\n\n        assert_eq!(find_object_type(&obj), ObjectType::Unknown);\n    });\n}\n\nfn bench_collect_generic_iterator(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let collection = py.eval(c\"list(range(1 << 20))\", None, None).unwrap();\n\n        b.iter(|| {\n            collection\n                .try_iter()\n                .unwrap()\n                .collect::<PyResult<Vec<_>>>()\n                .unwrap()\n        });\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"identify_object_type\", bench_identify_object_type);\n    c.bench_function(\"collect_generic_iterator\", bench_collect_generic_iterator);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_attach.rs",
    "content": "use codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::prelude::*;\n\nfn bench_clean_attach(b: &mut Bencher<'_>) {\n    // Acquiring first GIL will also create a \"clean\" GILPool, so this measures the Python overhead.\n    b.iter(|| Python::attach(|_| {}));\n}\n\nfn bench_dirty_attach(b: &mut Bencher<'_>) {\n    let obj = Python::attach(|py| py.None());\n    // Drop the returned clone of the object so that the reference pool has work to do.\n    b.iter(|| Python::attach(|py| obj.clone_ref(py)));\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"clean_attach\", bench_clean_attach);\n    c.bench_function(\"dirty_attach\", bench_dirty_attach);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_bigint.rs",
    "content": "use std::hint::black_box;\n\nuse codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\nuse num_bigint::BigInt;\n\nuse pyo3::prelude::*;\nuse pyo3::types::PyDict;\n\nfn extract_bigint_extract_fail(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let d = PyDict::new(py).into_any();\n\n        bench.iter(|| match black_box(&d).extract::<BigInt>() {\n            Ok(v) => panic!(\"should err {}\", v),\n            Err(e) => e,\n        });\n    });\n}\n\nfn extract_bigint_small(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let int = py.eval(c\"-42\", None, None).unwrap();\n\n        bench.iter_with_large_drop(|| black_box(&int).extract::<BigInt>().unwrap());\n    });\n}\n\nfn extract_bigint_big_negative(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let int = py.eval(c\"-10**300\", None, None).unwrap();\n\n        bench.iter_with_large_drop(|| black_box(&int).extract::<BigInt>().unwrap());\n    });\n}\n\nfn extract_bigint_big_positive(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let int = py.eval(c\"10**300\", None, None).unwrap();\n\n        bench.iter_with_large_drop(|| black_box(&int).extract::<BigInt>().unwrap());\n    });\n}\n\nfn extract_bigint_huge_negative(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let int = py.eval(c\"-10**3000\", None, None).unwrap();\n\n        bench.iter_with_large_drop(|| black_box(&int).extract::<BigInt>().unwrap());\n    });\n}\n\nfn extract_bigint_huge_positive(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let int = py.eval(c\"10**3000\", None, None).unwrap();\n\n        bench.iter_with_large_drop(|| black_box(&int).extract::<BigInt>().unwrap());\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"extract_bigint_extract_fail\", extract_bigint_extract_fail);\n    c.bench_function(\"extract_bigint_small\", extract_bigint_small);\n    c.bench_function(\"extract_bigint_big_negative\", extract_bigint_big_negative);\n    c.bench_function(\"extract_bigint_big_positive\", extract_bigint_big_positive);\n    c.bench_function(\"extract_bigint_huge_negative\", extract_bigint_huge_negative);\n    c.bench_function(\"extract_bigint_huge_positive\", extract_bigint_huge_positive);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_call.rs",
    "content": "use std::hint::black_box;\n\nuse codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::ffi::c_str;\nuse pyo3::prelude::*;\nuse pyo3::types::IntoPyDict;\n\nmacro_rules! test_module {\n    ($py:ident, $code:literal) => {\n        PyModule::from_code($py, c_str!($code), c_str!(file!()), c\"test_module\")\n            .expect(\"module creation failed\")\n    };\n}\n\nfn bench_call_0(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let module = test_module!(py, \"def foo(): pass\");\n\n        let foo_module = &module.getattr(\"foo\").unwrap();\n\n        b.iter(|| {\n            for _ in 0..1000 {\n                black_box(foo_module).call0().unwrap();\n            }\n        });\n    })\n}\n\nfn bench_call_1(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let module = test_module!(py, \"def foo(a, b, c): pass\");\n\n        let foo_module = &module.getattr(\"foo\").unwrap();\n        let args = (\n            1.into_pyobject(py).unwrap(),\n            \"s\".into_pyobject(py).unwrap(),\n            1.23.into_pyobject(py).unwrap(),\n        );\n\n        b.iter(|| {\n            for _ in 0..1000 {\n                black_box(foo_module).call1(args.clone()).unwrap();\n            }\n        });\n    })\n}\n\nfn bench_call(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let module = test_module!(py, \"def foo(a, b, c, d, e): pass\");\n\n        let foo_module = &module.getattr(\"foo\").unwrap();\n        let args = (\n            1.into_pyobject(py).unwrap(),\n            \"s\".into_pyobject(py).unwrap(),\n            1.23.into_pyobject(py).unwrap(),\n        );\n        let kwargs = [(\"d\", 1), (\"e\", 42)].into_py_dict(py).unwrap();\n\n        b.iter(|| {\n            for _ in 0..1000 {\n                black_box(foo_module)\n                    .call(args.clone(), Some(&kwargs))\n                    .unwrap();\n            }\n        });\n    })\n}\n\nfn bench_call_one_arg(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let module = test_module!(py, \"def foo(a): pass\");\n\n        let foo_module = &module.getattr(\"foo\").unwrap();\n        let arg = 1i32.into_pyobject(py).unwrap();\n\n        b.iter(|| {\n            for _ in 0..1000 {\n                black_box(foo_module).call1((arg.clone(),)).unwrap();\n            }\n        });\n    })\n}\n\nfn bench_call_method_0(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let module = test_module!(\n            py,\n            \"\nclass Foo:\n    def foo(self):\n        pass\n\"\n        );\n\n        let foo_module = &module.getattr(\"Foo\").unwrap().call0().unwrap();\n\n        b.iter(|| {\n            for _ in 0..1000 {\n                black_box(foo_module).call_method0(\"foo\").unwrap();\n            }\n        });\n    })\n}\n\nfn bench_call_method_1(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let module = test_module!(\n            py,\n            \"\nclass Foo:\n    def foo(self, a, b, c):\n        pass\n\"\n        );\n\n        let foo_module = &module.getattr(\"Foo\").unwrap().call0().unwrap();\n        let args = (\n            1.into_pyobject(py).unwrap(),\n            \"s\".into_pyobject(py).unwrap(),\n            1.23.into_pyobject(py).unwrap(),\n        );\n\n        b.iter(|| {\n            for _ in 0..1000 {\n                black_box(foo_module)\n                    .call_method1(\"foo\", args.clone())\n                    .unwrap();\n            }\n        });\n    })\n}\n\nfn bench_call_method(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let module = test_module!(\n            py,\n            \"\nclass Foo:\n    def foo(self, a, b, c, d, e):\n        pass\n\"\n        );\n\n        let foo_module = &module.getattr(\"Foo\").unwrap().call0().unwrap();\n        let args = (\n            1.into_pyobject(py).unwrap(),\n            \"s\".into_pyobject(py).unwrap(),\n            1.23.into_pyobject(py).unwrap(),\n        );\n        let kwargs = [(\"d\", 1), (\"e\", 42)].into_py_dict(py).unwrap();\n\n        b.iter(|| {\n            for _ in 0..1000 {\n                black_box(foo_module)\n                    .call_method(\"foo\", args.clone(), Some(&kwargs))\n                    .unwrap();\n            }\n        });\n    })\n}\n\nfn bench_call_method_one_arg(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let module = test_module!(\n            py,\n            \"\nclass Foo:\n    def foo(self, a):\n        pass\n\"\n        );\n\n        let foo_module = &module.getattr(\"Foo\").unwrap().call0().unwrap();\n        let arg = 1i32.into_pyobject(py).unwrap();\n\n        b.iter(|| {\n            for _ in 0..1000 {\n                black_box(foo_module)\n                    .call_method1(\"foo\", (arg.clone(),))\n                    .unwrap();\n            }\n        });\n    })\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"call_0\", bench_call_0);\n    c.bench_function(\"call_1\", bench_call_1);\n    c.bench_function(\"call\", bench_call);\n    c.bench_function(\"call_one_arg\", bench_call_one_arg);\n    c.bench_function(\"call_method_0\", bench_call_method_0);\n    c.bench_function(\"call_method_1\", bench_call_method_1);\n    c.bench_function(\"call_method\", bench_call_method);\n    c.bench_function(\"call_method_one_arg\", bench_call_method_one_arg);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_comparisons.rs",
    "content": "use codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::{prelude::*, pyclass::CompareOp, Python};\n\n#[pyclass]\nstruct OrderedDunderMethods(i64);\n\n#[pymethods]\nimpl OrderedDunderMethods {\n    fn __lt__(&self, other: &Self) -> bool {\n        self.0 < other.0\n    }\n\n    fn __le__(&self, other: &Self) -> bool {\n        self.0 <= other.0\n    }\n\n    fn __eq__(&self, other: &Self) -> bool {\n        self.0 == other.0\n    }\n\n    fn __ne__(&self, other: &Self) -> bool {\n        self.0 != other.0\n    }\n\n    fn __gt__(&self, other: &Self) -> bool {\n        self.0 > other.0\n    }\n\n    fn __ge__(&self, other: &Self) -> bool {\n        self.0 >= other.0\n    }\n}\n\n#[pyclass]\n#[derive(PartialEq, Eq, PartialOrd, Ord)]\nstruct OrderedRichcmp(i64);\n\n#[pymethods]\nimpl OrderedRichcmp {\n    fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool {\n        op.matches(self.cmp(other))\n    }\n}\n\nfn bench_ordered_dunder_methods(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let obj1 = &Bound::new(py, OrderedDunderMethods(0)).unwrap().into_any();\n        let obj2 = &Bound::new(py, OrderedDunderMethods(1)).unwrap().into_any();\n\n        b.iter(|| obj2.gt(obj1).unwrap());\n    });\n}\n\nfn bench_ordered_richcmp(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let obj1 = &Bound::new(py, OrderedRichcmp(0)).unwrap().into_any();\n        let obj2 = &Bound::new(py, OrderedRichcmp(1)).unwrap().into_any();\n\n        b.iter(|| obj2.gt(obj1).unwrap());\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"ordered_dunder_methods\", bench_ordered_dunder_methods);\n    c.bench_function(\"ordered_richcmp\", bench_ordered_richcmp);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_critical_sections.rs",
    "content": "use codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::prelude::*;\nuse pyo3::sync::critical_section::{with_critical_section, with_critical_section2};\nuse pyo3::types::PyList;\n\nfn create_cs(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let lis = PyList::new(py, 0..3).unwrap();\n        b.iter(|| {\n            with_critical_section(&lis, || {});\n        })\n    });\n}\n\nfn create_cs2(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let lis1 = PyList::new(py, 0..3).unwrap();\n        let lis2 = PyList::new(py, 4..6).unwrap();\n        b.iter(|| {\n            with_critical_section2(&lis1, &lis2, || {});\n        })\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"critical_section_creation\", create_cs);\n    c.bench_function(\"critical_section_creation2\", create_cs2);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_decimal.rs",
    "content": "use std::hint::black_box;\n\nuse codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\nuse rust_decimal::Decimal;\n\nuse pyo3::prelude::*;\nuse pyo3::types::PyDict;\n\nfn decimal_via_extract(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let locals = PyDict::new(py);\n        py.run(\n            cr#\"\nimport decimal\npy_dec = decimal.Decimal(\"0.0\")\n\"#,\n            None,\n            Some(&locals),\n        )\n        .unwrap();\n        let py_dec = locals.get_item(\"py_dec\").unwrap().unwrap();\n\n        b.iter(|| black_box(&py_dec).extract::<Decimal>().unwrap());\n    })\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"decimal_via_extract\", decimal_via_extract);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_dict.rs",
    "content": "use std::collections::{BTreeMap, HashMap};\nuse std::hint::black_box;\n\nuse codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::types::IntoPyDict;\nuse pyo3::{prelude::*, types::PyMapping};\n\nfn iter_dict(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        let dict = (0..LEN as u64)\n            .map(|i| (i, i * 2))\n            .into_py_dict(py)\n            .unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for (k, _v) in &dict {\n                let i: u64 = k.extract().unwrap();\n                sum += i;\n            }\n        });\n    })\n}\n\nfn dict_new(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        b.iter_with_large_drop(|| {\n            (0..LEN as u64)\n                .map(|i| (i, i * 2))\n                .into_py_dict(py)\n                .unwrap()\n        });\n    });\n}\n\nfn dict_get_item(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        let dict = (0..LEN as u64)\n            .map(|i| (i, i * 2))\n            .into_py_dict(py)\n            .unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for i in 0..LEN {\n                sum += dict\n                    .get_item(i)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<usize>()\n                    .unwrap();\n            }\n        });\n    });\n}\n\nfn extract_hashmap(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        let dict = (0..LEN as u64)\n            .map(|i| (i, i * 2))\n            .into_py_dict(py)\n            .unwrap()\n            .into_any();\n        b.iter(|| HashMap::<u64, u64>::extract(dict.as_borrowed()));\n    });\n}\n\nfn extract_btreemap(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        let dict = (0..LEN as u64)\n            .map(|i| (i, i * 2))\n            .into_py_dict(py)\n            .unwrap()\n            .into_any();\n        b.iter(|| BTreeMap::<u64, u64>::extract(dict.as_borrowed()));\n    });\n}\n\nfn extract_hashbrown_map(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        let dict = (0..LEN as u64)\n            .map(|i| (i, i * 2))\n            .into_py_dict(py)\n            .unwrap()\n            .into_any();\n        b.iter(|| hashbrown::HashMap::<u64, u64>::extract(dict.as_borrowed()));\n    });\n}\n\nfn mapping_from_dict(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        let dict = &(0..LEN as u64)\n            .map(|i| (i, i * 2))\n            .into_py_dict(py)\n            .unwrap();\n        b.iter(|| black_box(dict).cast::<PyMapping>().unwrap());\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"iter_dict\", iter_dict);\n    c.bench_function(\"dict_new\", dict_new);\n    c.bench_function(\"dict_get_item\", dict_get_item);\n    c.bench_function(\"extract_hashmap\", extract_hashmap);\n    c.bench_function(\"extract_btreemap\", extract_btreemap);\n    c.bench_function(\"mapping_from_dict\", mapping_from_dict);\n    c.bench_function(\"extract_hashbrown_map\", extract_hashbrown_map);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_err.rs",
    "content": "use codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::{exceptions::PyValueError, prelude::*};\n\nfn err_new_restore_and_fetch(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        b.iter(|| {\n            PyValueError::new_err(\"some exception message\").restore(py);\n            PyErr::fetch(py)\n        })\n    })\n}\n\nfn err_new_without_gil(b: &mut Bencher<'_>) {\n    b.iter(|| PyValueError::new_err(\"some exception message\"))\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"err_new_restore_and_fetch\", err_new_restore_and_fetch);\n    c.bench_function(\"err_new_without_gil\", err_new_without_gil);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_extract.rs",
    "content": "use std::hint::black_box;\n\nuse codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::{\n    prelude::*,\n    types::{PyDict, PyFloat, PyInt, PyString},\n};\n\nfn extract_str_extract_success(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let s = PyString::new(py, \"Hello, World!\").into_any();\n\n        bench.iter(|| black_box(&s).extract::<&str>().unwrap());\n    });\n}\n\nfn extract_str_extract_fail(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let d = PyDict::new(py).into_any();\n\n        bench.iter(|| match black_box(&d).extract::<&str>() {\n            Ok(v) => panic!(\"should err {}\", v),\n            Err(e) => e,\n        });\n    });\n}\n\n#[cfg(Py_3_10)]\nfn extract_str_cast_success(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let s = PyString::new(py, \"Hello, World!\").into_any();\n\n        bench.iter(|| {\n            let py_str = black_box(&s).cast::<PyString>().unwrap();\n            py_str.to_str().unwrap()\n        });\n    });\n}\n\nfn extract_str_cast_fail(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let d = PyDict::new(py).into_any();\n\n        bench.iter(|| match black_box(&d).cast::<PyString>() {\n            Ok(v) => panic!(\"should err {}\", v),\n            Err(e) => e,\n        });\n    });\n}\n\nfn extract_int_extract_success(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let int = 123i32.into_pyobject(py).unwrap();\n\n        bench.iter(|| black_box(&int).extract::<i64>().unwrap());\n    });\n}\n\nfn extract_int_extract_fail(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let d = PyDict::new(py).into_any();\n\n        bench.iter(|| match black_box(&d).extract::<i64>() {\n            Ok(v) => panic!(\"should err {}\", v),\n            Err(e) => e,\n        });\n    });\n}\n\nfn extract_int_cast_success(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let int = 123i32.into_pyobject(py).unwrap();\n\n        bench.iter(|| {\n            let py_int = black_box(&int).cast::<PyInt>().unwrap();\n            py_int.extract::<i64>().unwrap()\n        });\n    });\n}\n\nfn extract_int_cast_fail(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let d = PyDict::new(py).into_any();\n\n        bench.iter(|| match black_box(&d).cast::<PyInt>() {\n            Ok(v) => panic!(\"should err {}\", v),\n            Err(e) => black_box(e),\n        });\n    });\n}\n\nfn extract_float_extract_success(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let float = 23.42f64.into_pyobject(py).unwrap();\n\n        bench.iter(|| black_box(&float).extract::<f64>().unwrap());\n    });\n}\n\nfn extract_float_extract_fail(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let d = PyDict::new(py).into_any();\n\n        bench.iter(|| match black_box(&d).extract::<f64>() {\n            Ok(v) => panic!(\"should err {}\", v),\n            Err(e) => e,\n        });\n    });\n}\n\nfn extract_float_cast_success(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let float = 23.42f64.into_pyobject(py).unwrap();\n\n        bench.iter(|| {\n            let py_float = black_box(&float).cast::<PyFloat>().unwrap();\n            py_float.value()\n        });\n    });\n}\n\nfn extract_float_cast_fail(bench: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let d = PyDict::new(py).into_any();\n\n        bench.iter(|| match black_box(&d).cast::<PyFloat>() {\n            Ok(v) => panic!(\"should err {}\", v),\n            Err(e) => e,\n        });\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"extract_str_extract_success\", extract_str_extract_success);\n    c.bench_function(\"extract_str_extract_fail\", extract_str_extract_fail);\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    c.bench_function(\"extract_str_cast_success\", extract_str_cast_success);\n    c.bench_function(\"extract_str_cast_fail\", extract_str_cast_fail);\n    c.bench_function(\"extract_int_extract_success\", extract_int_extract_success);\n    c.bench_function(\"extract_int_extract_fail\", extract_int_extract_fail);\n    c.bench_function(\"extract_int_cast_success\", extract_int_cast_success);\n    c.bench_function(\"extract_int_cast_fail\", extract_int_cast_fail);\n    c.bench_function(\n        \"extract_float_extract_success\",\n        extract_float_extract_success,\n    );\n    c.bench_function(\"extract_float_extract_fail\", extract_float_extract_fail);\n    c.bench_function(\n        \"extract_float_cast_success\",\n        extract_float_cast_success,\n    );\n    c.bench_function(\"extract_float_cast_fail\", extract_float_cast_fail);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_frompyobject.rs",
    "content": "use std::hint::black_box;\n\nuse codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::{\n    prelude::*,\n    types::{PyByteArray, PyBytes, PyList, PyString},\n};\n\n#[derive(FromPyObject)]\n#[expect(dead_code)]\nenum ManyTypes {\n    Int(i32),\n    Bytes(Vec<u8>),\n    String(String),\n}\n\nfn enum_from_pyobject(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let any = PyString::new(py, \"hello world\").into_any();\n\n        b.iter(|| black_box(&any).extract::<ManyTypes>().unwrap());\n    })\n}\n\nfn list_via_cast(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let any = PyList::empty(py).into_any();\n\n        b.iter(|| black_box(&any).cast::<PyList>().unwrap());\n    })\n}\n\nfn list_via_extract(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let any = PyList::empty(py).into_any();\n\n        b.iter(|| black_box(&any).extract::<Bound<'_, PyList>>().unwrap());\n    })\n}\n\nfn not_a_list_via_cast(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let any = PyString::new(py, \"foobar\").into_any();\n\n        b.iter(|| black_box(&any).cast::<PyList>().unwrap_err());\n    })\n}\n\nfn not_a_list_via_extract(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let any = PyString::new(py, \"foobar\").into_any();\n\n        b.iter(|| black_box(&any).extract::<Bound<'_, PyList>>().unwrap_err());\n    })\n}\n\n#[derive(FromPyObject)]\nenum ListOrNotList<'a> {\n    List(Bound<'a, PyList>),\n    NotList(Bound<'a, PyAny>),\n}\n\nfn not_a_list_via_extract_enum(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let any = PyString::new(py, \"foobar\").into_any();\n\n        b.iter(|| match black_box(&any).extract::<ListOrNotList<'_>>() {\n            Ok(ListOrNotList::List(_list)) => panic!(),\n            Ok(ListOrNotList::NotList(any)) => any,\n            Err(_) => panic!(),\n        });\n    })\n}\n\nfn bench_vec_from_py_bytes(b: &mut Bencher<'_>, data: &[u8]) {\n    Python::attach(|py| {\n        let any = PyBytes::new(py, data).into_any();\n\n        b.iter(|| black_box(&any).extract::<Vec<u8>>().unwrap());\n    })\n}\n\nfn vec_bytes_from_py_bytes_small(b: &mut Bencher<'_>) {\n    bench_vec_from_py_bytes(b, &[]);\n}\n\nfn vec_bytes_from_py_bytes_medium(b: &mut Bencher<'_>) {\n    let data = (0..u8::MAX).collect::<Vec<u8>>();\n    bench_vec_from_py_bytes(b, &data);\n}\n\nfn vec_bytes_from_py_bytes_large(b: &mut Bencher<'_>) {\n    let data = vec![10u8; 100_000];\n    bench_vec_from_py_bytes(b, &data);\n}\n\nfn bench_vec_from_py_bytearray(b: &mut Bencher<'_>, data: &[u8]) {\n    Python::attach(|py| {\n        let any = PyByteArray::new(py, data).into_any();\n\n        b.iter(|| black_box(&any).extract::<Vec<u8>>().unwrap());\n    })\n}\n\nfn vec_bytes_from_py_bytearray_small(b: &mut Bencher<'_>) {\n    bench_vec_from_py_bytearray(b, &[]);\n}\n\nfn vec_bytes_from_py_bytearray_medium(b: &mut Bencher<'_>) {\n    let data = (0..u8::MAX).collect::<Vec<u8>>();\n    bench_vec_from_py_bytearray(b, &data);\n}\n\nfn vec_bytes_from_py_bytearray_large(b: &mut Bencher<'_>) {\n    let data = vec![10u8; 100_000];\n    bench_vec_from_py_bytearray(b, &data);\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"enum_from_pyobject\", enum_from_pyobject);\n\n    c.bench_function(\"list_via_cast\", list_via_cast);\n\n    c.bench_function(\"list_via_extract\", list_via_extract);\n\n    c.bench_function(\"not_a_list_via_cast\", not_a_list_via_cast);\n    c.bench_function(\"not_a_list_via_extract\", not_a_list_via_extract);\n    c.bench_function(\"not_a_list_via_extract_enum\", not_a_list_via_extract_enum);\n\n    c.bench_function(\n        \"vec_bytes_from_py_bytes_small\",\n        vec_bytes_from_py_bytes_small,\n    );\n    c.bench_function(\n        \"vec_bytes_from_py_bytes_medium\",\n        vec_bytes_from_py_bytes_medium,\n    );\n    c.bench_function(\n        \"vec_bytes_from_py_bytes_large\",\n        vec_bytes_from_py_bytes_large,\n    );\n\n    c.bench_function(\n        \"vec_bytes_from_py_bytearray_small\",\n        vec_bytes_from_py_bytearray_small,\n    );\n    c.bench_function(\n        \"vec_bytes_from_py_bytearray_medium\",\n        vec_bytes_from_py_bytearray_medium,\n    );\n    c.bench_function(\n        \"vec_bytes_from_py_bytearray_large\",\n        vec_bytes_from_py_bytearray_large,\n    );\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_intern.rs",
    "content": "use std::hint::black_box;\n\nuse codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::prelude::*;\n\nuse pyo3::intern;\n\nfn getattr_direct(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let sys = &py.import(\"sys\").unwrap();\n\n        b.iter(|| black_box(sys).getattr(\"version\").unwrap());\n    });\n}\n\nfn getattr_intern(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let sys = &py.import(\"sys\").unwrap();\n\n        b.iter(|| black_box(sys).getattr(intern!(py, \"version\")).unwrap());\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"getattr_direct\", getattr_direct);\n    c.bench_function(\"getattr_intern\", getattr_intern);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_intopyobject.rs",
    "content": "use std::hint::black_box;\n\nuse codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::conversion::IntoPyObject;\nuse pyo3::prelude::*;\nuse pyo3::types::PyBytes;\n\nfn bench_bytes_new(b: &mut Bencher<'_>, data: &[u8]) {\n    Python::attach(|py| {\n        b.iter_with_large_drop(|| PyBytes::new(py, black_box(data)));\n    });\n}\n\nfn bytes_new_small(b: &mut Bencher<'_>) {\n    bench_bytes_new(b, &[]);\n}\n\nfn bytes_new_medium(b: &mut Bencher<'_>) {\n    let data = (0..u8::MAX).collect::<Vec<u8>>();\n    bench_bytes_new(b, &data);\n}\n\nfn bytes_new_large(b: &mut Bencher<'_>) {\n    let data = vec![10u8; 100_000];\n    bench_bytes_new(b, &data);\n}\n\nfn bench_bytes_into_pyobject(b: &mut Bencher<'_>, data: &[u8]) {\n    Python::attach(|py| {\n        b.iter_with_large_drop(|| black_box(data).into_pyobject(py));\n    });\n}\n\nfn byte_slice_into_pyobject_small(b: &mut Bencher<'_>) {\n    bench_bytes_into_pyobject(b, &[]);\n}\n\nfn byte_slice_into_pyobject_medium(b: &mut Bencher<'_>) {\n    let data = (0..u8::MAX).collect::<Vec<u8>>();\n    bench_bytes_into_pyobject(b, &data);\n}\n\nfn byte_slice_into_pyobject_large(b: &mut Bencher<'_>) {\n    let data = vec![10u8; 100_000];\n    bench_bytes_into_pyobject(b, &data);\n}\n\nfn vec_into_pyobject(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        let bytes = (0..u8::MAX).collect::<Vec<u8>>();\n        b.iter_with_large_drop(|| black_box(&bytes).clone().into_pyobject(py));\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"bytes_new_small\", bytes_new_small);\n    c.bench_function(\"bytes_new_medium\", bytes_new_medium);\n    c.bench_function(\"bytes_new_large\", bytes_new_large);\n    c.bench_function(\n        \"byte_slice_into_pyobject_small\",\n        byte_slice_into_pyobject_small,\n    );\n    c.bench_function(\n        \"byte_slice_into_pyobject_medium\",\n        byte_slice_into_pyobject_medium,\n    );\n    c.bench_function(\n        \"byte_slice_into_pyobject_large\",\n        byte_slice_into_pyobject_large,\n    );\n    c.bench_function(\"vec_into_pyobject\", vec_into_pyobject);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_list.rs",
    "content": "use std::hint::black_box;\n\nuse codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::prelude::*;\nuse pyo3::types::{PyList, PySequence};\n\nfn iter_list(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        let list = PyList::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for x in &list {\n                let i: u64 = x.extract().unwrap();\n                sum += i;\n            }\n        });\n    });\n}\n\nfn list_new(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        b.iter_with_large_drop(|| PyList::new(py, 0..LEN));\n    });\n}\n\nfn list_get_item(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        let list = PyList::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for i in 0..LEN {\n                sum += list.get_item(i).unwrap().extract::<usize>().unwrap();\n            }\n        });\n    });\n}\n\nfn list_nth(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50;\n        let list = PyList::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for i in 0..LEN {\n                sum += list.iter().nth(i).unwrap().extract::<usize>().unwrap();\n            }\n        });\n    });\n}\n\nfn list_nth_back(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50;\n        let list = PyList::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for i in 0..LEN {\n                sum += list.iter().nth_back(i).unwrap().extract::<usize>().unwrap();\n            }\n        });\n    });\n}\n\n#[cfg(not(Py_LIMITED_API))]\nfn list_get_item_unchecked(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        let list = PyList::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for i in 0..LEN {\n                unsafe {\n                    sum += list.get_item_unchecked(i).extract::<usize>().unwrap();\n                }\n            }\n        });\n    });\n}\n\nfn sequence_from_list(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        let list = &PyList::new(py, 0..LEN).unwrap();\n        b.iter(|| black_box(list).cast::<PySequence>().unwrap());\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"iter_list\", iter_list);\n    c.bench_function(\"list_new\", list_new);\n    c.bench_function(\"list_nth\", list_nth);\n    c.bench_function(\"list_nth_back\", list_nth_back);\n    c.bench_function(\"list_get_item\", list_get_item);\n    #[cfg(not(Py_LIMITED_API))]\n    c.bench_function(\"list_get_item_unchecked\", list_get_item_unchecked);\n    c.bench_function(\"sequence_from_list\", sequence_from_list);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_py.rs",
    "content": "use codspeed_criterion_compat::{criterion_group, criterion_main, BatchSize, Bencher, Criterion};\n\nuse std::sync::{\n    atomic::{AtomicUsize, Ordering},\n    mpsc::channel,\n    Arc, Barrier,\n};\nuse std::thread::spawn;\nuse std::time::{Duration, Instant};\n\nuse pyo3::prelude::*;\n\nfn drop_many_objects(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        b.iter(|| {\n            for _ in 0..1000 {\n                drop(py.None());\n            }\n        });\n    });\n}\n\nfn drop_many_objects_without_gil(b: &mut Bencher<'_>) {\n    b.iter_batched(\n        || Python::attach(|py| (0..1000).map(|_| py.None()).collect::<Vec<Py<PyAny>>>()),\n        |objs| {\n            drop(objs);\n\n            Python::attach(|_py| ());\n        },\n        BatchSize::SmallInput,\n    );\n}\n\nfn drop_many_objects_multiple_threads(b: &mut Bencher<'_>) {\n    const THREADS: usize = 5;\n\n    let barrier = Arc::new(Barrier::new(1 + THREADS));\n\n    let done = Arc::new(AtomicUsize::new(0));\n\n    let sender = (0..THREADS)\n        .map(|_| {\n            let (sender, receiver) = channel();\n\n            let barrier = barrier.clone();\n\n            let done = done.clone();\n\n            spawn(move || {\n                for objs in receiver {\n                    barrier.wait();\n\n                    drop(objs);\n\n                    done.fetch_add(1, Ordering::AcqRel);\n                }\n            });\n\n            sender\n        })\n        .collect::<Vec<_>>();\n\n    b.iter_custom(|iters| {\n        let mut duration = Duration::ZERO;\n\n        let mut last_done = done.load(Ordering::Acquire);\n\n        for _ in 0..iters {\n            for sender in &sender {\n                let objs = Python::attach(|py| {\n                    (0..1000 / THREADS)\n                        .map(|_| py.None())\n                        .collect::<Vec<Py<PyAny>>>()\n                });\n\n                sender.send(objs).unwrap();\n            }\n\n            barrier.wait();\n\n            let start = Instant::now();\n\n            loop {\n                Python::attach(|_py| ());\n\n                let done = done.load(Ordering::Acquire);\n                if done - last_done == THREADS {\n                    last_done = done;\n                    break;\n                }\n            }\n\n            Python::attach(|_py| ());\n\n            duration += start.elapsed();\n        }\n\n        duration\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"drop_many_objects\", drop_many_objects);\n    c.bench_function(\n        \"drop_many_objects_without_gil\",\n        drop_many_objects_without_gil,\n    );\n    c.bench_function(\n        \"drop_many_objects_multiple_threads\",\n        drop_many_objects_multiple_threads,\n    );\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_pyclass.rs",
    "content": "use codspeed_criterion_compat::{criterion_group, criterion_main, BatchSize, Bencher, Criterion};\nuse pyo3::conversion::IntoPyObjectExt;\nuse pyo3::types::PyInt;\nuse pyo3::{impl_::pyclass::LazyTypeObject, prelude::*};\n\n/// This is a feature-rich class instance used to benchmark various parts of the pyclass lifecycle.\n#[pyclass]\nstruct MyClass {\n    #[pyo3(get, set)]\n    elements: Vec<i32>,\n}\n\n#[pymethods]\nimpl MyClass {\n    #[new]\n    fn new(elements: Vec<i32>) -> Self {\n        Self { elements }\n    }\n\n    fn __call__(&mut self, new_element: i32) -> usize {\n        self.elements.push(new_element);\n        self.elements.len()\n    }\n\n    /// A basic __str__ implementation.\n    fn __str__(&self) -> &'static str {\n        \"MyClass\"\n    }\n}\n\npub fn first_time_init(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        b.iter(|| {\n            // This is using an undocumented internal PyO3 API to measure pyclass performance; please\n            // don't use this in your own code!\n            let ty = LazyTypeObject::<MyClass>::new();\n            ty.get_or_try_init(py).unwrap();\n        });\n    });\n}\n\npub fn bench_pyclass(c: &mut Criterion) {\n    c.bench_function(\"bench_pyclass_create\", |b| {\n        Python::attach(|py| {\n            b.iter_batched(\n                || vec![1, 2, 3],\n                |elements| {\n                    MyClass::new(elements).into_py_any(py).unwrap();\n                },\n                BatchSize::SmallInput,\n            );\n        });\n    });\n    c.bench_function(\"bench_call\", |b| {\n        Python::attach(|py| {\n            b.iter_batched(\n                || {\n                    (\n                        MyClass::new(vec![1, 2, 3]).into_py_any(py).unwrap(),\n                        PyInt::new(py, 4),\n                    )\n                },\n                |(inst, arg)| {\n                    inst.call1(py, (arg,)).unwrap();\n                },\n                BatchSize::SmallInput,\n            );\n        });\n    });\n    c.bench_function(\"bench_str\", |b| {\n        Python::attach(|py| {\n            let inst = MyClass::new(vec![1, 2, 3]).into_py_any(py).unwrap();\n            let bound = inst.bind(py);\n            b.iter(|| bound.str());\n        });\n    });\n}\n\nfn bench_first_time_init(c: &mut Criterion) {\n    c.bench_function(\"first_time_init\", first_time_init);\n}\n\ncriterion_group!(benches, bench_first_time_init, bench_pyclass);\n\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_pystring_from_fmt.rs",
    "content": "use codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\nuse pyo3::{py_format, Python};\nuse std::hint::black_box;\n\nfn format_simple(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        b.iter(|| {\n            py_format!(py, \"Hello {}!\", \"world\").unwrap()\n        });\n    });\n}\n\nfn format_complex(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        b.iter(|| {\n            let value = (black_box(42), black_box(\"foo\"), [0; 0]);\n            py_format!(py, \"This is some complex value: {value:?}\").unwrap()\n        });\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"format_simple\", format_simple);\n    c.bench_function(\"format_complex\", format_complex);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_set.rs",
    "content": "use codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::types::PySet;\nuse pyo3::{prelude::*, IntoPyObjectExt};\nuse std::{\n    collections::{BTreeSet, HashSet},\n    hint::black_box,\n};\n\nfn set_new(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        // Create Python objects up-front, so that the benchmark doesn't need to include\n        // the cost of allocating LEN Python integers\n        let elements: Vec<Py<PyAny>> = (0..LEN).map(|i| i.into_py_any(py).unwrap()).collect();\n        b.iter_with_large_drop(|| PySet::new(py, &elements).unwrap());\n    });\n}\n\nfn iter_set(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        let set = PySet::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for x in &set {\n                let i: u64 = x.extract().unwrap();\n                sum += i;\n            }\n        });\n    });\n}\n\nfn extract_hashset(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        let any = PySet::new(py, 0..LEN).unwrap().into_any();\n        b.iter_with_large_drop(|| black_box(&any).extract::<HashSet<u64>>());\n    });\n}\n\nfn extract_btreeset(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        let any = PySet::new(py, 0..LEN).unwrap().into_any();\n        b.iter_with_large_drop(|| black_box(&any).extract::<BTreeSet<u64>>());\n    });\n}\n\nfn extract_hashbrown_set(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        let any = PySet::new(py, 0..LEN).unwrap().into_any();\n        b.iter_with_large_drop(|| black_box(&any).extract::<hashbrown::HashSet<u64>>());\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"set_new\", set_new);\n    c.bench_function(\"iter_set\", iter_set);\n    c.bench_function(\"extract_hashset\", extract_hashset);\n    c.bench_function(\"extract_btreeset\", extract_btreeset);\n    c.bench_function(\"extract_hashbrown_set\", extract_hashbrown_set);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/benches/bench_tuple.rs",
    "content": "use std::hint::black_box;\n\nuse codspeed_criterion_compat::{criterion_group, criterion_main, Bencher, Criterion};\n\nuse pyo3::prelude::*;\nuse pyo3::types::{PyList, PySequence, PyTuple};\n\nfn iter_tuple(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 100_000;\n        let tuple = PyTuple::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for x in tuple.iter_borrowed() {\n                let i: u64 = x.extract().unwrap();\n                sum += i;\n            }\n        });\n    });\n}\n\nfn tuple_new(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        b.iter_with_large_drop(|| PyTuple::new(py, 0..LEN).unwrap());\n    });\n}\n\nfn tuple_get_item(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        let tuple = PyTuple::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for i in 0..LEN {\n                sum += tuple.get_item(i).unwrap().extract::<usize>().unwrap();\n            }\n        });\n    });\n}\n\n#[cfg(not(any(Py_LIMITED_API, PyPy)))]\nfn tuple_get_item_unchecked(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        let tuple = PyTuple::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for i in 0..LEN {\n                unsafe {\n                    sum += tuple.get_item_unchecked(i).extract::<usize>().unwrap();\n                }\n            }\n        });\n    });\n}\n\nfn tuple_get_borrowed_item(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        let tuple = PyTuple::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for i in 0..LEN {\n                sum += tuple\n                    .get_borrowed_item(i)\n                    .unwrap()\n                    .extract::<usize>()\n                    .unwrap();\n            }\n        });\n    });\n}\n\n#[cfg(not(any(Py_LIMITED_API, PyPy)))]\nfn tuple_get_borrowed_item_unchecked(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        let tuple = PyTuple::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for i in 0..LEN {\n                unsafe {\n                    sum += tuple\n                        .get_borrowed_item_unchecked(i)\n                        .extract::<usize>()\n                        .unwrap();\n                }\n            }\n        });\n    });\n}\n\nfn sequence_from_tuple(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        let tuple = PyTuple::new(py, 0..LEN).unwrap().into_any();\n        b.iter(|| black_box(&tuple).cast::<PySequence>().unwrap());\n    });\n}\n\nfn tuple_new_list(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        let tuple = PyTuple::new(py, 0..LEN).unwrap();\n        b.iter_with_large_drop(|| PyList::new(py, tuple.iter_borrowed()));\n    });\n}\n\nfn tuple_to_list(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50_000;\n        let tuple = PyTuple::new(py, 0..LEN).unwrap();\n        b.iter_with_large_drop(|| tuple.to_list());\n    });\n}\n\nfn tuple_into_pyobject(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        b.iter(|| {\n            (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)\n                .into_pyobject(py)\n                .unwrap()\n        });\n    });\n}\n\nfn tuple_nth(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50;\n        let list = PyTuple::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for i in 0..LEN {\n                sum += list.iter().nth(i).unwrap().extract::<usize>().unwrap();\n            }\n        });\n    });\n}\n\nfn tuple_nth_back(b: &mut Bencher<'_>) {\n    Python::attach(|py| {\n        const LEN: usize = 50;\n        let list = PyTuple::new(py, 0..LEN).unwrap();\n        let mut sum = 0;\n        b.iter(|| {\n            for i in 0..LEN {\n                sum += list.iter().nth_back(i).unwrap().extract::<usize>().unwrap();\n            }\n        });\n    });\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    c.bench_function(\"iter_tuple\", iter_tuple);\n    c.bench_function(\"tuple_new\", tuple_new);\n    c.bench_function(\"tuple_get_item\", tuple_get_item);\n    c.bench_function(\"tuple_nth\", tuple_nth);\n    c.bench_function(\"tuple_nth_back\", tuple_nth_back);\n    #[cfg(not(any(Py_LIMITED_API, PyPy)))]\n    c.bench_function(\"tuple_get_item_unchecked\", tuple_get_item_unchecked);\n    c.bench_function(\"tuple_get_borrowed_item\", tuple_get_borrowed_item);\n    #[cfg(not(any(Py_LIMITED_API, PyPy)))]\n    c.bench_function(\n        \"tuple_get_borrowed_item_unchecked\",\n        tuple_get_borrowed_item_unchecked,\n    );\n    c.bench_function(\"sequence_from_tuple\", sequence_from_tuple);\n    c.bench_function(\"tuple_new_list\", tuple_new_list);\n    c.bench_function(\"tuple_to_list\", tuple_to_list);\n    c.bench_function(\"tuple_into_pyobject\", tuple_into_pyobject);\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "pyo3-benches/build.rs",
    "content": "fn main() {\n    pyo3_build_config::use_pyo3_cfgs();\n    pyo3_build_config::add_libpython_rpath_link_args();\n}\n"
  },
  {
    "path": "pyo3-build-config/Cargo.toml",
    "content": "[package]\nname = \"pyo3-build-config\"\nversion = \"0.28.2\"\ndescription = \"Build configuration for the PyO3 ecosystem\"\nauthors = [\"PyO3 Project and Contributors <https://github.com/PyO3>\"]\nkeywords = [\"pyo3\", \"python\", \"cpython\", \"ffi\"]\nhomepage = \"https://github.com/pyo3/pyo3\"\nrepository = \"https://github.com/pyo3/pyo3\"\ncategories = [\"api-bindings\", \"development-tools::ffi\"]\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version.workspace = true\n\n[dependencies]\ntarget-lexicon = \"0.13.3\"\n\n[build-dependencies]\ntarget-lexicon = \"0.13.3\"\n\n[features]\ndefault = []\n\n# Attempt to resolve a Python interpreter config for building in the build\n# script. If this feature isn't enabled, the build script no-ops.\nresolve-config = []\n\n# deprecated\nextension-module = []\n\n# deprecated: no longer needed, raw-dylib is used instead\ngenerate-import-lib = []\n\n# These features are enabled by pyo3 when building Stable ABI extension modules.\nabi3 = []\nabi3-py37 = [\"abi3-py38\"]\nabi3-py38 = [\"abi3-py39\"]\nabi3-py39 = [\"abi3-py310\"]\nabi3-py310 = [\"abi3-py311\"]\nabi3-py311 = [\"abi3-py312\"]\nabi3-py312 = [\"abi3-py313\"]\nabi3-py313 = [\"abi3-py314\"]\nabi3-py314 = [\"abi3\"]\n\n[package.metadata.docs.rs]\nfeatures = [\"resolve-config\"]\n"
  },
  {
    "path": "pyo3-build-config/build.rs",
    "content": "// Import some modules from this crate inline to generate the build config.\n// Allow dead code because not all code in the modules is used in this build script.\n\n#[path = \"src/impl_.rs\"]\n#[allow(dead_code, reason = \"not all code is used in build.rs\")]\nmod impl_;\n\n#[path = \"src/errors.rs\"]\n#[allow(dead_code, reason = \"not all code is used in build.rs\")]\nmod errors;\n\nuse std::{env, path::Path};\n\nuse errors::{Context, Result};\nuse impl_::{make_interpreter_config, InterpreterConfig};\n\nfn configure(interpreter_config: Option<InterpreterConfig>, name: &str) -> Result<bool> {\n    let target = Path::new(&env::var_os(\"OUT_DIR\").unwrap()).join(name);\n    if let Some(config) = interpreter_config {\n        config\n            .to_writer(&mut std::fs::File::create(&target).with_context(|| {\n                format!(\"failed to write config file at {}\", target.display())\n            })?)?;\n        Ok(true)\n    } else {\n        std::fs::File::create(&target)\n            .with_context(|| format!(\"failed to create new file at {}\", target.display()))?;\n        Ok(false)\n    }\n}\n\nfn generate_build_configs() -> Result<()> {\n    // If PYO3_CONFIG_FILE is set, copy it into the crate.\n    let configured = configure(\n        InterpreterConfig::from_pyo3_config_file_env().transpose()?,\n        \"pyo3-build-config-file.txt\",\n    )?;\n\n    if configured {\n        // Don't bother trying to find an interpreter on the host system\n        // if the user-provided config file is present.\n        configure(None, \"pyo3-build-config.txt\")?;\n    } else {\n        configure(Some(make_interpreter_config()?), \"pyo3-build-config.txt\")?;\n    }\n    Ok(())\n}\n\nfn main() {\n    if std::env::var(\"CARGO_FEATURE_RESOLVE_CONFIG\").is_ok() {\n        if let Err(e) = generate_build_configs() {\n            eprintln!(\"error: {}\", e.report());\n            std::process::exit(1)\n        }\n    } else {\n        eprintln!(\"resolve-config feature not enabled; build script in no-op mode\");\n    }\n}\n"
  },
  {
    "path": "pyo3-build-config/src/errors.rs",
    "content": "/// A simple macro for returning an error. Resembles anyhow::bail.\n#[macro_export]\n#[doc(hidden)]\nmacro_rules! bail {\n    ($($args: tt)+) => { return Err(format!($($args)+).into()) };\n}\n\n/// A simple macro for checking a condition. Resembles anyhow::ensure.\n#[macro_export]\n#[doc(hidden)]\nmacro_rules! ensure {\n    ($condition:expr, $($args: tt)+) => { if !($condition) { bail!($($args)+) } };\n}\n\n/// Show warning.\n#[macro_export]\n#[doc(hidden)]\nmacro_rules! warn {\n    ($($args: tt)+) => {\n        println!(\"{}\", $crate::format_warn!($($args)+))\n    };\n}\n\n/// Format warning into string.\n#[macro_export]\n#[doc(hidden)]\nmacro_rules! format_warn {\n    ($($args: tt)+) => {\n        format!(\"cargo:warning={}\", format_args!($($args)+))\n    };\n}\n\n/// A simple error implementation which allows chaining of errors, inspired somewhat by anyhow.\n#[derive(Debug)]\npub struct Error {\n    value: String,\n    source: Option<Box<dyn std::error::Error>>,\n}\n\n/// Error report inspired by\n/// <https://blog.rust-lang.org/inside-rust/2021/07/01/What-the-error-handling-project-group-is-working-towards.html#2-error-reporter>\npub struct ErrorReport<'a>(&'a Error);\n\nimpl Error {\n    pub fn report(&self) -> ErrorReport<'_> {\n        ErrorReport(self)\n    }\n}\n\nimpl std::fmt::Display for Error {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}\", self.value)\n    }\n}\n\nimpl std::error::Error for Error {\n    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {\n        self.source.as_deref()\n    }\n}\n\nimpl std::fmt::Display for ErrorReport<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        use std::error::Error;\n        self.0.fmt(f)?;\n        let mut source = self.0.source();\n        if source.is_some() {\n            writeln!(f, \"\\ncaused by:\")?;\n            let mut index = 0;\n            while let Some(some_source) = source {\n                writeln!(f, \"  - {index}: {some_source}\")?;\n                source = some_source.source();\n                index += 1;\n            }\n        }\n        Ok(())\n    }\n}\n\nimpl From<String> for Error {\n    fn from(value: String) -> Self {\n        Self {\n            value,\n            source: None,\n        }\n    }\n}\n\nimpl From<&'_ str> for Error {\n    fn from(value: &str) -> Self {\n        value.to_string().into()\n    }\n}\n\nimpl From<std::convert::Infallible> for Error {\n    fn from(value: std::convert::Infallible) -> Self {\n        match value {}\n    }\n}\n\npub type Result<T, E = Error> = std::result::Result<T, E>;\n\npub trait Context<T> {\n    fn context(self, message: impl Into<String>) -> Result<T>;\n    fn with_context(self, message: impl FnOnce() -> String) -> Result<T>;\n}\n\nimpl<T, E> Context<T> for Result<T, E>\nwhere\n    E: std::error::Error + 'static,\n{\n    fn context(self, message: impl Into<String>) -> Result<T> {\n        self.map_err(|error| Error {\n            value: message.into(),\n            source: Some(Box::new(error)),\n        })\n    }\n\n    fn with_context(self, message: impl FnOnce() -> String) -> Result<T> {\n        self.map_err(|error| Error {\n            value: message(),\n            source: Some(Box::new(error)),\n        })\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn error_report() {\n        let error: Result<()> = Err(Error::from(\"there was an internal error\"))\n            .with_context(|| format!(\"failed to do {}\", \"something difficult\"))\n            .context(\"things went wrong\");\n\n        assert_eq!(\n            error\n                .unwrap_err()\n                .report()\n                .to_string()\n                .split('\\n')\n                .collect::<Vec<&str>>(),\n            vec![\n                \"things went wrong\",\n                \"caused by:\",\n                \"  - 0: failed to do something difficult\",\n                \"  - 1: there was an internal error\",\n                \"\"\n            ]\n        );\n    }\n}\n"
  },
  {
    "path": "pyo3-build-config/src/impl_.rs",
    "content": "//! Main implementation module included in both the `pyo3-build-config` library crate\n//! and its build script.\n\n#[cfg(test)]\nuse std::cell::RefCell;\nuse std::{\n    collections::{HashMap, HashSet},\n    env,\n    ffi::{OsStr, OsString},\n    fmt::Display,\n    fs::{self, DirEntry},\n    io::{BufRead, BufReader, Read, Write},\n    path::{Path, PathBuf},\n    process::{Command, Stdio},\n    str::{self, FromStr},\n};\n\npub use target_lexicon::Triple;\n\nuse target_lexicon::{Architecture, Environment, OperatingSystem, Vendor};\n\nuse crate::{\n    bail, ensure,\n    errors::{Context, Error, Result},\n    warn,\n};\n\n/// Minimum Python version PyO3 supports.\npub(crate) const MINIMUM_SUPPORTED_VERSION: PythonVersion = PythonVersion { major: 3, minor: 7 };\n\npub(crate) const MINIMUM_SUPPORTED_VERSION_PYPY: PythonVersion = PythonVersion {\n    major: 3,\n    minor: 11,\n};\npub(crate) const MAXIMUM_SUPPORTED_VERSION_PYPY: PythonVersion = PythonVersion {\n    major: 3,\n    minor: 11,\n};\n\n/// GraalPy may implement the same CPython version over multiple releases.\nconst MINIMUM_SUPPORTED_VERSION_GRAALPY: PythonVersion = PythonVersion {\n    major: 25,\n    minor: 0,\n};\n\n/// Maximum Python version that can be used as minimum required Python version with abi3.\npub(crate) const ABI3_MAX_MINOR: u8 = 14;\n\n#[cfg(test)]\nthread_local! {\n    static READ_ENV_VARS: RefCell<Vec<String>> = const { RefCell::new(Vec::new()) };\n}\n\n/// Gets an environment variable owned by cargo.\n///\n/// Environment variables set by cargo are expected to be valid UTF8.\npub fn cargo_env_var(var: &str) -> Option<String> {\n    env::var_os(var).map(|os_string| os_string.to_str().unwrap().into())\n}\n\n/// Gets an external environment variable, and registers the build script to rerun if\n/// the variable changes.\npub fn env_var(var: &str) -> Option<OsString> {\n    if cfg!(feature = \"resolve-config\") {\n        println!(\"cargo:rerun-if-env-changed={var}\");\n    }\n    #[cfg(test)]\n    {\n        READ_ENV_VARS.with(|env_vars| {\n            env_vars.borrow_mut().push(var.to_owned());\n        });\n    }\n    env::var_os(var)\n}\n\n/// Gets the compilation target triple from environment variables set by Cargo.\n///\n/// Must be called from a crate build script.\npub fn target_triple_from_env() -> Triple {\n    env::var(\"TARGET\")\n        .expect(\"target_triple_from_env() must be called from a build script\")\n        .parse()\n        .expect(\"Unrecognized TARGET environment variable value\")\n}\n\n/// Configuration needed by PyO3 to build for the correct Python implementation.\n///\n/// Usually this is queried directly from the Python interpreter, or overridden using the\n/// `PYO3_CONFIG_FILE` environment variable.\n///\n/// When the `PYO3_NO_PYTHON` variable is set, or during cross compile situations, then alternative\n/// strategies are used to populate this type.\n#[cfg_attr(test, derive(Debug, PartialEq, Eq))]\npub struct InterpreterConfig {\n    /// The Python implementation flavor.\n    ///\n    /// Serialized to `implementation`.\n    pub implementation: PythonImplementation,\n\n    /// Python `X.Y` version. e.g. `3.9`.\n    ///\n    /// Serialized to `version`.\n    pub version: PythonVersion,\n\n    /// Whether link library is shared.\n    ///\n    /// Serialized to `shared`.\n    pub shared: bool,\n\n    /// Whether linking against the stable/limited Python 3 API.\n    ///\n    /// Serialized to `abi3`.\n    pub abi3: bool,\n\n    /// The name of the link library defining Python.\n    ///\n    /// This effectively controls the `cargo:rustc-link-lib=<name>` value to\n    /// control how libpython is linked. Values should not contain the `lib`\n    /// prefix.\n    ///\n    /// Serialized to `lib_name`.\n    pub lib_name: Option<String>,\n\n    /// The directory containing the Python library to link against.\n    ///\n    /// The effectively controls the `cargo:rustc-link-search=native=<path>` value\n    /// to add an additional library search path for the linker.\n    ///\n    /// Serialized to `lib_dir`.\n    pub lib_dir: Option<String>,\n\n    /// Path of host `python` executable.\n    ///\n    /// This is a valid executable capable of running on the host/building machine.\n    /// For configurations derived by invoking a Python interpreter, it was the\n    /// executable invoked.\n    ///\n    /// Serialized to `executable`.\n    pub executable: Option<String>,\n\n    /// Width in bits of pointers on the target machine.\n    ///\n    /// Serialized to `pointer_width`.\n    pub pointer_width: Option<u32>,\n\n    /// Additional relevant Python build flags / configuration settings.\n    ///\n    /// Serialized to `build_flags`.\n    pub build_flags: BuildFlags,\n\n    /// Whether to suppress emitting of `cargo:rustc-link-*` lines from the build script.\n    ///\n    /// Typically, `pyo3`'s build script will emit `cargo:rustc-link-lib=` and\n    /// `cargo:rustc-link-search=` lines derived from other fields in this struct. In\n    /// advanced building configurations, the default logic to derive these lines may not\n    /// be sufficient. This field can be set to `Some(true)` to suppress the emission\n    /// of these lines.\n    ///\n    /// If suppression is enabled, `extra_build_script_lines` should contain equivalent\n    /// functionality or else a build failure is likely.\n    pub suppress_build_script_link_lines: bool,\n\n    /// Additional lines to `println!()` from Cargo build scripts.\n    ///\n    /// This field can be populated to enable the `pyo3` crate to emit additional lines from its\n    /// its Cargo build script.\n    ///\n    /// This crate doesn't populate this field itself. Rather, it is intended to be used with\n    /// externally provided config files to give them significant control over how the crate\n    /// is build/configured.\n    ///\n    /// Serialized to multiple `extra_build_script_line` values.\n    pub extra_build_script_lines: Vec<String>,\n    /// macOS Python3.framework requires special rpath handling\n    pub python_framework_prefix: Option<String>,\n}\n\nimpl InterpreterConfig {\n    #[doc(hidden)]\n    pub fn build_script_outputs(&self) -> Vec<String> {\n        // This should have been checked during pyo3-build-config build time.\n        assert!(self.version >= MINIMUM_SUPPORTED_VERSION);\n\n        let mut out = vec![];\n\n        for i in MINIMUM_SUPPORTED_VERSION.minor..=self.version.minor {\n            out.push(format!(\"cargo:rustc-cfg=Py_3_{i}\"));\n        }\n\n        match self.implementation {\n            PythonImplementation::CPython => {}\n            PythonImplementation::PyPy => out.push(\"cargo:rustc-cfg=PyPy\".to_owned()),\n            PythonImplementation::GraalPy => out.push(\"cargo:rustc-cfg=GraalPy\".to_owned()),\n        }\n\n        // If Py_GIL_DISABLED is set, do not build with limited API support\n        if self.abi3 && !self.is_free_threaded() {\n            out.push(\"cargo:rustc-cfg=Py_LIMITED_API\".to_owned());\n        }\n\n        for flag in &self.build_flags.0 {\n            match flag {\n                BuildFlag::Py_GIL_DISABLED => {\n                    out.push(\"cargo:rustc-cfg=Py_GIL_DISABLED\".to_owned())\n                }\n                flag => out.push(format!(\"cargo:rustc-cfg=py_sys_config=\\\"{flag}\\\"\")),\n            }\n        }\n\n        out\n    }\n\n    #[doc(hidden)]\n    pub fn from_interpreter(interpreter: impl AsRef<Path>) -> Result<Self> {\n        const SCRIPT: &str = r#\"\n# Allow the script to run on Python 2, so that nicer error can be printed later.\nfrom __future__ import print_function\n\nimport os.path\nimport platform\nimport struct\nimport sys\nfrom sysconfig import get_config_var, get_platform\n\nPYPY = platform.python_implementation() == \"PyPy\"\nGRAALPY = platform.python_implementation() == \"GraalVM\"\n\nif GRAALPY:\n    graalpy_ver = map(int, __graalpython__.get_graalvm_version().split('.'));\n    print(\"graalpy_major\", next(graalpy_ver))\n    print(\"graalpy_minor\", next(graalpy_ver))\n\n# sys.base_prefix is missing on Python versions older than 3.3; this allows the script to continue\n# so that the version mismatch can be reported in a nicer way later.\nbase_prefix = getattr(sys, \"base_prefix\", None)\n\nif base_prefix:\n    # Anaconda based python distributions have a static python executable, but include\n    # the shared library. Use the shared library for embedding to avoid rust trying to\n    # LTO the static library (and failing with newer gcc's, because it is old).\n    ANACONDA = os.path.exists(os.path.join(base_prefix, \"conda-meta\"))\nelse:\n    ANACONDA = False\n\ndef print_if_set(varname, value):\n    if value is not None:\n        print(varname, value)\n\n# Windows always uses shared linking\nWINDOWS = platform.system() == \"Windows\"\n\n# macOS framework packages use shared linking\nFRAMEWORK = bool(get_config_var(\"PYTHONFRAMEWORK\"))\nFRAMEWORK_PREFIX = get_config_var(\"PYTHONFRAMEWORKPREFIX\")\n\n# unix-style shared library enabled\nSHARED = bool(get_config_var(\"Py_ENABLE_SHARED\"))\n\nprint(\"implementation\", platform.python_implementation())\nprint(\"version_major\", sys.version_info[0])\nprint(\"version_minor\", sys.version_info[1])\nprint(\"shared\", PYPY or GRAALPY or ANACONDA or WINDOWS or FRAMEWORK or SHARED)\nprint(\"python_framework_prefix\", FRAMEWORK_PREFIX)\nprint_if_set(\"ld_version\", get_config_var(\"LDVERSION\"))\nprint_if_set(\"libdir\", get_config_var(\"LIBDIR\"))\nprint_if_set(\"base_prefix\", base_prefix)\nprint(\"executable\", sys.executable)\nprint(\"calcsize_pointer\", struct.calcsize(\"P\"))\nprint(\"mingw\", get_platform().startswith(\"mingw\"))\nprint(\"cygwin\", get_platform().startswith(\"cygwin\"))\nprint(\"ext_suffix\", get_config_var(\"EXT_SUFFIX\"))\nprint(\"gil_disabled\", get_config_var(\"Py_GIL_DISABLED\"))\n\"#;\n        let output = run_python_script(interpreter.as_ref(), SCRIPT)?;\n        let map: HashMap<String, String> = parse_script_output(&output);\n\n        ensure!(\n            !map.is_empty(),\n            \"broken Python interpreter: {}\",\n            interpreter.as_ref().display()\n        );\n\n        if let Some(value) = map.get(\"graalpy_major\") {\n            let graalpy_version = PythonVersion {\n                major: value\n                    .parse()\n                    .context(\"failed to parse GraalPy major version\")?,\n                minor: map[\"graalpy_minor\"]\n                    .parse()\n                    .context(\"failed to parse GraalPy minor version\")?,\n            };\n            ensure!(\n                graalpy_version >= MINIMUM_SUPPORTED_VERSION_GRAALPY,\n                \"At least GraalPy version {} needed, got {}\",\n                MINIMUM_SUPPORTED_VERSION_GRAALPY,\n                graalpy_version\n            );\n        };\n\n        let shared = map[\"shared\"].as_str() == \"True\";\n        let python_framework_prefix = map.get(\"python_framework_prefix\").cloned();\n\n        let version = PythonVersion {\n            major: map[\"version_major\"]\n                .parse()\n                .context(\"failed to parse major version\")?,\n            minor: map[\"version_minor\"]\n                .parse()\n                .context(\"failed to parse minor version\")?,\n        };\n\n        let abi3 = is_abi3();\n\n        let implementation = map[\"implementation\"].parse()?;\n\n        let gil_disabled = match map[\"gil_disabled\"].as_str() {\n            \"1\" => true,\n            \"0\" => false,\n            \"None\" => false,\n            _ => panic!(\"Unknown Py_GIL_DISABLED value\"),\n        };\n\n        let cygwin = map[\"cygwin\"].as_str() == \"True\";\n\n        let lib_name = if cfg!(windows) {\n            default_lib_name_windows(\n                version,\n                implementation,\n                abi3,\n                map[\"mingw\"].as_str() == \"True\",\n                // This is the best heuristic currently available to detect debug build\n                // on Windows from sysconfig - e.g. ext_suffix may be\n                // `_d.cp312-win_amd64.pyd` for 3.12 debug build\n                map[\"ext_suffix\"].starts_with(\"_d.\"),\n                gil_disabled,\n            )?\n        } else {\n            default_lib_name_unix(\n                version,\n                implementation,\n                abi3,\n                cygwin,\n                map.get(\"ld_version\").map(String::as_str),\n                gil_disabled,\n            )?\n        };\n\n        let lib_dir = if cfg!(windows) {\n            map.get(\"base_prefix\")\n                .map(|base_prefix| format!(\"{base_prefix}\\\\libs\"))\n        } else {\n            map.get(\"libdir\").cloned()\n        };\n\n        // The reason we don't use platform.architecture() here is that it's not\n        // reliable on macOS. See https://stackoverflow.com/a/1405971/823869.\n        // Similarly, sys.maxsize is not reliable on Windows. See\n        // https://stackoverflow.com/questions/1405913/how-do-i-determine-if-my-python-shell-is-executing-in-32bit-or-64bit-mode-on-os/1405971#comment6209952_1405971\n        // and https://stackoverflow.com/a/3411134/823869.\n        let calcsize_pointer: u32 = map[\"calcsize_pointer\"]\n            .parse()\n            .context(\"failed to parse calcsize_pointer\")?;\n\n        Ok(InterpreterConfig {\n            version,\n            implementation,\n            shared,\n            abi3,\n            lib_name: Some(lib_name),\n            lib_dir,\n            executable: map.get(\"executable\").cloned(),\n            pointer_width: Some(calcsize_pointer * 8),\n            build_flags: BuildFlags::from_interpreter(interpreter)?,\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix,\n        })\n    }\n\n    /// Generate from parsed sysconfigdata file\n    ///\n    /// Use [`parse_sysconfigdata`] to generate a hash map of configuration values which may be\n    /// used to build an [`InterpreterConfig`].\n    pub fn from_sysconfigdata(sysconfigdata: &Sysconfigdata) -> Result<Self> {\n        macro_rules! get_key {\n            ($sysconfigdata:expr, $key:literal) => {\n                $sysconfigdata\n                    .get_value($key)\n                    .ok_or(concat!($key, \" not found in sysconfigdata file\"))\n            };\n        }\n\n        macro_rules! parse_key {\n            ($sysconfigdata:expr, $key:literal) => {\n                get_key!($sysconfigdata, $key)?\n                    .parse()\n                    .context(concat!(\"could not parse value of \", $key))\n            };\n        }\n\n        let soabi = get_key!(sysconfigdata, \"SOABI\")?;\n        let implementation = PythonImplementation::from_soabi(soabi)?;\n        let version = parse_key!(sysconfigdata, \"VERSION\")?;\n        let shared = match sysconfigdata.get_value(\"Py_ENABLE_SHARED\") {\n            Some(\"1\") | Some(\"true\") | Some(\"True\") => true,\n            Some(\"0\") | Some(\"false\") | Some(\"False\") => false,\n            _ => bail!(\"expected a bool (1/true/True or 0/false/False) for Py_ENABLE_SHARED\"),\n        };\n        // macOS framework packages use shared linking (PYTHONFRAMEWORK is the framework name, hence the empty check)\n        let framework = match sysconfigdata.get_value(\"PYTHONFRAMEWORK\") {\n            Some(s) => !s.is_empty(),\n            _ => false,\n        };\n        let python_framework_prefix = sysconfigdata\n            .get_value(\"PYTHONFRAMEWORKPREFIX\")\n            .map(str::to_string);\n        let lib_dir = get_key!(sysconfigdata, \"LIBDIR\").ok().map(str::to_string);\n        let gil_disabled = match sysconfigdata.get_value(\"Py_GIL_DISABLED\") {\n            Some(value) => value == \"1\",\n            None => false,\n        };\n        let cygwin = soabi.ends_with(\"cygwin\");\n        let abi3 = is_abi3();\n        let lib_name = Some(default_lib_name_unix(\n            version,\n            implementation,\n            abi3,\n            cygwin,\n            sysconfigdata.get_value(\"LDVERSION\"),\n            gil_disabled,\n        )?);\n        let pointer_width = parse_key!(sysconfigdata, \"SIZEOF_VOID_P\")\n            .map(|bytes_width: u32| bytes_width * 8)\n            .ok();\n        let build_flags = BuildFlags::from_sysconfigdata(sysconfigdata);\n\n        Ok(InterpreterConfig {\n            implementation,\n            version,\n            shared: shared || framework,\n            abi3,\n            lib_dir,\n            lib_name,\n            executable: None,\n            pointer_width,\n            build_flags,\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix,\n        })\n    }\n\n    /// Import an externally-provided config file.\n    ///\n    /// The `abi3` features, if set, may apply an `abi3` constraint to the Python version.\n    #[allow(dead_code)] // only used in build.rs\n    pub(super) fn from_pyo3_config_file_env() -> Option<Result<Self>> {\n        env_var(\"PYO3_CONFIG_FILE\").map(|path| {\n            let path = Path::new(&path);\n            println!(\"cargo:rerun-if-changed={}\", path.display());\n            // Absolute path is necessary because this build script is run with a cwd different to the\n            // original `cargo build` instruction.\n            ensure!(\n                path.is_absolute(),\n                \"PYO3_CONFIG_FILE must be an absolute path\"\n            );\n\n            let mut config = InterpreterConfig::from_path(path)\n                .context(\"failed to parse contents of PYO3_CONFIG_FILE\")?;\n            // If the abi3 feature is enabled, the minimum Python version is constrained by the abi3\n            // feature.\n            //\n            // TODO: abi3 is a property of the build mode, not the interpreter. Should this be\n            // removed from `InterpreterConfig`?\n            config.abi3 |= is_abi3();\n            config.fixup_for_abi3_version(get_abi3_version())?;\n\n            Ok(config)\n        })\n    }\n\n    #[doc(hidden)]\n    pub fn from_path(path: impl AsRef<Path>) -> Result<Self> {\n        let path = path.as_ref();\n        let config_file = std::fs::File::open(path)\n            .with_context(|| format!(\"failed to open PyO3 config file at {}\", path.display()))?;\n        let reader = std::io::BufReader::new(config_file);\n        InterpreterConfig::from_reader(reader)\n    }\n\n    #[doc(hidden)]\n    pub fn from_cargo_dep_env() -> Option<Result<Self>> {\n        cargo_env_var(\"DEP_PYTHON_PYO3_CONFIG\")\n            .map(|buf| InterpreterConfig::from_reader(&*unescape(&buf)))\n    }\n\n    #[doc(hidden)]\n    pub fn from_reader(reader: impl Read) -> Result<Self> {\n        let reader = BufReader::new(reader);\n        let lines = reader.lines();\n\n        macro_rules! parse_value {\n            ($variable:ident, $value:ident) => {\n                $variable = Some($value.trim().parse().context(format!(\n                    concat!(\n                        \"failed to parse \",\n                        stringify!($variable),\n                        \" from config value '{}'\"\n                    ),\n                    $value\n                ))?)\n            };\n        }\n\n        let mut implementation = None;\n        let mut version = None;\n        let mut shared = None;\n        let mut abi3 = None;\n        let mut lib_name = None;\n        let mut lib_dir = None;\n        let mut executable = None;\n        let mut pointer_width = None;\n        let mut build_flags: Option<BuildFlags> = None;\n        let mut suppress_build_script_link_lines = None;\n        let mut extra_build_script_lines = vec![];\n        let mut python_framework_prefix = None;\n\n        for (i, line) in lines.enumerate() {\n            let line = line.context(\"failed to read line from config\")?;\n            let mut split = line.splitn(2, '=');\n            let (key, value) = (\n                split\n                    .next()\n                    .expect(\"first splitn value should always be present\"),\n                split\n                    .next()\n                    .ok_or_else(|| format!(\"expected key=value pair on line {}\", i + 1))?,\n            );\n            match key {\n                \"implementation\" => parse_value!(implementation, value),\n                \"version\" => parse_value!(version, value),\n                \"shared\" => parse_value!(shared, value),\n                \"abi3\" => parse_value!(abi3, value),\n                \"lib_name\" => parse_value!(lib_name, value),\n                \"lib_dir\" => parse_value!(lib_dir, value),\n                \"executable\" => parse_value!(executable, value),\n                \"pointer_width\" => parse_value!(pointer_width, value),\n                \"build_flags\" => parse_value!(build_flags, value),\n                \"suppress_build_script_link_lines\" => {\n                    parse_value!(suppress_build_script_link_lines, value)\n                }\n                \"extra_build_script_line\" => {\n                    extra_build_script_lines.push(value.to_string());\n                }\n                \"python_framework_prefix\" => parse_value!(python_framework_prefix, value),\n                unknown => warn!(\"unknown config key `{}`\", unknown),\n            }\n        }\n\n        let version = version.ok_or(\"missing value for version\")?;\n        let implementation = implementation.unwrap_or(PythonImplementation::CPython);\n        let abi3 = abi3.unwrap_or(false);\n        let build_flags = build_flags.unwrap_or_default();\n\n        Ok(InterpreterConfig {\n            implementation,\n            version,\n            shared: shared.unwrap_or(true),\n            abi3,\n            lib_name,\n            lib_dir,\n            executable,\n            pointer_width,\n            build_flags,\n            suppress_build_script_link_lines: suppress_build_script_link_lines.unwrap_or(false),\n            extra_build_script_lines,\n            python_framework_prefix,\n        })\n    }\n\n    /// Helper function to apply a default lib_name if none is set in `PYO3_CONFIG_FILE`.\n    ///\n    /// This requires knowledge of the final target, so cannot be done when the config file is\n    /// inlined into `pyo3-build-config` at build time and instead needs to be done when\n    /// resolving the build config for linking.\n    #[cfg(any(test, feature = \"resolve-config\"))]\n    pub(crate) fn apply_default_lib_name_to_config_file(&mut self, target: &Triple) {\n        if self.lib_name.is_none() {\n            self.lib_name = Some(default_lib_name_for_target(\n                self.version,\n                self.implementation,\n                self.abi3,\n                self.is_free_threaded(),\n                target,\n            ));\n        }\n    }\n\n    #[doc(hidden)]\n    /// Serialize the `InterpreterConfig` and print it to the environment for Cargo to pass along\n    /// to dependent packages during build time.\n    ///\n    /// NB: writing to the cargo environment requires the\n    /// [`links`](https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key)\n    /// manifest key to be set. In this case that means this is called by the `pyo3-ffi` crate and\n    /// available for dependent package build scripts in `DEP_PYTHON_PYO3_CONFIG`. See\n    /// documentation for the\n    /// [`DEP_<name>_<key>`](https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts)\n    /// environment variable.\n    pub fn to_cargo_dep_env(&self) -> Result<()> {\n        let mut buf = Vec::new();\n        self.to_writer(&mut buf)?;\n        // escape newlines in env var\n        println!(\"cargo:PYO3_CONFIG={}\", escape(&buf));\n        Ok(())\n    }\n\n    #[doc(hidden)]\n    pub fn to_writer(&self, mut writer: impl Write) -> Result<()> {\n        macro_rules! write_line {\n            ($value:ident) => {\n                writeln!(writer, \"{}={}\", stringify!($value), self.$value).context(concat!(\n                    \"failed to write \",\n                    stringify!($value),\n                    \" to config\"\n                ))\n            };\n        }\n\n        macro_rules! write_option_line {\n            ($value:ident) => {\n                if let Some(value) = &self.$value {\n                    writeln!(writer, \"{}={}\", stringify!($value), value).context(concat!(\n                        \"failed to write \",\n                        stringify!($value),\n                        \" to config\"\n                    ))\n                } else {\n                    Ok(())\n                }\n            };\n        }\n\n        write_line!(implementation)?;\n        write_line!(version)?;\n        write_line!(shared)?;\n        write_line!(abi3)?;\n        write_option_line!(lib_name)?;\n        write_option_line!(lib_dir)?;\n        write_option_line!(executable)?;\n        write_option_line!(pointer_width)?;\n        write_line!(build_flags)?;\n        write_option_line!(python_framework_prefix)?;\n        write_line!(suppress_build_script_link_lines)?;\n        for line in &self.extra_build_script_lines {\n            writeln!(writer, \"extra_build_script_line={line}\")\n                .context(\"failed to write extra_build_script_line\")?;\n        }\n        Ok(())\n    }\n\n    /// Run a python script using the [`InterpreterConfig::executable`].\n    ///\n    /// # Panics\n    ///\n    /// This function will panic if the [`executable`](InterpreterConfig::executable) is `None`.\n    pub fn run_python_script(&self, script: &str) -> Result<String> {\n        run_python_script_with_envs(\n            Path::new(self.executable.as_ref().expect(\"no interpreter executable\")),\n            script,\n            std::iter::empty::<(&str, &str)>(),\n        )\n    }\n\n    /// Run a python script using the [`InterpreterConfig::executable`] with additional\n    /// environment variables (e.g. PYTHONPATH) set.\n    ///\n    /// # Panics\n    ///\n    /// This function will panic if the [`executable`](InterpreterConfig::executable) is `None`.\n    pub fn run_python_script_with_envs<I, K, V>(&self, script: &str, envs: I) -> Result<String>\n    where\n        I: IntoIterator<Item = (K, V)>,\n        K: AsRef<OsStr>,\n        V: AsRef<OsStr>,\n    {\n        run_python_script_with_envs(\n            Path::new(self.executable.as_ref().expect(\"no interpreter executable\")),\n            script,\n            envs,\n        )\n    }\n\n    pub fn is_free_threaded(&self) -> bool {\n        self.build_flags.0.contains(&BuildFlag::Py_GIL_DISABLED)\n    }\n\n    /// Updates configured ABI to build for to the requested abi3 version\n    /// This is a no-op for platforms where abi3 is not supported\n    fn fixup_for_abi3_version(&mut self, abi3_version: Option<PythonVersion>) -> Result<()> {\n        // PyPy, GraalPy, and the free-threaded build don't support abi3; don't adjust the version\n        if self.implementation.is_pypy()\n            || self.implementation.is_graalpy()\n            || self.is_free_threaded()\n        {\n            return Ok(());\n        }\n\n        if let Some(version) = abi3_version {\n            ensure!(\n                version <= self.version,\n                \"cannot set a minimum Python version {} higher than the interpreter version {} \\\n                (the minimum Python version is implied by the abi3-py3{} feature)\",\n                version,\n                self.version,\n                version.minor,\n            );\n\n            self.version = version;\n        } else if is_abi3() && self.version.minor > ABI3_MAX_MINOR {\n            warn!(\"Automatically falling back to abi3-py3{ABI3_MAX_MINOR} because current Python is higher than the maximum supported\");\n            self.version.minor = ABI3_MAX_MINOR;\n        }\n\n        Ok(())\n    }\n}\n\n#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]\npub struct PythonVersion {\n    pub major: u8,\n    pub minor: u8,\n}\n\nimpl PythonVersion {\n    pub const PY315: Self = PythonVersion {\n        major: 3,\n        minor: 15,\n    };\n    pub const PY313: Self = PythonVersion {\n        major: 3,\n        minor: 13,\n    };\n    pub const PY312: Self = PythonVersion {\n        major: 3,\n        minor: 12,\n    };\n    const PY310: Self = PythonVersion {\n        major: 3,\n        minor: 10,\n    };\n    const PY37: Self = PythonVersion { major: 3, minor: 7 };\n}\n\nimpl Display for PythonVersion {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}.{}\", self.major, self.minor)\n    }\n}\n\nimpl FromStr for PythonVersion {\n    type Err = crate::errors::Error;\n\n    fn from_str(value: &str) -> Result<Self, Self::Err> {\n        let mut split = value.splitn(2, '.');\n        let (major, minor) = (\n            split\n                .next()\n                .expect(\"first splitn value should always be present\"),\n            split.next().ok_or(\"expected major.minor version\")?,\n        );\n        Ok(Self {\n            major: major.parse().context(\"failed to parse major version\")?,\n            minor: minor.parse().context(\"failed to parse minor version\")?,\n        })\n    }\n}\n\n#[derive(Debug, Copy, Clone, PartialEq, Eq)]\npub enum PythonImplementation {\n    CPython,\n    PyPy,\n    GraalPy,\n}\n\nimpl PythonImplementation {\n    #[doc(hidden)]\n    pub fn is_pypy(self) -> bool {\n        self == PythonImplementation::PyPy\n    }\n\n    #[doc(hidden)]\n    pub fn is_graalpy(self) -> bool {\n        self == PythonImplementation::GraalPy\n    }\n\n    #[doc(hidden)]\n    pub fn from_soabi(soabi: &str) -> Result<Self> {\n        if soabi.starts_with(\"pypy\") {\n            Ok(PythonImplementation::PyPy)\n        } else if soabi.starts_with(\"cpython\") {\n            Ok(PythonImplementation::CPython)\n        } else if soabi.starts_with(\"graalpy\") {\n            Ok(PythonImplementation::GraalPy)\n        } else {\n            bail!(\"unsupported Python interpreter\");\n        }\n    }\n}\n\nimpl Display for PythonImplementation {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            PythonImplementation::CPython => write!(f, \"CPython\"),\n            PythonImplementation::PyPy => write!(f, \"PyPy\"),\n            PythonImplementation::GraalPy => write!(f, \"GraalVM\"),\n        }\n    }\n}\n\nimpl FromStr for PythonImplementation {\n    type Err = Error;\n    fn from_str(s: &str) -> Result<Self> {\n        match s {\n            \"CPython\" => Ok(PythonImplementation::CPython),\n            \"PyPy\" => Ok(PythonImplementation::PyPy),\n            \"GraalVM\" => Ok(PythonImplementation::GraalPy),\n            _ => bail!(\"unknown interpreter: {}\", s),\n        }\n    }\n}\n\n/// Checks if we should look for a Python interpreter installation\n/// to get the target interpreter configuration.\n///\n/// Returns `false` if `PYO3_NO_PYTHON` environment variable is set.\nfn have_python_interpreter() -> bool {\n    env_var(\"PYO3_NO_PYTHON\").is_none()\n}\n\n/// Checks if `abi3` or any of the `abi3-py3*` features is enabled for the PyO3 crate.\n///\n/// Must be called from a PyO3 crate build script.\nfn is_abi3() -> bool {\n    cargo_env_var(\"CARGO_FEATURE_ABI3\").is_some()\n        || env_var(\"PYO3_USE_ABI3_FORWARD_COMPATIBILITY\").is_some_and(|os_str| os_str == \"1\")\n}\n\n/// Gets the minimum supported Python version from PyO3 `abi3-py*` features.\n///\n/// Must be called from a PyO3 crate build script.\npub fn get_abi3_version() -> Option<PythonVersion> {\n    let minor_version = (MINIMUM_SUPPORTED_VERSION.minor..=ABI3_MAX_MINOR)\n        .find(|i| cargo_env_var(&format!(\"CARGO_FEATURE_ABI3_PY3{i}\")).is_some());\n    minor_version.map(|minor| PythonVersion { major: 3, minor })\n}\n\n/// Checks if the `extension-module` feature is enabled for the PyO3 crate.\n///\n/// This can be triggered either by:\n/// - The `extension-module` Cargo feature (deprecated)\n/// - Setting the `PYO3_BUILD_EXTENSION_MODULE` environment variable\n///\n/// Must be called from a PyO3 crate build script.\npub fn is_extension_module() -> bool {\n    cargo_env_var(\"CARGO_FEATURE_EXTENSION_MODULE\").is_some()\n        || env_var(\"PYO3_BUILD_EXTENSION_MODULE\").is_some()\n}\n\n/// Checks if we need to link to `libpython` for the target.\n///\n/// Must be called from a PyO3 crate build script.\npub fn is_linking_libpython_for_target(target: &Triple) -> bool {\n    target.operating_system == OperatingSystem::Windows\n        // See https://github.com/PyO3/pyo3/issues/4068#issuecomment-2051159852\n        || target.operating_system == OperatingSystem::Aix\n        || target.environment == Environment::Android\n        || target.environment == Environment::Androideabi\n        || target.operating_system == OperatingSystem::Cygwin\n        || matches!(target.operating_system, OperatingSystem::IOS(_))\n        || !is_extension_module()\n}\n\n/// Checks if we need to discover the Python library directory\n/// to link the extension module binary.\n///\n/// Must be called from a PyO3 crate build script.\nfn require_libdir_for_target(target: &Triple) -> bool {\n    // With raw-dylib, Windows targets never need a lib dir — the compiler generates\n    // import entries directly from `#[link(kind = \"raw-dylib\")]` attributes.\n    if target.operating_system == OperatingSystem::Windows {\n        return false;\n    }\n\n    is_linking_libpython_for_target(target)\n}\n\n/// Configuration needed by PyO3 to cross-compile for a target platform.\n///\n/// Usually this is collected from the environment (i.e. `PYO3_CROSS_*` and `CARGO_CFG_TARGET_*`)\n/// when a cross-compilation configuration is detected.\n#[derive(Debug, PartialEq, Eq)]\npub struct CrossCompileConfig {\n    /// The directory containing the Python library to link against.\n    pub lib_dir: Option<PathBuf>,\n\n    /// The version of the Python library to link against.\n    version: Option<PythonVersion>,\n\n    /// The target Python implementation hint (CPython, PyPy, GraalPy, ...)\n    implementation: Option<PythonImplementation>,\n\n    /// The compile target triple (e.g. aarch64-unknown-linux-gnu)\n    target: Triple,\n\n    /// Python ABI flags, used to detect free-threaded Python builds.\n    abiflags: Option<String>,\n}\n\nimpl CrossCompileConfig {\n    /// Creates a new cross compile config struct from PyO3 environment variables\n    /// and the build environment when cross compilation mode is detected.\n    ///\n    /// Returns `None` when not cross compiling.\n    fn try_from_env_vars_host_target(\n        env_vars: CrossCompileEnvVars,\n        host: &Triple,\n        target: &Triple,\n    ) -> Result<Option<Self>> {\n        if env_vars.any() || Self::is_cross_compiling_from_to(host, target) {\n            let lib_dir = env_vars.lib_dir_path()?;\n            let (version, abiflags) = env_vars.parse_version()?;\n            let implementation = env_vars.parse_implementation()?;\n            let target = target.clone();\n\n            Ok(Some(CrossCompileConfig {\n                lib_dir,\n                version,\n                implementation,\n                target,\n                abiflags,\n            }))\n        } else {\n            Ok(None)\n        }\n    }\n\n    /// Checks if compiling on `host` for `target` required \"real\" cross compilation.\n    ///\n    /// Returns `false` if the target Python interpreter can run on the host.\n    fn is_cross_compiling_from_to(host: &Triple, target: &Triple) -> bool {\n        // Not cross-compiling if arch-vendor-os is all the same\n        // e.g. x86_64-unknown-linux-musl on x86_64-unknown-linux-gnu host\n        //      x86_64-pc-windows-gnu on x86_64-pc-windows-msvc host\n        let mut compatible = host.architecture == target.architecture\n            && (host.vendor == target.vendor\n                // Don't treat `-pc-` to `-win7-` as cross-compiling\n                || (host.vendor == Vendor::Pc && target.vendor.as_str() == \"win7\"))\n            && host.operating_system == target.operating_system;\n\n        // Not cross-compiling to compile for 32-bit Python from windows 64-bit\n        compatible |= target.operating_system == OperatingSystem::Windows\n            && host.operating_system == OperatingSystem::Windows\n            && matches!(target.architecture, Architecture::X86_32(_))\n            && host.architecture == Architecture::X86_64;\n\n        // Not cross-compiling to compile for x86-64 Python from macOS arm64 and vice versa\n        compatible |= matches!(target.operating_system, OperatingSystem::Darwin(_))\n            && matches!(host.operating_system, OperatingSystem::Darwin(_));\n\n        compatible |= matches!(target.operating_system, OperatingSystem::IOS(_));\n\n        !compatible\n    }\n\n    /// Converts `lib_dir` member field to an UTF-8 string.\n    ///\n    /// The conversion can not fail because `PYO3_CROSS_LIB_DIR` variable\n    /// is ensured contain a valid UTF-8 string.\n    #[allow(dead_code)]\n    fn lib_dir_string(&self) -> Option<String> {\n        self.lib_dir\n            .as_ref()\n            .map(|s| s.to_str().unwrap().to_owned())\n    }\n}\n\n/// PyO3-specific cross compile environment variable values\nstruct CrossCompileEnvVars {\n    /// `PYO3_CROSS`\n    pyo3_cross: Option<OsString>,\n    /// `PYO3_CROSS_LIB_DIR`\n    pyo3_cross_lib_dir: Option<OsString>,\n    /// `PYO3_CROSS_PYTHON_VERSION`\n    pyo3_cross_python_version: Option<OsString>,\n    /// `PYO3_CROSS_PYTHON_IMPLEMENTATION`\n    pyo3_cross_python_implementation: Option<OsString>,\n}\n\nimpl CrossCompileEnvVars {\n    /// Grabs the PyO3 cross-compile variables from the environment.\n    ///\n    /// Registers the build script to rerun if any of the variables changes.\n    fn from_env() -> Self {\n        CrossCompileEnvVars {\n            pyo3_cross: env_var(\"PYO3_CROSS\"),\n            pyo3_cross_lib_dir: env_var(\"PYO3_CROSS_LIB_DIR\"),\n            pyo3_cross_python_version: env_var(\"PYO3_CROSS_PYTHON_VERSION\"),\n            pyo3_cross_python_implementation: env_var(\"PYO3_CROSS_PYTHON_IMPLEMENTATION\"),\n        }\n    }\n\n    /// Checks if any of the variables is set.\n    fn any(&self) -> bool {\n        self.pyo3_cross.is_some()\n            || self.pyo3_cross_lib_dir.is_some()\n            || self.pyo3_cross_python_version.is_some()\n            || self.pyo3_cross_python_implementation.is_some()\n    }\n\n    /// Parses `PYO3_CROSS_PYTHON_VERSION` environment variable value\n    /// into `PythonVersion` and ABI flags.\n    fn parse_version(&self) -> Result<(Option<PythonVersion>, Option<String>)> {\n        match self.pyo3_cross_python_version.as_ref() {\n            Some(os_string) => {\n                let utf8_str = os_string\n                    .to_str()\n                    .ok_or(\"PYO3_CROSS_PYTHON_VERSION is not valid a UTF-8 string\")?;\n                let (utf8_str, abiflags) = if let Some(version) = utf8_str.strip_suffix('t') {\n                    (version, Some(\"t\".to_string()))\n                } else {\n                    (utf8_str, None)\n                };\n                let version = utf8_str\n                    .parse()\n                    .context(\"failed to parse PYO3_CROSS_PYTHON_VERSION\")?;\n                Ok((Some(version), abiflags))\n            }\n            None => Ok((None, None)),\n        }\n    }\n\n    /// Parses `PYO3_CROSS_PYTHON_IMPLEMENTATION` environment variable value\n    /// into `PythonImplementation`.\n    fn parse_implementation(&self) -> Result<Option<PythonImplementation>> {\n        let implementation = self\n            .pyo3_cross_python_implementation\n            .as_ref()\n            .map(|os_string| {\n                let utf8_str = os_string\n                    .to_str()\n                    .ok_or(\"PYO3_CROSS_PYTHON_IMPLEMENTATION is not valid a UTF-8 string\")?;\n                utf8_str\n                    .parse()\n                    .context(\"failed to parse PYO3_CROSS_PYTHON_IMPLEMENTATION\")\n            })\n            .transpose()?;\n\n        Ok(implementation)\n    }\n\n    /// Converts the stored `PYO3_CROSS_LIB_DIR` variable value (if any)\n    /// into a `PathBuf` instance.\n    ///\n    /// Ensures that the path is a valid UTF-8 string.\n    fn lib_dir_path(&self) -> Result<Option<PathBuf>> {\n        let lib_dir = self.pyo3_cross_lib_dir.as_ref().map(PathBuf::from);\n\n        if let Some(dir) = lib_dir.as_ref() {\n            ensure!(\n                dir.to_str().is_some(),\n                \"PYO3_CROSS_LIB_DIR variable value is not a valid UTF-8 string\"\n            );\n        }\n\n        Ok(lib_dir)\n    }\n}\n\n/// Detect whether we are cross compiling and return an assembled CrossCompileConfig if so.\n///\n/// This function relies on PyO3 cross-compiling environment variables:\n///\n/// * `PYO3_CROSS`: If present, forces PyO3 to configure as a cross-compilation.\n/// * `PYO3_CROSS_LIB_DIR`: If present, must be set to the directory containing\n///   the target's libpython DSO and the associated `_sysconfigdata*.py` file for\n///   Unix-like targets, or the Python DLL import libraries for the Windows target.\n/// * `PYO3_CROSS_PYTHON_VERSION`: Major and minor version (e.g. 3.9) of the target Python\n///   installation. This variable is only needed if PyO3 cannot determine the version to target\n///   from `abi3-py3*` features, or if there are multiple versions of Python present in\n///   `PYO3_CROSS_LIB_DIR`.\n///\n/// See the [PyO3 User Guide](https://pyo3.rs/) for more info on cross-compiling.\npub fn cross_compiling_from_to(\n    host: &Triple,\n    target: &Triple,\n) -> Result<Option<CrossCompileConfig>> {\n    let env_vars = CrossCompileEnvVars::from_env();\n    CrossCompileConfig::try_from_env_vars_host_target(env_vars, host, target)\n}\n\n/// Detect whether we are cross compiling from Cargo and `PYO3_CROSS_*` environment\n/// variables and return an assembled `CrossCompileConfig` if so.\n///\n/// This must be called from PyO3's build script, because it relies on environment\n/// variables such as `CARGO_CFG_TARGET_OS` which aren't available at any other time.\n#[allow(dead_code)]\npub fn cross_compiling_from_cargo_env() -> Result<Option<CrossCompileConfig>> {\n    let env_vars = CrossCompileEnvVars::from_env();\n    let host = Triple::host();\n    let target = target_triple_from_env();\n\n    CrossCompileConfig::try_from_env_vars_host_target(env_vars, &host, &target)\n}\n\n#[allow(non_camel_case_types)]\n#[derive(Debug, Clone, Hash, PartialEq, Eq)]\npub enum BuildFlag {\n    Py_DEBUG,\n    Py_REF_DEBUG,\n    #[deprecated(since = \"0.29.0\", note = \"no longer supported by PyO3\")]\n    Py_TRACE_REFS,\n    Py_GIL_DISABLED,\n    COUNT_ALLOCS,\n    Other(String),\n}\n\nimpl Display for BuildFlag {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        match self {\n            BuildFlag::Other(flag) => write!(f, \"{flag}\"),\n            _ => write!(f, \"{self:?}\"),\n        }\n    }\n}\n\nimpl FromStr for BuildFlag {\n    type Err = std::convert::Infallible;\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        match s {\n            \"Py_DEBUG\" => Ok(BuildFlag::Py_DEBUG),\n            \"Py_REF_DEBUG\" => Ok(BuildFlag::Py_REF_DEBUG),\n            \"Py_GIL_DISABLED\" => Ok(BuildFlag::Py_GIL_DISABLED),\n            \"COUNT_ALLOCS\" => Ok(BuildFlag::COUNT_ALLOCS),\n            other => Ok(BuildFlag::Other(other.to_owned())),\n        }\n    }\n}\n\n/// A list of python interpreter compile-time preprocessor defines.\n///\n/// PyO3 will pick these up and pass to rustc via `--cfg=py_sys_config={varname}`;\n/// this allows using them conditional cfg attributes in the .rs files, so\n///\n/// ```rust,no_run\n/// #[cfg(py_sys_config=\"{varname}\")]\n/// # struct Foo;\n/// ```\n///\n/// is the equivalent of `#ifdef {varname}` in C.\n///\n/// see Misc/SpecialBuilds.txt in the python source for what these mean.\n#[cfg_attr(test, derive(Debug, PartialEq, Eq))]\n#[derive(Clone, Default)]\npub struct BuildFlags(pub HashSet<BuildFlag>);\n\nimpl BuildFlags {\n    const ALL: [BuildFlag; 4] = [\n        BuildFlag::Py_DEBUG,\n        BuildFlag::Py_REF_DEBUG,\n        BuildFlag::Py_GIL_DISABLED,\n        BuildFlag::COUNT_ALLOCS,\n    ];\n\n    pub fn new() -> Self {\n        BuildFlags(HashSet::new())\n    }\n\n    fn from_sysconfigdata(config_map: &Sysconfigdata) -> Self {\n        Self(\n            BuildFlags::ALL\n                .iter()\n                .filter(|flag| config_map.get_value(flag.to_string()) == Some(\"1\"))\n                .cloned()\n                .collect(),\n        )\n        .fixup()\n    }\n\n    /// Examine python's compile flags to pass to cfg by launching\n    /// the interpreter and printing variables of interest from\n    /// sysconfig.get_config_vars.\n    fn from_interpreter(interpreter: impl AsRef<Path>) -> Result<Self> {\n        // sysconfig is missing all the flags on windows for Python 3.12 and\n        // older, so we can't actually query the interpreter directly for its\n        // build flags on those versions.\n        if cfg!(windows) {\n            let script = String::from(\"import sys;print(sys.version_info < (3, 13))\");\n            let stdout = run_python_script(interpreter.as_ref(), &script)?;\n            if stdout.trim_end() == \"True\" {\n                return Ok(Self::new());\n            }\n        }\n\n        let mut script = String::from(\"import sysconfig\\n\");\n        script.push_str(\"config = sysconfig.get_config_vars()\\n\");\n\n        for k in &BuildFlags::ALL {\n            use std::fmt::Write;\n            writeln!(&mut script, \"print(config.get('{k}', '0'))\").unwrap();\n        }\n\n        let stdout = run_python_script(interpreter.as_ref(), &script)?;\n        let split_stdout: Vec<&str> = stdout.trim_end().lines().collect();\n        ensure!(\n            split_stdout.len() == BuildFlags::ALL.len(),\n            \"Python stdout len didn't return expected number of lines: {}\",\n            split_stdout.len()\n        );\n        let flags = BuildFlags::ALL\n            .iter()\n            .zip(split_stdout)\n            .filter(|(_, flag_value)| *flag_value == \"1\")\n            .map(|(flag, _)| flag.clone())\n            .collect();\n\n        Ok(Self(flags).fixup())\n    }\n\n    fn fixup(mut self) -> Self {\n        if self.0.contains(&BuildFlag::Py_DEBUG) {\n            self.0.insert(BuildFlag::Py_REF_DEBUG);\n        }\n\n        self\n    }\n}\n\nimpl Display for BuildFlags {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let mut first = true;\n        for flag in &self.0 {\n            if first {\n                first = false;\n            } else {\n                write!(f, \",\")?;\n            }\n            write!(f, \"{flag}\")?;\n        }\n        Ok(())\n    }\n}\n\nimpl FromStr for BuildFlags {\n    type Err = std::convert::Infallible;\n\n    fn from_str(value: &str) -> Result<Self, Self::Err> {\n        let mut flags = HashSet::new();\n        for flag in value.split_terminator(',') {\n            flags.insert(flag.parse().unwrap());\n        }\n        Ok(BuildFlags(flags))\n    }\n}\n\nfn parse_script_output(output: &str) -> HashMap<String, String> {\n    output\n        .lines()\n        .filter_map(|line| {\n            let mut i = line.splitn(2, ' ');\n            Some((i.next()?.into(), i.next()?.into()))\n        })\n        .collect()\n}\n\n/// Parsed data from Python sysconfigdata file\n///\n/// A hash map of all values from a sysconfigdata file.\npub struct Sysconfigdata(HashMap<String, String>);\n\nimpl Sysconfigdata {\n    pub fn get_value<S: AsRef<str>>(&self, k: S) -> Option<&str> {\n        self.0.get(k.as_ref()).map(String::as_str)\n    }\n\n    #[allow(dead_code)]\n    fn new() -> Self {\n        Sysconfigdata(HashMap::new())\n    }\n\n    #[allow(dead_code)]\n    fn insert<S: Into<String>>(&mut self, k: S, v: S) {\n        self.0.insert(k.into(), v.into());\n    }\n}\n\n/// Parse sysconfigdata file\n///\n/// The sysconfigdata is simply a dictionary containing all the build time variables used for the\n/// python executable and library. This function necessitates a python interpreter on the host\n/// machine to work. Here it is read into a `Sysconfigdata` (hash map), which can be turned into an\n/// [`InterpreterConfig`] using\n/// [`from_sysconfigdata`](InterpreterConfig::from_sysconfigdata).\npub fn parse_sysconfigdata(sysconfigdata_path: impl AsRef<Path>) -> Result<Sysconfigdata> {\n    let sysconfigdata_path = sysconfigdata_path.as_ref();\n    let mut script = fs::read_to_string(sysconfigdata_path).with_context(|| {\n        format!(\n            \"failed to read config from {}\",\n            sysconfigdata_path.display()\n        )\n    })?;\n    script += r#\"\nfor key, val in build_time_vars.items():\n    # (ana)conda(-forge) built Pythons are statically linked but ship the shared library with them.\n    # We detect them based on the magic prefix directory they have encoded in their builds.\n    if key == \"Py_ENABLE_SHARED\" and \"_h_env_placehold\" in build_time_vars.get(\"prefix\"):\n        val = 1\n    print(key, val)\n\"#;\n\n    let output = run_python_script(&find_interpreter()?, &script)?;\n\n    Ok(Sysconfigdata(parse_script_output(&output)))\n}\n\nfn starts_with(entry: &DirEntry, pat: &str) -> bool {\n    let name = entry.file_name();\n    name.to_string_lossy().starts_with(pat)\n}\nfn ends_with(entry: &DirEntry, pat: &str) -> bool {\n    let name = entry.file_name();\n    name.to_string_lossy().ends_with(pat)\n}\n\n/// Finds the sysconfigdata file when the target Python library directory is set.\n///\n/// Returns `None` if the library directory is not available, and a runtime error\n/// when no or multiple sysconfigdata files are found.\n#[allow(dead_code)]\nfn find_sysconfigdata(cross: &CrossCompileConfig) -> Result<Option<PathBuf>> {\n    let mut sysconfig_paths = find_all_sysconfigdata(cross)?;\n    if sysconfig_paths.is_empty() {\n        if let Some(lib_dir) = cross.lib_dir.as_ref() {\n            bail!(\"Could not find _sysconfigdata*.py in {}\", lib_dir.display());\n        } else {\n            // Continue with the default configuration when PYO3_CROSS_LIB_DIR is not set.\n            return Ok(None);\n        }\n    } else if sysconfig_paths.len() > 1 {\n        let mut error_msg = String::from(\n            \"Detected multiple possible Python versions. Please set either the \\\n            PYO3_CROSS_PYTHON_VERSION variable to the wanted version or the \\\n            _PYTHON_SYSCONFIGDATA_NAME variable to the wanted sysconfigdata file name.\\n\\n\\\n            sysconfigdata files found:\",\n        );\n        for path in sysconfig_paths {\n            use std::fmt::Write;\n            write!(&mut error_msg, \"\\n\\t{}\", path.display()).unwrap();\n        }\n        bail!(\"{}\\n\", error_msg);\n    }\n\n    Ok(Some(sysconfig_paths.remove(0)))\n}\n\n/// Finds `_sysconfigdata*.py` files for detected Python interpreters.\n///\n/// From the python source for `_sysconfigdata*.py` is always going to be located at\n/// `build/lib.{PLATFORM}-{PY_MINOR_VERSION}` when built from source. The [exact line][1] is defined as:\n///\n/// ```py\n/// pybuilddir = 'build/lib.%s-%s' % (get_platform(), sys.version_info[:2])\n/// ```\n///\n/// Where get_platform returns a kebab-case formatted string containing the os, the architecture and\n/// possibly the os' kernel version (not the case on linux). However, when installed using a package\n/// manager, the `_sysconfigdata*.py` file is installed in the `${PREFIX}/lib/python3.Y/` directory.\n/// The `_sysconfigdata*.py` is generally in a sub-directory of the location of `libpython3.Y.so`.\n/// So we must find the file in the following possible locations:\n///\n/// ```sh\n/// # distribution from package manager, (lib_dir may or may not include lib/)\n/// ${INSTALL_PREFIX}/lib/python3.Y/_sysconfigdata*.py\n/// ${INSTALL_PREFIX}/lib/libpython3.Y.so\n/// ${INSTALL_PREFIX}/lib/python3.Y/config-3.Y-${HOST_TRIPLE}/libpython3.Y.so\n///\n/// # Built from source from host\n/// ${CROSS_COMPILED_LOCATION}/build/lib.linux-x86_64-Y/_sysconfigdata*.py\n/// ${CROSS_COMPILED_LOCATION}/libpython3.Y.so\n///\n/// # if cross compiled, kernel release is only present on certain OS targets.\n/// ${CROSS_COMPILED_LOCATION}/build/lib.{OS}(-{OS-KERNEL-RELEASE})?-{ARCH}-Y/_sysconfigdata*.py\n/// ${CROSS_COMPILED_LOCATION}/libpython3.Y.so\n///\n/// # PyPy includes a similar file since v73\n/// ${INSTALL_PREFIX}/lib/pypy3.Y/_sysconfigdata.py\n/// ${INSTALL_PREFIX}/lib_pypy/_sysconfigdata.py\n/// ```\n///\n/// [1]: https://github.com/python/cpython/blob/3.5/Lib/sysconfig.py#L389\n///\n/// Returns an empty vector when the target Python library directory\n/// is not set via `PYO3_CROSS_LIB_DIR`.\npub fn find_all_sysconfigdata(cross: &CrossCompileConfig) -> Result<Vec<PathBuf>> {\n    let sysconfig_paths = if let Some(lib_dir) = cross.lib_dir.as_ref() {\n        search_lib_dir(lib_dir, cross).with_context(|| {\n            format!(\n                \"failed to search the lib dir at 'PYO3_CROSS_LIB_DIR={}'\",\n                lib_dir.display()\n            )\n        })?\n    } else {\n        return Ok(Vec::new());\n    };\n\n    let sysconfig_name = env_var(\"_PYTHON_SYSCONFIGDATA_NAME\");\n    let mut sysconfig_paths = sysconfig_paths\n        .iter()\n        .filter_map(|p| {\n            let canonical = fs::canonicalize(p).ok();\n            match &sysconfig_name {\n                Some(_) => canonical.filter(|p| p.file_stem() == sysconfig_name.as_deref()),\n                None => canonical,\n            }\n        })\n        .collect::<Vec<PathBuf>>();\n\n    sysconfig_paths.sort();\n    sysconfig_paths.dedup();\n\n    Ok(sysconfig_paths)\n}\n\nfn is_pypy_lib_dir(path: &str, v: &Option<PythonVersion>) -> bool {\n    let pypy_version_pat = if let Some(v) = v {\n        format!(\"pypy{v}\")\n    } else {\n        \"pypy3.\".into()\n    };\n    path == \"lib_pypy\" || path.starts_with(&pypy_version_pat)\n}\n\nfn is_graalpy_lib_dir(path: &str, v: &Option<PythonVersion>) -> bool {\n    let graalpy_version_pat = if let Some(v) = v {\n        format!(\"graalpy{v}\")\n    } else {\n        \"graalpy2\".into()\n    };\n    path == \"lib_graalpython\" || path.starts_with(&graalpy_version_pat)\n}\n\nfn is_cpython_lib_dir(path: &str, v: &Option<PythonVersion>) -> bool {\n    let cpython_version_pat = if let Some(v) = v {\n        format!(\"python{v}\")\n    } else {\n        \"python3.\".into()\n    };\n    path.starts_with(&cpython_version_pat)\n}\n\n/// recursive search for _sysconfigdata, returns all possibilities of sysconfigdata paths\nfn search_lib_dir(path: impl AsRef<Path>, cross: &CrossCompileConfig) -> Result<Vec<PathBuf>> {\n    let mut sysconfig_paths = vec![];\n    for f in fs::read_dir(path.as_ref()).with_context(|| {\n        format!(\n            \"failed to list the entries in '{}'\",\n            path.as_ref().display()\n        )\n    })? {\n        sysconfig_paths.extend(match &f {\n            // Python 3.7+ sysconfigdata with platform specifics\n            Ok(f) if starts_with(f, \"_sysconfigdata_\") && ends_with(f, \"py\") => vec![f.path()],\n            Ok(f) if f.metadata().is_ok_and(|metadata| metadata.is_dir()) => {\n                let file_name = f.file_name();\n                let file_name = file_name.to_string_lossy();\n                if file_name == \"build\" || file_name == \"lib\" {\n                    search_lib_dir(f.path(), cross)?\n                } else if file_name.starts_with(\"lib.\") {\n                    // check if right target os\n                    if !file_name.contains(&cross.target.operating_system.to_string()) {\n                        continue;\n                    }\n                    // Check if right arch\n                    if !file_name.contains(&cross.target.architecture.to_string()) {\n                        continue;\n                    }\n                    search_lib_dir(f.path(), cross)?\n                } else if is_cpython_lib_dir(&file_name, &cross.version)\n                    || is_pypy_lib_dir(&file_name, &cross.version)\n                    || is_graalpy_lib_dir(&file_name, &cross.version)\n                {\n                    search_lib_dir(f.path(), cross)?\n                } else {\n                    continue;\n                }\n            }\n            _ => continue,\n        });\n    }\n    // If we got more than one file, only take those that contain the arch name.\n    // For ubuntu 20.04 with host architecture x86_64 and a foreign architecture of armhf\n    // this reduces the number of candidates to 1:\n    //\n    // $ find /usr/lib/python3.8/ -name '_sysconfigdata*.py' -not -lname '*'\n    //  /usr/lib/python3.8/_sysconfigdata__x86_64-linux-gnu.py\n    //  /usr/lib/python3.8/_sysconfigdata__arm-linux-gnueabihf.py\n    if sysconfig_paths.len() > 1 {\n        let temp = sysconfig_paths\n            .iter()\n            .filter(|p| {\n                p.to_string_lossy()\n                    .contains(&cross.target.architecture.to_string())\n            })\n            .cloned()\n            .collect::<Vec<PathBuf>>();\n        if !temp.is_empty() {\n            sysconfig_paths = temp;\n        }\n    }\n\n    Ok(sysconfig_paths)\n}\n\n/// Find cross compilation information from sysconfigdata file\n///\n/// first find sysconfigdata file which follows the pattern [`_sysconfigdata_{abi}_{platform}_{multiarch}`][1]\n///\n/// [1]: https://github.com/python/cpython/blob/3.8/Lib/sysconfig.py#L348\n///\n/// Returns `None` when the target Python library directory is not set.\n#[allow(dead_code)]\nfn cross_compile_from_sysconfigdata(\n    cross_compile_config: &CrossCompileConfig,\n) -> Result<Option<InterpreterConfig>> {\n    if let Some(path) = find_sysconfigdata(cross_compile_config)? {\n        let data = parse_sysconfigdata(path)?;\n        let mut config = InterpreterConfig::from_sysconfigdata(&data)?;\n        if let Some(cross_lib_dir) = cross_compile_config.lib_dir_string() {\n            config.lib_dir = Some(cross_lib_dir)\n        }\n\n        Ok(Some(config))\n    } else {\n        Ok(None)\n    }\n}\n\n/// Generates \"default\" cross compilation information for the target.\n///\n/// This should work for most CPython extension modules when targeting\n/// Windows, macOS and Linux.\n///\n/// Must be called from a PyO3 crate build script.\n#[allow(unused_mut, dead_code)]\nfn default_cross_compile(cross_compile_config: &CrossCompileConfig) -> Result<InterpreterConfig> {\n    let version = cross_compile_config\n        .version\n        .or_else(get_abi3_version)\n        .ok_or_else(||\n            format!(\n                \"PYO3_CROSS_PYTHON_VERSION or an abi3-py3* feature must be specified \\\n                when cross-compiling and PYO3_CROSS_LIB_DIR is not set.\\n\\\n                = help: see the PyO3 user guide for more information: https://pyo3.rs/v{}/building-and-distribution.html#cross-compiling\",\n                env!(\"CARGO_PKG_VERSION\")\n            )\n        )?;\n\n    let abi3 = is_abi3();\n    let implementation = cross_compile_config\n        .implementation\n        .unwrap_or(PythonImplementation::CPython);\n    let gil_disabled: bool = cross_compile_config.abiflags.as_deref() == Some(\"t\");\n\n    let lib_name = default_lib_name_for_target(\n        version,\n        implementation,\n        abi3,\n        gil_disabled,\n        &cross_compile_config.target,\n    );\n\n    let mut lib_dir = cross_compile_config.lib_dir_string();\n\n    Ok(InterpreterConfig {\n        implementation,\n        version,\n        shared: true,\n        abi3,\n        lib_name: Some(lib_name),\n        lib_dir,\n        executable: None,\n        pointer_width: None,\n        build_flags: BuildFlags::default(),\n        suppress_build_script_link_lines: false,\n        extra_build_script_lines: vec![],\n        python_framework_prefix: None,\n    })\n}\n\n/// Generates \"default\" interpreter configuration when compiling \"abi3\" extensions\n/// without a working Python interpreter.\n///\n/// `version` specifies the minimum supported Stable ABI CPython version.\n///\n/// This should work for most CPython extension modules when compiling on\n/// Windows, macOS and Linux.\n///\n/// Must be called from a PyO3 crate build script.\nfn default_abi3_config(host: &Triple, version: PythonVersion) -> Result<InterpreterConfig> {\n    // FIXME: PyPy & GraalPy do not support the Stable ABI.\n    let implementation = PythonImplementation::CPython;\n    let abi3 = true;\n\n    let lib_name = if host.operating_system == OperatingSystem::Windows {\n        Some(default_lib_name_windows(\n            version,\n            implementation,\n            abi3,\n            false,\n            false,\n            false,\n        )?)\n    } else {\n        None\n    };\n\n    Ok(InterpreterConfig {\n        implementation,\n        version,\n        shared: true,\n        abi3,\n        lib_name,\n        lib_dir: None,\n        executable: None,\n        pointer_width: None,\n        build_flags: BuildFlags::default(),\n        suppress_build_script_link_lines: false,\n        extra_build_script_lines: vec![],\n        python_framework_prefix: None,\n    })\n}\n\n/// Detects the cross compilation target interpreter configuration from all\n/// available sources (PyO3 environment variables, Python sysconfigdata, etc.).\n///\n/// Returns the \"default\" target interpreter configuration for Windows and\n/// when no target Python interpreter is found.\n///\n/// Must be called from a PyO3 crate build script.\n#[allow(dead_code)]\nfn load_cross_compile_config(\n    cross_compile_config: CrossCompileConfig,\n) -> Result<InterpreterConfig> {\n    let windows = cross_compile_config.target.operating_system == OperatingSystem::Windows;\n\n    let config = if windows || !have_python_interpreter() {\n        // Load the defaults for Windows even when `PYO3_CROSS_LIB_DIR` is set\n        // since it has no sysconfigdata files in it.\n        // Also, do not try to look for sysconfigdata when `PYO3_NO_PYTHON` variable is set.\n        default_cross_compile(&cross_compile_config)?\n    } else if let Some(config) = cross_compile_from_sysconfigdata(&cross_compile_config)? {\n        // Try to find and parse sysconfigdata files on other targets.\n        config\n    } else {\n        // Fall back to the defaults when nothing else can be done.\n        default_cross_compile(&cross_compile_config)?\n    };\n\n    Ok(config)\n}\n\n// These contains only the limited ABI symbols.\nconst WINDOWS_ABI3_LIB_NAME: &str = \"python3\";\nconst WINDOWS_ABI3_DEBUG_LIB_NAME: &str = \"python3_d\";\n\n/// Generates the default library name for the target platform.\n#[allow(dead_code)]\nfn default_lib_name_for_target(\n    version: PythonVersion,\n    implementation: PythonImplementation,\n    abi3: bool,\n    gil_disabled: bool,\n    target: &Triple,\n) -> String {\n    if target.operating_system == OperatingSystem::Windows {\n        default_lib_name_windows(version, implementation, abi3, false, false, gil_disabled).unwrap()\n    } else {\n        default_lib_name_unix(\n            version,\n            implementation,\n            abi3,\n            target.operating_system == OperatingSystem::Cygwin,\n            None,\n            gil_disabled,\n        )\n        .unwrap()\n    }\n}\n\nfn default_lib_name_windows(\n    version: PythonVersion,\n    implementation: PythonImplementation,\n    abi3: bool,\n    mingw: bool,\n    debug: bool,\n    gil_disabled: bool,\n) -> Result<String> {\n    if implementation.is_pypy() {\n        // PyPy on Windows ships `libpypy3.X-c.dll` (e.g. `libpypy3.11-c.dll`),\n        // not CPython's `pythonXY.dll`. With raw-dylib linking we need the real\n        // DLL name rather than the import-library alias.\n        Ok(format!(\"libpypy{}.{}-c\", version.major, version.minor))\n    } else if debug && version < PythonVersion::PY310 {\n        // CPython bug: linking against python3_d.dll raises error\n        // https://github.com/python/cpython/issues/101614\n        Ok(format!(\"python{}{}_d\", version.major, version.minor))\n    } else if abi3 && !(gil_disabled || implementation.is_pypy() || implementation.is_graalpy()) {\n        if debug {\n            Ok(WINDOWS_ABI3_DEBUG_LIB_NAME.to_owned())\n        } else {\n            Ok(WINDOWS_ABI3_LIB_NAME.to_owned())\n        }\n    } else if mingw {\n        ensure!(\n            !gil_disabled,\n            \"MinGW free-threaded builds are not currently tested or supported\"\n        );\n        // https://packages.msys2.org/base/mingw-w64-python\n        Ok(format!(\"python{}.{}\", version.major, version.minor))\n    } else if gil_disabled {\n        ensure!(version >= PythonVersion::PY313, \"Cannot compile C extensions for the free-threaded build on Python versions earlier than 3.13, found {}.{}\", version.major, version.minor);\n        if debug {\n            Ok(format!(\"python{}{}t_d\", version.major, version.minor))\n        } else {\n            Ok(format!(\"python{}{}t\", version.major, version.minor))\n        }\n    } else if debug {\n        Ok(format!(\"python{}{}_d\", version.major, version.minor))\n    } else {\n        Ok(format!(\"python{}{}\", version.major, version.minor))\n    }\n}\n\nfn default_lib_name_unix(\n    version: PythonVersion,\n    implementation: PythonImplementation,\n    abi3: bool,\n    cygwin: bool,\n    ld_version: Option<&str>,\n    gil_disabled: bool,\n) -> Result<String> {\n    match implementation {\n        PythonImplementation::CPython => match ld_version {\n            Some(ld_version) => Ok(format!(\"python{ld_version}\")),\n            None => {\n                if cygwin && abi3 {\n                    Ok(\"python3\".to_string())\n                } else if version > PythonVersion::PY37 {\n                    // PEP 3149 ABI version tags are finally gone\n                    if gil_disabled {\n                        ensure!(version >= PythonVersion::PY313, \"Cannot compile C extensions for the free-threaded build on Python versions earlier than 3.13, found {}.{}\", version.major, version.minor);\n                        Ok(format!(\"python{}.{}t\", version.major, version.minor))\n                    } else {\n                        Ok(format!(\"python{}.{}\", version.major, version.minor))\n                    }\n                } else {\n                    // Work around https://bugs.python.org/issue36707\n                    Ok(format!(\"python{}.{}m\", version.major, version.minor))\n                }\n            }\n        },\n        PythonImplementation::PyPy => match ld_version {\n            Some(ld_version) => Ok(format!(\"pypy{ld_version}-c\")),\n            None => Ok(format!(\"pypy{}.{}-c\", version.major, version.minor)),\n        },\n\n        PythonImplementation::GraalPy => Ok(\"python-native\".to_string()),\n    }\n}\n\n/// Run a python script using the specified interpreter binary.\nfn run_python_script(interpreter: &Path, script: &str) -> Result<String> {\n    run_python_script_with_envs(interpreter, script, std::iter::empty::<(&str, &str)>())\n}\n\n/// Run a python script using the specified interpreter binary with additional environment\n/// variables (e.g. PYTHONPATH) set.\nfn run_python_script_with_envs<I, K, V>(interpreter: &Path, script: &str, envs: I) -> Result<String>\nwhere\n    I: IntoIterator<Item = (K, V)>,\n    K: AsRef<OsStr>,\n    V: AsRef<OsStr>,\n{\n    let out = Command::new(interpreter)\n        .env(\"PYTHONIOENCODING\", \"utf-8\")\n        .envs(envs)\n        .stdin(Stdio::piped())\n        .stdout(Stdio::piped())\n        .stderr(Stdio::inherit())\n        .spawn()\n        .and_then(|mut child| {\n            child\n                .stdin\n                .as_mut()\n                .expect(\"piped stdin\")\n                .write_all(script.as_bytes())?;\n            child.wait_with_output()\n        });\n\n    match out {\n        Err(err) => bail!(\n            \"failed to run the Python interpreter at {}: {}\",\n            interpreter.display(),\n            err\n        ),\n        Ok(ok) if !ok.status.success() => bail!(\"Python script failed\"),\n        Ok(ok) => Ok(String::from_utf8(ok.stdout)\n            .context(\"failed to parse Python script output as utf-8\")?),\n    }\n}\n\nfn venv_interpreter(virtual_env: &OsStr, windows: bool) -> PathBuf {\n    if windows {\n        Path::new(virtual_env).join(\"Scripts\").join(\"python.exe\")\n    } else {\n        Path::new(virtual_env).join(\"bin\").join(\"python\")\n    }\n}\n\nfn conda_env_interpreter(conda_prefix: &OsStr, windows: bool) -> PathBuf {\n    if windows {\n        Path::new(conda_prefix).join(\"python.exe\")\n    } else {\n        Path::new(conda_prefix).join(\"bin\").join(\"python\")\n    }\n}\n\nfn get_env_interpreter() -> Option<PathBuf> {\n    match (env_var(\"VIRTUAL_ENV\"), env_var(\"CONDA_PREFIX\")) {\n        // Use cfg rather than CARGO_CFG_TARGET_OS because this affects where files are located on the\n        // build host\n        (Some(dir), None) => Some(venv_interpreter(&dir, cfg!(windows))),\n        (None, Some(dir)) => Some(conda_env_interpreter(&dir, cfg!(windows))),\n        (Some(_), Some(_)) => {\n            warn!(\n                \"Both VIRTUAL_ENV and CONDA_PREFIX are set. PyO3 will ignore both of these for \\\n                 locating the Python interpreter until you unset one of them.\"\n            );\n            None\n        }\n        (None, None) => None,\n    }\n}\n\n/// Attempts to locate a python interpreter.\n///\n/// Locations are checked in the order listed:\n///   1. If `PYO3_PYTHON` is set, this interpreter is used.\n///   2. If in a virtualenv, that environment's interpreter is used.\n///   3. `python`, if this is functional a Python 3.x interpreter\n///   4. `python3`, as above\npub fn find_interpreter() -> Result<PathBuf> {\n    // Trigger rebuilds when `PYO3_ENVIRONMENT_SIGNATURE` env var value changes\n    // See https://github.com/PyO3/pyo3/issues/2724\n    println!(\"cargo:rerun-if-env-changed=PYO3_ENVIRONMENT_SIGNATURE\");\n\n    if let Some(exe) = env_var(\"PYO3_PYTHON\") {\n        Ok(exe.into())\n    } else if let Some(env_interpreter) = get_env_interpreter() {\n        Ok(env_interpreter)\n    } else {\n        println!(\"cargo:rerun-if-env-changed=PATH\");\n        [\"python\", \"python3\"]\n            .iter()\n            .find(|bin| {\n                if let Ok(out) = Command::new(bin).arg(\"--version\").output() {\n                    // begin with `Python 3.X.X :: additional info`\n                    out.stdout.starts_with(b\"Python 3\")\n                        || out.stderr.starts_with(b\"Python 3\")\n                        || out.stdout.starts_with(b\"GraalPy 3\")\n                } else {\n                    false\n                }\n            })\n            .map(PathBuf::from)\n            .ok_or_else(|| \"no Python 3.x interpreter found\".into())\n    }\n}\n\n/// Locates and extracts the build host Python interpreter configuration.\n///\n/// Lowers the configured Python version to `abi3_version` if required.\nfn get_host_interpreter(abi3_version: Option<PythonVersion>) -> Result<InterpreterConfig> {\n    let interpreter_path = find_interpreter()?;\n\n    let mut interpreter_config = InterpreterConfig::from_interpreter(interpreter_path)?;\n    interpreter_config.fixup_for_abi3_version(abi3_version)?;\n\n    Ok(interpreter_config)\n}\n\n/// Generates an interpreter config suitable for cross-compilation.\n///\n/// This must be called from PyO3's build script, because it relies on environment variables such as\n/// CARGO_CFG_TARGET_OS which aren't available at any other time.\n#[allow(dead_code)]\npub fn make_cross_compile_config() -> Result<Option<InterpreterConfig>> {\n    let interpreter_config = if let Some(cross_config) = cross_compiling_from_cargo_env()? {\n        let mut interpreter_config = load_cross_compile_config(cross_config)?;\n        interpreter_config.fixup_for_abi3_version(get_abi3_version())?;\n        Some(interpreter_config)\n    } else {\n        None\n    };\n\n    Ok(interpreter_config)\n}\n\n/// Generates an interpreter config which will be hard-coded into the pyo3-build-config crate.\n/// Only used by `pyo3-build-config` build script.\n#[allow(dead_code, unused_mut)]\npub fn make_interpreter_config() -> Result<InterpreterConfig> {\n    let host = Triple::host();\n    let abi3_version = get_abi3_version();\n\n    // See if we can safely skip the Python interpreter configuration detection.\n    // Unix \"abi3\" extension modules can usually be built without any interpreter.\n    let need_interpreter = abi3_version.is_none() || require_libdir_for_target(&host);\n\n    if have_python_interpreter() {\n        match get_host_interpreter(abi3_version) {\n            Ok(interpreter_config) => return Ok(interpreter_config),\n            // Bail if the interpreter configuration is required to build.\n            Err(e) if need_interpreter => return Err(e),\n            _ => {\n                // Fall back to the \"abi3\" defaults just as if `PYO3_NO_PYTHON`\n                // environment variable was set.\n                warn!(\"Compiling without a working Python interpreter.\");\n            }\n        }\n    } else {\n        ensure!(\n            abi3_version.is_some(),\n            \"An abi3-py3* feature must be specified when compiling without a Python interpreter.\"\n        );\n    };\n\n    let interpreter_config = default_abi3_config(&host, abi3_version.unwrap())?;\n\n    Ok(interpreter_config)\n}\n\nfn escape(bytes: &[u8]) -> String {\n    let mut escaped = String::with_capacity(2 * bytes.len());\n\n    for byte in bytes {\n        const LUT: &[u8; 16] = b\"0123456789abcdef\";\n\n        escaped.push(LUT[(byte >> 4) as usize] as char);\n        escaped.push(LUT[(byte & 0x0F) as usize] as char);\n    }\n\n    escaped\n}\n\nfn unescape(escaped: &str) -> Vec<u8> {\n    assert_eq!(escaped.len() % 2, 0, \"invalid hex encoding\");\n\n    let mut bytes = Vec::with_capacity(escaped.len() / 2);\n\n    for chunk in escaped.as_bytes().chunks_exact(2) {\n        fn unhex(hex: u8) -> u8 {\n            match hex {\n                b'a'..=b'f' => hex - b'a' + 10,\n                b'0'..=b'9' => hex - b'0',\n                _ => panic!(\"invalid hex encoding\"),\n            }\n        }\n\n        bytes.push((unhex(chunk[0]) << 4) | unhex(chunk[1]));\n    }\n\n    bytes\n}\n\n#[cfg(test)]\nmod tests {\n    use target_lexicon::triple;\n\n    use super::*;\n\n    #[test]\n    fn test_config_file_roundtrip() {\n        let config = InterpreterConfig {\n            abi3: true,\n            build_flags: BuildFlags::default(),\n            pointer_width: Some(32),\n            executable: Some(\"executable\".into()),\n            implementation: PythonImplementation::CPython,\n            lib_name: Some(\"lib_name\".into()),\n            lib_dir: Some(\"lib_dir\".into()),\n            shared: true,\n            version: MINIMUM_SUPPORTED_VERSION,\n            suppress_build_script_link_lines: true,\n            extra_build_script_lines: vec![\"cargo:test1\".to_string(), \"cargo:test2\".to_string()],\n            python_framework_prefix: None,\n        };\n        let mut buf: Vec<u8> = Vec::new();\n        config.to_writer(&mut buf).unwrap();\n\n        assert_eq!(config, InterpreterConfig::from_reader(&*buf).unwrap());\n\n        // And some different options, for variety\n\n        let config = InterpreterConfig {\n            abi3: false,\n            build_flags: {\n                let mut flags = HashSet::new();\n                flags.insert(BuildFlag::Py_DEBUG);\n                flags.insert(BuildFlag::Other(String::from(\"Py_SOME_FLAG\")));\n                BuildFlags(flags)\n            },\n            pointer_width: None,\n            executable: None,\n            implementation: PythonImplementation::PyPy,\n            lib_dir: None,\n            lib_name: None,\n            shared: true,\n            version: PythonVersion {\n                major: 3,\n                minor: 10,\n            },\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix: None,\n        };\n        let mut buf: Vec<u8> = Vec::new();\n        config.to_writer(&mut buf).unwrap();\n\n        assert_eq!(config, InterpreterConfig::from_reader(&*buf).unwrap());\n    }\n\n    #[test]\n    fn test_config_file_roundtrip_with_escaping() {\n        let config = InterpreterConfig {\n            abi3: true,\n            build_flags: BuildFlags::default(),\n            pointer_width: Some(32),\n            executable: Some(\"executable\".into()),\n            implementation: PythonImplementation::CPython,\n            lib_name: Some(\"lib_name\".into()),\n            lib_dir: Some(\"lib_dir\\\\n\".into()),\n            shared: true,\n            version: MINIMUM_SUPPORTED_VERSION,\n            suppress_build_script_link_lines: true,\n            extra_build_script_lines: vec![\"cargo:test1\".to_string(), \"cargo:test2\".to_string()],\n            python_framework_prefix: None,\n        };\n        let mut buf: Vec<u8> = Vec::new();\n        config.to_writer(&mut buf).unwrap();\n\n        let buf = unescape(&escape(&buf));\n\n        assert_eq!(config, InterpreterConfig::from_reader(&*buf).unwrap());\n    }\n\n    #[test]\n    fn test_config_file_defaults() {\n        // Only version is required\n        assert_eq!(\n            InterpreterConfig::from_reader(\"version=3.7\".as_bytes()).unwrap(),\n            InterpreterConfig {\n                version: PythonVersion { major: 3, minor: 7 },\n                implementation: PythonImplementation::CPython,\n                shared: true,\n                abi3: false,\n                lib_name: None,\n                lib_dir: None,\n                executable: None,\n                pointer_width: None,\n                build_flags: BuildFlags::default(),\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        )\n    }\n\n    #[test]\n    fn test_config_file_unknown_keys() {\n        // ext_suffix is unknown to pyo3-build-config, but it shouldn't error\n        assert_eq!(\n            InterpreterConfig::from_reader(\"version=3.7\\next_suffix=.python37.so\".as_bytes())\n                .unwrap(),\n            InterpreterConfig {\n                version: PythonVersion { major: 3, minor: 7 },\n                implementation: PythonImplementation::CPython,\n                shared: true,\n                abi3: false,\n                lib_name: None,\n                lib_dir: None,\n                executable: None,\n                pointer_width: None,\n                build_flags: BuildFlags::default(),\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        )\n    }\n\n    #[test]\n    fn build_flags_default() {\n        assert_eq!(BuildFlags::default(), BuildFlags::new());\n    }\n\n    #[test]\n    fn build_flags_from_sysconfigdata() {\n        let mut sysconfigdata = Sysconfigdata::new();\n\n        assert_eq!(\n            BuildFlags::from_sysconfigdata(&sysconfigdata).0,\n            HashSet::new()\n        );\n\n        for flag in &BuildFlags::ALL {\n            sysconfigdata.insert(flag.to_string(), \"0\".into());\n        }\n\n        assert_eq!(\n            BuildFlags::from_sysconfigdata(&sysconfigdata).0,\n            HashSet::new()\n        );\n\n        let mut expected_flags = HashSet::new();\n        for flag in &BuildFlags::ALL {\n            sysconfigdata.insert(flag.to_string(), \"1\".into());\n            expected_flags.insert(flag.clone());\n        }\n\n        assert_eq!(\n            BuildFlags::from_sysconfigdata(&sysconfigdata).0,\n            expected_flags\n        );\n    }\n\n    #[test]\n    fn build_flags_fixup() {\n        let mut build_flags = BuildFlags::new();\n\n        build_flags = build_flags.fixup();\n        assert!(build_flags.0.is_empty());\n\n        build_flags.0.insert(BuildFlag::Py_DEBUG);\n\n        build_flags = build_flags.fixup();\n\n        // Py_DEBUG implies Py_REF_DEBUG\n        assert!(build_flags.0.contains(&BuildFlag::Py_REF_DEBUG));\n    }\n\n    #[test]\n    fn parse_script_output() {\n        let output = \"foo bar\\nbar foobar\\n\\n\";\n        let map = super::parse_script_output(output);\n        assert_eq!(map.len(), 2);\n        assert_eq!(map[\"foo\"], \"bar\");\n        assert_eq!(map[\"bar\"], \"foobar\");\n    }\n\n    #[test]\n    fn config_from_interpreter() {\n        // Smoke test to just see whether this works\n        //\n        // PyO3's CI is dependent on Python being installed, so this should be reliable.\n        assert!(make_interpreter_config().is_ok())\n    }\n\n    #[test]\n    fn config_from_empty_sysconfigdata() {\n        let sysconfigdata = Sysconfigdata::new();\n        assert!(InterpreterConfig::from_sysconfigdata(&sysconfigdata).is_err());\n    }\n\n    #[test]\n    fn config_from_sysconfigdata() {\n        let mut sysconfigdata = Sysconfigdata::new();\n        // these are the minimal values required such that InterpreterConfig::from_sysconfigdata\n        // does not error\n        sysconfigdata.insert(\"SOABI\", \"cpython-37m-x86_64-linux-gnu\");\n        sysconfigdata.insert(\"VERSION\", \"3.7\");\n        sysconfigdata.insert(\"Py_ENABLE_SHARED\", \"1\");\n        sysconfigdata.insert(\"LIBDIR\", \"/usr/lib\");\n        sysconfigdata.insert(\"LDVERSION\", \"3.7m\");\n        sysconfigdata.insert(\"SIZEOF_VOID_P\", \"8\");\n        assert_eq!(\n            InterpreterConfig::from_sysconfigdata(&sysconfigdata).unwrap(),\n            InterpreterConfig {\n                abi3: false,\n                build_flags: BuildFlags::from_sysconfigdata(&sysconfigdata),\n                pointer_width: Some(64),\n                executable: None,\n                implementation: PythonImplementation::CPython,\n                lib_dir: Some(\"/usr/lib\".into()),\n                lib_name: Some(\"python3.7m\".into()),\n                shared: true,\n                version: PythonVersion::PY37,\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        );\n    }\n\n    #[test]\n    fn config_from_sysconfigdata_framework() {\n        let mut sysconfigdata = Sysconfigdata::new();\n        sysconfigdata.insert(\"SOABI\", \"cpython-37m-x86_64-linux-gnu\");\n        sysconfigdata.insert(\"VERSION\", \"3.7\");\n        // PYTHONFRAMEWORK should override Py_ENABLE_SHARED\n        sysconfigdata.insert(\"Py_ENABLE_SHARED\", \"0\");\n        sysconfigdata.insert(\"PYTHONFRAMEWORK\", \"Python\");\n        sysconfigdata.insert(\"LIBDIR\", \"/usr/lib\");\n        sysconfigdata.insert(\"LDVERSION\", \"3.7m\");\n        sysconfigdata.insert(\"SIZEOF_VOID_P\", \"8\");\n        assert_eq!(\n            InterpreterConfig::from_sysconfigdata(&sysconfigdata).unwrap(),\n            InterpreterConfig {\n                abi3: false,\n                build_flags: BuildFlags::from_sysconfigdata(&sysconfigdata),\n                pointer_width: Some(64),\n                executable: None,\n                implementation: PythonImplementation::CPython,\n                lib_dir: Some(\"/usr/lib\".into()),\n                lib_name: Some(\"python3.7m\".into()),\n                shared: true,\n                version: PythonVersion::PY37,\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        );\n\n        sysconfigdata = Sysconfigdata::new();\n        sysconfigdata.insert(\"SOABI\", \"cpython-37m-x86_64-linux-gnu\");\n        sysconfigdata.insert(\"VERSION\", \"3.7\");\n        // An empty PYTHONFRAMEWORK means it is not a framework\n        sysconfigdata.insert(\"Py_ENABLE_SHARED\", \"0\");\n        sysconfigdata.insert(\"PYTHONFRAMEWORK\", \"\");\n        sysconfigdata.insert(\"LIBDIR\", \"/usr/lib\");\n        sysconfigdata.insert(\"LDVERSION\", \"3.7m\");\n        sysconfigdata.insert(\"SIZEOF_VOID_P\", \"8\");\n        assert_eq!(\n            InterpreterConfig::from_sysconfigdata(&sysconfigdata).unwrap(),\n            InterpreterConfig {\n                abi3: false,\n                build_flags: BuildFlags::from_sysconfigdata(&sysconfigdata),\n                pointer_width: Some(64),\n                executable: None,\n                implementation: PythonImplementation::CPython,\n                lib_dir: Some(\"/usr/lib\".into()),\n                lib_name: Some(\"python3.7m\".into()),\n                shared: false,\n                version: PythonVersion::PY37,\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        );\n    }\n\n    #[test]\n    fn windows_hardcoded_abi3_compile() {\n        let host = triple!(\"x86_64-pc-windows-msvc\");\n        let min_version = \"3.7\".parse().unwrap();\n\n        assert_eq!(\n            default_abi3_config(&host, min_version).unwrap(),\n            InterpreterConfig {\n                implementation: PythonImplementation::CPython,\n                version: PythonVersion { major: 3, minor: 7 },\n                shared: true,\n                abi3: true,\n                lib_name: Some(\"python3\".into()),\n                lib_dir: None,\n                executable: None,\n                pointer_width: None,\n                build_flags: BuildFlags::default(),\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        );\n    }\n\n    #[test]\n    fn unix_hardcoded_abi3_compile() {\n        let host = triple!(\"x86_64-unknown-linux-gnu\");\n        let min_version = \"3.9\".parse().unwrap();\n\n        assert_eq!(\n            default_abi3_config(&host, min_version).unwrap(),\n            InterpreterConfig {\n                implementation: PythonImplementation::CPython,\n                version: PythonVersion { major: 3, minor: 9 },\n                shared: true,\n                abi3: true,\n                lib_name: None,\n                lib_dir: None,\n                executable: None,\n                pointer_width: None,\n                build_flags: BuildFlags::default(),\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        );\n    }\n\n    #[test]\n    fn windows_hardcoded_cross_compile() {\n        let env_vars = CrossCompileEnvVars {\n            pyo3_cross: None,\n            pyo3_cross_lib_dir: Some(\"C:\\\\some\\\\path\".into()),\n            pyo3_cross_python_implementation: None,\n            pyo3_cross_python_version: Some(\"3.7\".into()),\n        };\n\n        let host = triple!(\"x86_64-unknown-linux-gnu\");\n        let target = triple!(\"i686-pc-windows-msvc\");\n        let cross_config =\n            CrossCompileConfig::try_from_env_vars_host_target(env_vars, &host, &target)\n                .unwrap()\n                .unwrap();\n\n        assert_eq!(\n            default_cross_compile(&cross_config).unwrap(),\n            InterpreterConfig {\n                implementation: PythonImplementation::CPython,\n                version: PythonVersion { major: 3, minor: 7 },\n                shared: true,\n                abi3: false,\n                lib_name: Some(\"python37\".into()),\n                lib_dir: Some(\"C:\\\\some\\\\path\".into()),\n                executable: None,\n                pointer_width: None,\n                build_flags: BuildFlags::default(),\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        );\n    }\n\n    #[test]\n    fn mingw_hardcoded_cross_compile() {\n        let env_vars = CrossCompileEnvVars {\n            pyo3_cross: None,\n            pyo3_cross_lib_dir: Some(\"/usr/lib/mingw\".into()),\n            pyo3_cross_python_implementation: None,\n            pyo3_cross_python_version: Some(\"3.8\".into()),\n        };\n\n        let host = triple!(\"x86_64-unknown-linux-gnu\");\n        let target = triple!(\"i686-pc-windows-gnu\");\n        let cross_config =\n            CrossCompileConfig::try_from_env_vars_host_target(env_vars, &host, &target)\n                .unwrap()\n                .unwrap();\n\n        assert_eq!(\n            default_cross_compile(&cross_config).unwrap(),\n            InterpreterConfig {\n                implementation: PythonImplementation::CPython,\n                version: PythonVersion { major: 3, minor: 8 },\n                shared: true,\n                abi3: false,\n                lib_name: Some(\"python38\".into()),\n                lib_dir: Some(\"/usr/lib/mingw\".into()),\n                executable: None,\n                pointer_width: None,\n                build_flags: BuildFlags::default(),\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        );\n    }\n\n    #[test]\n    fn unix_hardcoded_cross_compile() {\n        let env_vars = CrossCompileEnvVars {\n            pyo3_cross: None,\n            pyo3_cross_lib_dir: Some(\"/usr/arm64/lib\".into()),\n            pyo3_cross_python_implementation: None,\n            pyo3_cross_python_version: Some(\"3.9\".into()),\n        };\n\n        let host = triple!(\"x86_64-unknown-linux-gnu\");\n        let target = triple!(\"aarch64-unknown-linux-gnu\");\n        let cross_config =\n            CrossCompileConfig::try_from_env_vars_host_target(env_vars, &host, &target)\n                .unwrap()\n                .unwrap();\n\n        assert_eq!(\n            default_cross_compile(&cross_config).unwrap(),\n            InterpreterConfig {\n                implementation: PythonImplementation::CPython,\n                version: PythonVersion { major: 3, minor: 9 },\n                shared: true,\n                abi3: false,\n                lib_name: Some(\"python3.9\".into()),\n                lib_dir: Some(\"/usr/arm64/lib\".into()),\n                executable: None,\n                pointer_width: None,\n                build_flags: BuildFlags::default(),\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        );\n    }\n\n    #[test]\n    fn pypy_hardcoded_cross_compile() {\n        let env_vars = CrossCompileEnvVars {\n            pyo3_cross: None,\n            pyo3_cross_lib_dir: None,\n            pyo3_cross_python_implementation: Some(\"PyPy\".into()),\n            pyo3_cross_python_version: Some(\"3.11\".into()),\n        };\n\n        let triple = triple!(\"x86_64-unknown-linux-gnu\");\n        let cross_config =\n            CrossCompileConfig::try_from_env_vars_host_target(env_vars, &triple, &triple)\n                .unwrap()\n                .unwrap();\n\n        assert_eq!(\n            default_cross_compile(&cross_config).unwrap(),\n            InterpreterConfig {\n                implementation: PythonImplementation::PyPy,\n                version: PythonVersion {\n                    major: 3,\n                    minor: 11\n                },\n                shared: true,\n                abi3: false,\n                lib_name: Some(\"pypy3.11-c\".into()),\n                lib_dir: None,\n                executable: None,\n                pointer_width: None,\n                build_flags: BuildFlags::default(),\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        );\n    }\n\n    #[test]\n    fn default_lib_name_windows() {\n        use PythonImplementation::*;\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion { major: 3, minor: 9 },\n                CPython,\n                false,\n                false,\n                false,\n                false,\n            )\n            .unwrap(),\n            \"python39\",\n        );\n        assert!(super::default_lib_name_windows(\n            PythonVersion { major: 3, minor: 9 },\n            CPython,\n            false,\n            false,\n            false,\n            true,\n        )\n        .is_err());\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion { major: 3, minor: 9 },\n                CPython,\n                true,\n                false,\n                false,\n                false,\n            )\n            .unwrap(),\n            \"python3\",\n        );\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion { major: 3, minor: 9 },\n                CPython,\n                false,\n                true,\n                false,\n                false,\n            )\n            .unwrap(),\n            \"python3.9\",\n        );\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion { major: 3, minor: 9 },\n                CPython,\n                true,\n                true,\n                false,\n                false,\n            )\n            .unwrap(),\n            \"python3\",\n        );\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion { major: 3, minor: 9 },\n                PyPy,\n                true,\n                false,\n                false,\n                false,\n            )\n            .unwrap(),\n            \"libpypy3.9-c\",\n        );\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion {\n                    major: 3,\n                    minor: 11\n                },\n                PyPy,\n                false,\n                false,\n                false,\n                false,\n            )\n            .unwrap(),\n            \"libpypy3.11-c\",\n        );\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion { major: 3, minor: 9 },\n                CPython,\n                false,\n                false,\n                true,\n                false,\n            )\n            .unwrap(),\n            \"python39_d\",\n        );\n        // abi3 debug builds on windows use version-specific lib on 3.9 and older\n        // to workaround https://github.com/python/cpython/issues/101614\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion { major: 3, minor: 9 },\n                CPython,\n                true,\n                false,\n                true,\n                false,\n            )\n            .unwrap(),\n            \"python39_d\",\n        );\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion {\n                    major: 3,\n                    minor: 10\n                },\n                CPython,\n                true,\n                false,\n                true,\n                false,\n            )\n            .unwrap(),\n            \"python3_d\",\n        );\n        // Python versions older than 3.13 don't support gil_disabled\n        assert!(super::default_lib_name_windows(\n            PythonVersion {\n                major: 3,\n                minor: 12,\n            },\n            CPython,\n            false,\n            false,\n            false,\n            true,\n        )\n        .is_err());\n        // mingw and free-threading are incompatible (until someone adds support)\n        assert!(super::default_lib_name_windows(\n            PythonVersion {\n                major: 3,\n                minor: 12,\n            },\n            CPython,\n            false,\n            true,\n            false,\n            true,\n        )\n        .is_err());\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion {\n                    major: 3,\n                    minor: 13\n                },\n                CPython,\n                false,\n                false,\n                false,\n                true,\n            )\n            .unwrap(),\n            \"python313t\",\n        );\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion {\n                    major: 3,\n                    minor: 13\n                },\n                CPython,\n                true, // abi3 true should not affect the free-threaded lib name\n                false,\n                false,\n                true,\n            )\n            .unwrap(),\n            \"python313t\",\n        );\n        assert_eq!(\n            super::default_lib_name_windows(\n                PythonVersion {\n                    major: 3,\n                    minor: 13\n                },\n                CPython,\n                false,\n                false,\n                true,\n                true,\n            )\n            .unwrap(),\n            \"python313t_d\",\n        );\n    }\n\n    #[test]\n    fn default_lib_name_unix() {\n        use PythonImplementation::*;\n        // Defaults to python3.7m for CPython 3.7\n        assert_eq!(\n            super::default_lib_name_unix(\n                PythonVersion { major: 3, minor: 7 },\n                CPython,\n                false,\n                false,\n                None,\n                false\n            )\n            .unwrap(),\n            \"python3.7m\",\n        );\n        // Defaults to pythonX.Y for CPython 3.8+\n        assert_eq!(\n            super::default_lib_name_unix(\n                PythonVersion { major: 3, minor: 8 },\n                CPython,\n                false,\n                false,\n                None,\n                false\n            )\n            .unwrap(),\n            \"python3.8\",\n        );\n        assert_eq!(\n            super::default_lib_name_unix(\n                PythonVersion { major: 3, minor: 9 },\n                CPython,\n                false,\n                false,\n                None,\n                false\n            )\n            .unwrap(),\n            \"python3.9\",\n        );\n        // Can use ldversion to override for CPython\n        assert_eq!(\n            super::default_lib_name_unix(\n                PythonVersion { major: 3, minor: 9 },\n                CPython,\n                false,\n                false,\n                Some(\"3.7md\"),\n                false\n            )\n            .unwrap(),\n            \"python3.7md\",\n        );\n\n        // PyPy 3.11 includes ldversion\n        assert_eq!(\n            super::default_lib_name_unix(\n                PythonVersion {\n                    major: 3,\n                    minor: 11\n                },\n                PyPy,\n                false,\n                false,\n                None,\n                false\n            )\n            .unwrap(),\n            \"pypy3.11-c\",\n        );\n\n        assert_eq!(\n            super::default_lib_name_unix(\n                PythonVersion { major: 3, minor: 9 },\n                PyPy,\n                false,\n                false,\n                Some(\"3.11d\"),\n                false\n            )\n            .unwrap(),\n            \"pypy3.11d-c\",\n        );\n\n        // free-threading adds a t suffix\n        assert_eq!(\n            super::default_lib_name_unix(\n                PythonVersion {\n                    major: 3,\n                    minor: 13\n                },\n                CPython,\n                false,\n                false,\n                None,\n                true\n            )\n            .unwrap(),\n            \"python3.13t\",\n        );\n        // 3.12 and older are incompatible with gil_disabled\n        assert!(super::default_lib_name_unix(\n            PythonVersion {\n                major: 3,\n                minor: 12,\n            },\n            CPython,\n            false,\n            false,\n            None,\n            true,\n        )\n        .is_err());\n        // cygwin abi3 links to unversioned libpython\n        assert_eq!(\n            super::default_lib_name_unix(\n                PythonVersion {\n                    major: 3,\n                    minor: 13\n                },\n                CPython,\n                true,\n                true,\n                None,\n                false\n            )\n            .unwrap(),\n            \"python3\",\n        );\n    }\n\n    #[test]\n    fn parse_cross_python_version() {\n        let env_vars = CrossCompileEnvVars {\n            pyo3_cross: None,\n            pyo3_cross_lib_dir: None,\n            pyo3_cross_python_version: Some(\"3.9\".into()),\n            pyo3_cross_python_implementation: None,\n        };\n\n        assert_eq!(\n            env_vars.parse_version().unwrap(),\n            (Some(PythonVersion { major: 3, minor: 9 }), None),\n        );\n\n        let env_vars = CrossCompileEnvVars {\n            pyo3_cross: None,\n            pyo3_cross_lib_dir: None,\n            pyo3_cross_python_version: None,\n            pyo3_cross_python_implementation: None,\n        };\n\n        assert_eq!(env_vars.parse_version().unwrap(), (None, None));\n\n        let env_vars = CrossCompileEnvVars {\n            pyo3_cross: None,\n            pyo3_cross_lib_dir: None,\n            pyo3_cross_python_version: Some(\"3.13t\".into()),\n            pyo3_cross_python_implementation: None,\n        };\n\n        assert_eq!(\n            env_vars.parse_version().unwrap(),\n            (\n                Some(PythonVersion {\n                    major: 3,\n                    minor: 13\n                }),\n                Some(\"t\".into())\n            ),\n        );\n\n        let env_vars = CrossCompileEnvVars {\n            pyo3_cross: None,\n            pyo3_cross_lib_dir: None,\n            pyo3_cross_python_version: Some(\"100\".into()),\n            pyo3_cross_python_implementation: None,\n        };\n\n        assert!(env_vars.parse_version().is_err());\n    }\n\n    #[test]\n    fn interpreter_version_reduced_to_abi3() {\n        let mut config = InterpreterConfig {\n            abi3: true,\n            build_flags: BuildFlags::default(),\n            pointer_width: None,\n            executable: None,\n            implementation: PythonImplementation::CPython,\n            lib_dir: None,\n            lib_name: None,\n            shared: true,\n            version: PythonVersion { major: 3, minor: 7 },\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix: None,\n        };\n\n        config\n            .fixup_for_abi3_version(Some(PythonVersion { major: 3, minor: 7 }))\n            .unwrap();\n        assert_eq!(config.version, PythonVersion { major: 3, minor: 7 });\n    }\n\n    #[test]\n    fn abi3_version_cannot_be_higher_than_interpreter() {\n        let mut config = InterpreterConfig {\n            abi3: true,\n            build_flags: BuildFlags::new(),\n            pointer_width: None,\n            executable: None,\n            implementation: PythonImplementation::CPython,\n            lib_dir: None,\n            lib_name: None,\n            shared: true,\n            version: PythonVersion { major: 3, minor: 7 },\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix: None,\n        };\n\n        assert!(config\n            .fixup_for_abi3_version(Some(PythonVersion { major: 3, minor: 8 }))\n            .unwrap_err()\n            .to_string()\n            .contains(\n                \"cannot set a minimum Python version 3.8 higher than the interpreter version 3.7\"\n            ));\n    }\n\n    #[test]\n    #[cfg(all(\n        target_os = \"linux\",\n        target_arch = \"x86_64\",\n        feature = \"resolve-config\"\n    ))]\n    fn parse_sysconfigdata() {\n        // A best effort attempt to get test coverage for the sysconfigdata parsing.\n        // Might not complete successfully depending on host installation; that's ok as long as\n        // CI demonstrates this path is covered!\n\n        let interpreter_config = crate::get();\n\n        let lib_dir = match &interpreter_config.lib_dir {\n            Some(lib_dir) => Path::new(lib_dir),\n            // Don't know where to search for sysconfigdata; never mind.\n            None => return,\n        };\n\n        let cross = CrossCompileConfig {\n            lib_dir: Some(lib_dir.into()),\n            version: Some(interpreter_config.version),\n            implementation: Some(interpreter_config.implementation),\n            target: triple!(\"x86_64-unknown-linux-gnu\"),\n            abiflags: if interpreter_config.is_free_threaded() {\n                Some(\"t\".into())\n            } else {\n                None\n            },\n        };\n\n        let sysconfigdata_path = match find_sysconfigdata(&cross) {\n            Ok(Some(path)) => path,\n            // Couldn't find a matching sysconfigdata; never mind!\n            _ => return,\n        };\n        let sysconfigdata = super::parse_sysconfigdata(sysconfigdata_path).unwrap();\n        let parsed_config = InterpreterConfig::from_sysconfigdata(&sysconfigdata).unwrap();\n\n        assert_eq!(\n            parsed_config,\n            InterpreterConfig {\n                abi3: false,\n                build_flags: BuildFlags(interpreter_config.build_flags.0.clone()),\n                pointer_width: Some(64),\n                executable: None,\n                implementation: PythonImplementation::CPython,\n                lib_dir: interpreter_config.lib_dir.to_owned(),\n                lib_name: interpreter_config.lib_name.to_owned(),\n                shared: true,\n                version: interpreter_config.version,\n                suppress_build_script_link_lines: false,\n                extra_build_script_lines: vec![],\n                python_framework_prefix: None,\n            }\n        )\n    }\n\n    #[test]\n    fn test_venv_interpreter() {\n        let base = OsStr::new(\"base\");\n        assert_eq!(\n            venv_interpreter(base, true),\n            PathBuf::from_iter(&[\"base\", \"Scripts\", \"python.exe\"])\n        );\n        assert_eq!(\n            venv_interpreter(base, false),\n            PathBuf::from_iter(&[\"base\", \"bin\", \"python\"])\n        );\n    }\n\n    #[test]\n    fn test_conda_env_interpreter() {\n        let base = OsStr::new(\"base\");\n        assert_eq!(\n            conda_env_interpreter(base, true),\n            PathBuf::from_iter(&[\"base\", \"python.exe\"])\n        );\n        assert_eq!(\n            conda_env_interpreter(base, false),\n            PathBuf::from_iter(&[\"base\", \"bin\", \"python\"])\n        );\n    }\n\n    #[test]\n    fn test_not_cross_compiling_from_to() {\n        assert!(cross_compiling_from_to(\n            &triple!(\"x86_64-unknown-linux-gnu\"),\n            &triple!(\"x86_64-unknown-linux-gnu\"),\n        )\n        .unwrap()\n        .is_none());\n\n        assert!(cross_compiling_from_to(\n            &triple!(\"x86_64-apple-darwin\"),\n            &triple!(\"x86_64-apple-darwin\")\n        )\n        .unwrap()\n        .is_none());\n\n        assert!(cross_compiling_from_to(\n            &triple!(\"aarch64-apple-darwin\"),\n            &triple!(\"x86_64-apple-darwin\")\n        )\n        .unwrap()\n        .is_none());\n\n        assert!(cross_compiling_from_to(\n            &triple!(\"x86_64-apple-darwin\"),\n            &triple!(\"aarch64-apple-darwin\")\n        )\n        .unwrap()\n        .is_none());\n\n        assert!(cross_compiling_from_to(\n            &triple!(\"x86_64-pc-windows-msvc\"),\n            &triple!(\"i686-pc-windows-msvc\")\n        )\n        .unwrap()\n        .is_none());\n\n        assert!(cross_compiling_from_to(\n            &triple!(\"x86_64-unknown-linux-gnu\"),\n            &triple!(\"x86_64-unknown-linux-musl\")\n        )\n        .unwrap()\n        .is_none());\n\n        assert!(cross_compiling_from_to(\n            &triple!(\"x86_64-pc-windows-msvc\"),\n            &triple!(\"x86_64-win7-windows-msvc\"),\n        )\n        .unwrap()\n        .is_none());\n    }\n\n    #[test]\n    fn test_is_cross_compiling_from_to() {\n        assert!(cross_compiling_from_to(\n            &triple!(\"x86_64-pc-windows-msvc\"),\n            &triple!(\"aarch64-pc-windows-msvc\")\n        )\n        .unwrap()\n        .is_some());\n    }\n\n    #[test]\n    fn test_run_python_script() {\n        // as above, this should be okay in CI where Python is presumed installed\n        let interpreter = make_interpreter_config()\n            .expect(\"could not get InterpreterConfig from installed interpreter\");\n        let out = interpreter\n            .run_python_script(\"print(2 + 2)\")\n            .expect(\"failed to run Python script\");\n        assert_eq!(out.trim_end(), \"4\");\n    }\n\n    #[test]\n    fn test_run_python_script_with_envs() {\n        // as above, this should be okay in CI where Python is presumed installed\n        let interpreter = make_interpreter_config()\n            .expect(\"could not get InterpreterConfig from installed interpreter\");\n        let out = interpreter\n            .run_python_script_with_envs(\n                \"import os; print(os.getenv('PYO3_TEST'))\",\n                vec![(\"PYO3_TEST\", \"42\")],\n            )\n            .expect(\"failed to run Python script\");\n        assert_eq!(out.trim_end(), \"42\");\n    }\n\n    #[test]\n    fn test_build_script_outputs_base() {\n        let interpreter_config = InterpreterConfig {\n            implementation: PythonImplementation::CPython,\n            version: PythonVersion {\n                major: 3,\n                minor: 11,\n            },\n            shared: true,\n            abi3: false,\n            lib_name: Some(\"python3\".into()),\n            lib_dir: None,\n            executable: None,\n            pointer_width: None,\n            build_flags: BuildFlags::default(),\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix: None,\n        };\n        assert_eq!(\n            interpreter_config.build_script_outputs(),\n            [\n                \"cargo:rustc-cfg=Py_3_7\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_8\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_9\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_10\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_11\".to_owned(),\n            ]\n        );\n\n        let interpreter_config = InterpreterConfig {\n            implementation: PythonImplementation::PyPy,\n            ..interpreter_config\n        };\n        assert_eq!(\n            interpreter_config.build_script_outputs(),\n            [\n                \"cargo:rustc-cfg=Py_3_7\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_8\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_9\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_10\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_11\".to_owned(),\n                \"cargo:rustc-cfg=PyPy\".to_owned(),\n            ]\n        );\n    }\n\n    #[test]\n    fn test_build_script_outputs_abi3() {\n        let interpreter_config = InterpreterConfig {\n            implementation: PythonImplementation::CPython,\n            version: PythonVersion { major: 3, minor: 9 },\n            shared: true,\n            abi3: true,\n            lib_name: Some(\"python3\".into()),\n            lib_dir: None,\n            executable: None,\n            pointer_width: None,\n            build_flags: BuildFlags::default(),\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix: None,\n        };\n\n        assert_eq!(\n            interpreter_config.build_script_outputs(),\n            [\n                \"cargo:rustc-cfg=Py_3_7\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_8\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_9\".to_owned(),\n                \"cargo:rustc-cfg=Py_LIMITED_API\".to_owned(),\n            ]\n        );\n\n        let interpreter_config = InterpreterConfig {\n            implementation: PythonImplementation::PyPy,\n            ..interpreter_config\n        };\n        assert_eq!(\n            interpreter_config.build_script_outputs(),\n            [\n                \"cargo:rustc-cfg=Py_3_7\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_8\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_9\".to_owned(),\n                \"cargo:rustc-cfg=PyPy\".to_owned(),\n                \"cargo:rustc-cfg=Py_LIMITED_API\".to_owned(),\n            ]\n        );\n    }\n\n    #[test]\n    fn test_build_script_outputs_gil_disabled() {\n        let mut build_flags = BuildFlags::default();\n        build_flags.0.insert(BuildFlag::Py_GIL_DISABLED);\n        let interpreter_config = InterpreterConfig {\n            implementation: PythonImplementation::CPython,\n            version: PythonVersion {\n                major: 3,\n                minor: 13,\n            },\n            shared: true,\n            abi3: false,\n            lib_name: Some(\"python3\".into()),\n            lib_dir: None,\n            executable: None,\n            pointer_width: None,\n            build_flags,\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix: None,\n        };\n\n        assert_eq!(\n            interpreter_config.build_script_outputs(),\n            [\n                \"cargo:rustc-cfg=Py_3_7\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_8\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_9\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_10\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_11\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_12\".to_owned(),\n                \"cargo:rustc-cfg=Py_3_13\".to_owned(),\n                \"cargo:rustc-cfg=Py_GIL_DISABLED\".to_owned(),\n            ]\n        );\n    }\n\n    #[test]\n    fn test_build_script_outputs_debug() {\n        let mut build_flags = BuildFlags::default();\n        build_flags.0.insert(BuildFlag::Py_DEBUG);\n        let interpreter_config = InterpreterConfig {\n            implementation: PythonImplementation::CPython,\n            version: PythonVersion { major: 3, minor: 7 },\n            shared: true,\n            abi3: false,\n            lib_name: Some(\"python3\".into()),\n            lib_dir: None,\n            executable: None,\n            pointer_width: None,\n            build_flags,\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix: None,\n        };\n\n        assert_eq!(\n            interpreter_config.build_script_outputs(),\n            [\n                \"cargo:rustc-cfg=Py_3_7\".to_owned(),\n                \"cargo:rustc-cfg=py_sys_config=\\\"Py_DEBUG\\\"\".to_owned(),\n            ]\n        );\n    }\n\n    #[test]\n    fn test_find_sysconfigdata_in_invalid_lib_dir() {\n        let e = find_all_sysconfigdata(&CrossCompileConfig {\n            lib_dir: Some(PathBuf::from(\"/abc/123/not/a/real/path\")),\n            version: None,\n            implementation: None,\n            target: triple!(\"x86_64-unknown-linux-gnu\"),\n            abiflags: None,\n        })\n        .unwrap_err();\n\n        // actual error message is platform-dependent, so just check the context we add\n        assert!(e.report().to_string().starts_with(\n            \"failed to search the lib dir at 'PYO3_CROSS_LIB_DIR=/abc/123/not/a/real/path'\\n\\\n            caused by:\\n  \\\n              - 0: failed to list the entries in '/abc/123/not/a/real/path'\\n  \\\n              - 1: \\\n            \"\n        ));\n    }\n\n    #[test]\n    fn test_from_pyo3_config_file_env_rebuild() {\n        READ_ENV_VARS.with(|vars| vars.borrow_mut().clear());\n        let _ = InterpreterConfig::from_pyo3_config_file_env();\n        // it's possible that other env vars were also read, hence just checking for contains\n        READ_ENV_VARS.with(|vars| assert!(vars.borrow().contains(&\"PYO3_CONFIG_FILE\".to_string())));\n    }\n\n    #[test]\n    fn test_apply_default_lib_name_to_config_file() {\n        let mut config = InterpreterConfig {\n            implementation: PythonImplementation::CPython,\n            version: PythonVersion { major: 3, minor: 9 },\n            shared: true,\n            abi3: false,\n            lib_name: None,\n            lib_dir: None,\n            executable: None,\n            pointer_width: None,\n            build_flags: BuildFlags::default(),\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix: None,\n        };\n\n        let unix = Triple::from_str(\"x86_64-unknown-linux-gnu\").unwrap();\n        let win_x64 = Triple::from_str(\"x86_64-pc-windows-msvc\").unwrap();\n        let win_arm64 = Triple::from_str(\"aarch64-pc-windows-msvc\").unwrap();\n\n        config.apply_default_lib_name_to_config_file(&unix);\n        assert_eq!(config.lib_name, Some(\"python3.9\".into()));\n\n        config.lib_name = None;\n        config.apply_default_lib_name_to_config_file(&win_x64);\n        assert_eq!(config.lib_name, Some(\"python39\".into()));\n\n        config.lib_name = None;\n        config.apply_default_lib_name_to_config_file(&win_arm64);\n        assert_eq!(config.lib_name, Some(\"python39\".into()));\n\n        // PyPy\n        config.implementation = PythonImplementation::PyPy;\n        config.version = PythonVersion {\n            major: 3,\n            minor: 11,\n        };\n        config.lib_name = None;\n        config.apply_default_lib_name_to_config_file(&unix);\n        assert_eq!(config.lib_name, Some(\"pypy3.11-c\".into()));\n\n        config.lib_name = None;\n        config.apply_default_lib_name_to_config_file(&win_x64);\n        assert_eq!(config.lib_name, Some(\"libpypy3.11-c\".into()));\n\n        config.implementation = PythonImplementation::CPython;\n\n        // Free-threaded\n        config.build_flags.0.insert(BuildFlag::Py_GIL_DISABLED);\n        config.version = PythonVersion {\n            major: 3,\n            minor: 13,\n        };\n        config.lib_name = None;\n        config.apply_default_lib_name_to_config_file(&unix);\n        assert_eq!(config.lib_name, Some(\"python3.13t\".into()));\n\n        config.lib_name = None;\n        config.apply_default_lib_name_to_config_file(&win_x64);\n        assert_eq!(config.lib_name, Some(\"python313t\".into()));\n\n        config.lib_name = None;\n        config.apply_default_lib_name_to_config_file(&win_arm64);\n        assert_eq!(config.lib_name, Some(\"python313t\".into()));\n\n        config.build_flags.0.remove(&BuildFlag::Py_GIL_DISABLED);\n\n        // abi3\n        config.abi3 = true;\n        config.lib_name = None;\n        config.apply_default_lib_name_to_config_file(&unix);\n        assert_eq!(config.lib_name, Some(\"python3.13\".into()));\n\n        config.lib_name = None;\n        config.apply_default_lib_name_to_config_file(&win_x64);\n        assert_eq!(config.lib_name, Some(\"python3\".into()));\n\n        config.lib_name = None;\n        config.apply_default_lib_name_to_config_file(&win_arm64);\n        assert_eq!(config.lib_name, Some(\"python3\".into()));\n    }\n}\n"
  },
  {
    "path": "pyo3-build-config/src/lib.rs",
    "content": "//! Configuration used by PyO3 for conditional support of varying Python versions.\n//!\n//! This crate exposes functionality to be called from build scripts to simplify building crates\n//! which depend on PyO3.\n//!\n//! It used internally by the PyO3 crate's build script to apply the same configuration.\n\n#![warn(elided_lifetimes_in_paths, unused_lifetimes)]\n\nmod errors;\nmod impl_;\n\n#[cfg(feature = \"resolve-config\")]\nuse std::{\n    io::Cursor,\n    path::{Path, PathBuf},\n};\n\nuse std::{env, process::Command, str::FromStr, sync::OnceLock};\n\npub use impl_::{\n    cross_compiling_from_to, find_all_sysconfigdata, parse_sysconfigdata, BuildFlag, BuildFlags,\n    CrossCompileConfig, InterpreterConfig, PythonImplementation, PythonVersion, Triple,\n};\n\nuse target_lexicon::OperatingSystem;\n\n/// Adds all the [`#[cfg]` flags](index.html) to the current compilation.\n///\n/// This should be called from a build script.\n///\n/// The full list of attributes added are the following:\n///\n/// | Flag | Description |\n/// | ---- | ----------- |\n/// | `#[cfg(Py_3_7)]`, `#[cfg(Py_3_8)]`, `#[cfg(Py_3_9)]`, `#[cfg(Py_3_10)]` | These attributes mark code only for a given Python version and up. For example, `#[cfg(Py_3_7)]` marks code which can run on Python 3.7 **and newer**. |\n/// | `#[cfg(Py_LIMITED_API)]` | This marks code which is run when compiling with PyO3's `abi3` feature enabled. |\n/// | `#[cfg(Py_GIL_DISABLED)]` | This marks code which is run on the free-threaded interpreter. |\n/// | `#[cfg(PyPy)]` | This marks code which is run when compiling for PyPy. |\n/// | `#[cfg(GraalPy)]` | This marks code which is run when compiling for GraalPy. |\n///\n/// For examples of how to use these attributes,\n#[doc = concat!(\"[see PyO3's guide](https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/building-and-distribution/multiple_python_versions.html)\")]\n/// .\n#[cfg(feature = \"resolve-config\")]\npub fn use_pyo3_cfgs() {\n    print_expected_cfgs();\n    for cargo_command in get().build_script_outputs() {\n        println!(\"{cargo_command}\")\n    }\n}\n\n/// Adds linker arguments suitable for linking an extension module.\n///\n/// This should be called from a build script.\n///\n/// The following link flags are added:\n/// - macOS: `-undefined dynamic_lookup`\n/// - wasm32-unknown-emscripten: for Rust <= 1.95, `-sSIDE_MODULE=2 -sWASM_BIGINT`\n///\n/// All other platforms currently are no-ops, however this may change as necessary\n/// in future.\npub fn add_extension_module_link_args() {\n    _add_extension_module_link_args(\n        &impl_::target_triple_from_env(),\n        std::io::stdout(),\n        rustc_minor_version(),\n    )\n}\n\nfn _add_extension_module_link_args(\n    triple: &Triple,\n    mut writer: impl std::io::Write,\n    rustc_minor_version: Option<u32>,\n) {\n    if matches!(triple.operating_system, OperatingSystem::Darwin(_)) {\n        writeln!(writer, \"cargo:rustc-cdylib-link-arg=-undefined\").unwrap();\n        writeln!(writer, \"cargo:rustc-cdylib-link-arg=dynamic_lookup\").unwrap();\n    } else if triple == &Triple::from_str(\"wasm32-unknown-emscripten\").unwrap()\n        && rustc_minor_version.is_some_and(|version| version < 95)\n    {\n        writeln!(writer, \"cargo:rustc-cdylib-link-arg=-sSIDE_MODULE=2\").unwrap();\n        writeln!(writer, \"cargo:rustc-cdylib-link-arg=-sWASM_BIGINT\").unwrap();\n    }\n}\n\n/// Adds linker arguments to set rpath when embedding Python within a Rust binary.\n///\n/// When running tests or binaries built with PyO3, the Python dynamic library needs\n/// to be found at runtime.\n///\n/// This can be done by setting environment variables like `DYLD_LIBRARY_PATH` on macOS,\n/// `LD_LIBRARY_PATH` on Linux, or `PATH` on Windows.\n///\n/// Altrnatively (as per this function) rpath can be set at link time to point to the\n/// directory containing the Python dynamic library. This avoids the need to set environment\n/// variables, so can be convenient, however may not be appropriate for binaries packaged\n/// for distribution.\n///\n#[doc = concat!(\"[See PyO3's guide](https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/building-and-distribution#dynamically-embedding-the-python-interpreter)\")]\n/// for more details.\n#[cfg(feature = \"resolve-config\")]\npub fn add_libpython_rpath_link_args() {\n    let target = impl_::target_triple_from_env();\n    _add_libpython_rpath_link_args(\n        get(),\n        impl_::is_linking_libpython_for_target(&target),\n        std::io::stdout(),\n    )\n}\n\n#[cfg(feature = \"resolve-config\")]\nfn _add_libpython_rpath_link_args(\n    interpreter_config: &InterpreterConfig,\n    is_linking_libpython: bool,\n    mut writer: impl std::io::Write,\n) {\n    if is_linking_libpython {\n        if let Some(lib_dir) = interpreter_config.lib_dir.as_ref() {\n            writeln!(writer, \"cargo:rustc-link-arg=-Wl,-rpath,{lib_dir}\").unwrap();\n        }\n    }\n}\n\n/// Adds linker arguments suitable for linking against the Python framework on macOS.\n///\n/// This should be called from a build script.\n///\n/// The following link flags are added:\n/// - macOS: `-Wl,-rpath,<framework_prefix>`\n///\n/// All other platforms currently are no-ops.\n#[cfg(feature = \"resolve-config\")]\npub fn add_python_framework_link_args() {\n    let target = impl_::target_triple_from_env();\n    _add_python_framework_link_args(\n        get(),\n        &target,\n        impl_::is_linking_libpython_for_target(&target),\n        std::io::stdout(),\n    )\n}\n\n#[cfg(feature = \"resolve-config\")]\nfn _add_python_framework_link_args(\n    interpreter_config: &InterpreterConfig,\n    triple: &Triple,\n    link_libpython: bool,\n    mut writer: impl std::io::Write,\n) {\n    if matches!(triple.operating_system, OperatingSystem::Darwin(_)) && link_libpython {\n        if let Some(framework_prefix) = interpreter_config.python_framework_prefix.as_ref() {\n            writeln!(writer, \"cargo:rustc-link-arg=-Wl,-rpath,{framework_prefix}\").unwrap();\n        }\n    }\n}\n\n/// Loads the configuration determined from the build environment.\n///\n/// Because this will never change in a given compilation run, this is cached in a `OnceLock`.\n#[cfg(feature = \"resolve-config\")]\npub fn get() -> &'static InterpreterConfig {\n    static CONFIG: OnceLock<InterpreterConfig> = OnceLock::new();\n    CONFIG.get_or_init(|| {\n        // Check if we are in a build script and cross compiling to a different target.\n        let cross_compile_config_path = resolve_cross_compile_config_path();\n        let cross_compiling = cross_compile_config_path\n            .as_ref()\n            .map(|path| path.exists())\n            .unwrap_or(false);\n\n        #[allow(\n            clippy::const_is_empty,\n            reason = \"CONFIG_FILE is generated in build.rs, content can vary\"\n        )]\n        if let Some(interpreter_config) = InterpreterConfig::from_cargo_dep_env() {\n            interpreter_config\n        } else if let Some(interpreter_config) = config_from_pyo3_config_file_env() {\n            Ok(interpreter_config)\n        } else if cross_compiling {\n            InterpreterConfig::from_path(cross_compile_config_path.as_ref().unwrap())\n        } else {\n            InterpreterConfig::from_reader(Cursor::new(HOST_CONFIG))\n        }\n        .expect(\"failed to parse PyO3 config\")\n    })\n}\n\n/// Build configuration provided by `PYO3_CONFIG_FILE`, inlined into the `pyo3-build-config` binary.\n#[cfg(feature = \"resolve-config\")]\nfn config_from_pyo3_config_file_env() -> Option<InterpreterConfig> {\n    #[doc(hidden)]\n    const CONFIG_FILE: &str = include_str!(concat!(env!(\"OUT_DIR\"), \"/pyo3-build-config-file.txt\"));\n\n    #[allow(\n        clippy::const_is_empty,\n        reason = \"CONFIG_FILE is generated in build.rs, content can vary\"\n    )]\n    if !CONFIG_FILE.is_empty() {\n        let config = InterpreterConfig::from_reader(Cursor::new(CONFIG_FILE))\n            .expect(\"contents of CONFIG_FILE should always be valid (generated by pyo3-build-config's build.rs)\");\n        Some(config)\n    } else {\n        None\n    }\n}\n\n/// Build configuration discovered by `pyo3-build-config` build script. Not aware of\n/// cross-compilation settings. Not generated if `PYO3_CONFIG_FILE` is set.\n#[doc(hidden)]\n#[cfg(feature = \"resolve-config\")]\nconst HOST_CONFIG: &str = include_str!(concat!(env!(\"OUT_DIR\"), \"/pyo3-build-config.txt\"));\n\n/// Returns the path where PyO3's build.rs writes its cross compile configuration.\n///\n/// The config file will be named `$OUT_DIR/<triple>/pyo3-build-config.txt`.\n///\n/// Must be called from a build script, returns `None` if not.\n#[doc(hidden)]\n#[cfg(feature = \"resolve-config\")]\nfn resolve_cross_compile_config_path() -> Option<PathBuf> {\n    env::var_os(\"TARGET\").map(|target| {\n        let mut path = PathBuf::from(env!(\"OUT_DIR\"));\n        path.push(Path::new(&target));\n        path.push(\"pyo3-build-config.txt\");\n        path\n    })\n}\n\n/// Helper to print a feature cfg with a minimum rust version required.\nfn print_feature_cfg(minor_version_required: u32, cfg: &str) {\n    let minor_version = rustc_minor_version().unwrap_or(0);\n\n    if minor_version >= minor_version_required {\n        println!(\"cargo:rustc-cfg={cfg}\");\n    }\n\n    // rustc 1.80.0 stabilized `rustc-check-cfg` feature, don't emit before\n    if minor_version >= 80 {\n        println!(\"cargo:rustc-check-cfg=cfg({cfg})\");\n    }\n}\n\n/// Use certain features if we detect the compiler being used supports them.\n///\n/// Features may be removed or added as MSRV gets bumped or new features become available,\n/// so this function is unstable.\n#[doc(hidden)]\npub fn print_feature_cfgs() {\n    print_feature_cfg(85, \"fn_ptr_eq\");\n    print_feature_cfg(86, \"from_bytes_with_nul_error\");\n}\n\n/// Registers `pyo3`s config names as reachable cfg expressions\n///\n/// - <https://github.com/rust-lang/cargo/pull/13571>\n/// - <https://doc.rust-lang.org/nightly/cargo/reference/build-scripts.html#rustc-check-cfg>\n#[doc(hidden)]\npub fn print_expected_cfgs() {\n    if rustc_minor_version().is_some_and(|version| version < 80) {\n        // rustc 1.80.0 stabilized `rustc-check-cfg` feature, don't emit before\n        return;\n    }\n\n    println!(\"cargo:rustc-check-cfg=cfg(Py_LIMITED_API)\");\n    println!(\"cargo:rustc-check-cfg=cfg(Py_GIL_DISABLED)\");\n    println!(\"cargo:rustc-check-cfg=cfg(PyPy)\");\n    println!(\"cargo:rustc-check-cfg=cfg(GraalPy)\");\n    println!(\"cargo:rustc-check-cfg=cfg(py_sys_config, values(\\\"Py_DEBUG\\\", \\\"Py_REF_DEBUG\\\", \\\"Py_TRACE_REFS\\\", \\\"COUNT_ALLOCS\\\"))\");\n    println!(\"cargo:rustc-check-cfg=cfg(pyo3_disable_reference_pool)\");\n    println!(\"cargo:rustc-check-cfg=cfg(pyo3_leak_on_drop_without_reference_pool)\");\n\n    // allow `Py_3_*` cfgs from the minimum supported version up to the\n    // maximum minor version (+1 for development for the next)\n    for i in impl_::MINIMUM_SUPPORTED_VERSION.minor..=impl_::ABI3_MAX_MINOR + 1 {\n        println!(\"cargo:rustc-check-cfg=cfg(Py_3_{i})\");\n    }\n\n    // pyo3_dll cfg for raw-dylib linking on Windows\n    let mut dll_names = vec![\"python3\".to_string(), \"python3_d\".to_string()];\n    for i in impl_::MINIMUM_SUPPORTED_VERSION.minor..=impl_::ABI3_MAX_MINOR + 1 {\n        dll_names.push(format!(\"python3{i}\"));\n        dll_names.push(format!(\"python3{i}_d\"));\n        if i >= 13 {\n            dll_names.push(format!(\"python3{i}t\"));\n            dll_names.push(format!(\"python3{i}t_d\"));\n        }\n    }\n    // PyPy DLL names (libpypy3.X-c.dll)\n    for i in\n        impl_::MINIMUM_SUPPORTED_VERSION_PYPY.minor..=impl_::MAXIMUM_SUPPORTED_VERSION_PYPY.minor\n    {\n        dll_names.push(format!(\"libpypy3.{i}-c\"));\n    }\n    let values = dll_names\n        .iter()\n        .map(|n| format!(\"\\\"{n}\\\"\"))\n        .collect::<Vec<_>>()\n        .join(\", \");\n    println!(\"cargo:rustc-check-cfg=cfg(pyo3_dll, values({values}))\");\n}\n\n/// Private exports used in PyO3's build.rs\n///\n/// Please don't use these - they could change at any time.\n#[doc(hidden)]\n#[cfg(feature = \"resolve-config\")]\npub mod pyo3_build_script_impl {\n    use crate::errors::{Context, Result};\n\n    use super::*;\n\n    pub mod errors {\n        pub use crate::errors::*;\n    }\n    pub use crate::impl_::{\n        cargo_env_var, env_var, is_linking_libpython_for_target, make_cross_compile_config,\n        target_triple_from_env, InterpreterConfig, PythonVersion,\n    };\n    pub enum BuildConfigSource {\n        /// Config was provided by `PYO3_CONFIG_FILE`.\n        ConfigFile,\n        /// Config was found by an interpreter on the host system.\n        Host,\n        /// Config was configured by cross-compilation settings.\n        CrossCompile,\n    }\n\n    pub struct BuildConfig {\n        pub interpreter_config: InterpreterConfig,\n        pub source: BuildConfigSource,\n    }\n\n    /// Gets the configuration for use from `pyo3-ffi`'s build script.\n    ///\n    /// Differs from `.get()` in three ways:\n    /// 1. The cargo_dep_env config is not yet available (exported by `pyo3-ffi`'s build script).\n    /// 1. If `PYO3_CONFIG_FILE` is set, lib name is fixed up and the windows import libs might be generated.\n    /// 2. The cross-compile config file is generated if necessary.\n    ///\n    /// Steps 2 and 3 are necessary because `pyo3-ffi`'s build script is the first code run which knows\n    /// the correct target triple.\n    pub fn resolve_build_config(target: &Triple) -> Result<BuildConfig> {\n        #[allow(\n            clippy::const_is_empty,\n            reason = \"CONFIG_FILE is generated in build.rs, content can vary\"\n        )]\n        if let Some(mut interpreter_config) = config_from_pyo3_config_file_env() {\n            interpreter_config.apply_default_lib_name_to_config_file(target);\n            Ok(BuildConfig {\n                interpreter_config,\n                source: BuildConfigSource::ConfigFile,\n            })\n        } else if let Some(interpreter_config) = make_cross_compile_config()? {\n            // This is a cross compile and need to write the config file.\n            let path = resolve_cross_compile_config_path()\n                .expect(\"resolve_build_config() must be called from a build script\");\n            let parent_dir = path.parent().ok_or_else(|| {\n                format!(\n                    \"failed to resolve parent directory of config file {}\",\n                    path.display()\n                )\n            })?;\n            std::fs::create_dir_all(parent_dir).with_context(|| {\n                format!(\n                    \"failed to create config file directory {}\",\n                    parent_dir.display()\n                )\n            })?;\n            interpreter_config.to_writer(&mut std::fs::File::create(&path).with_context(\n                || format!(\"failed to create config file at {}\", path.display()),\n            )?)?;\n            Ok(BuildConfig {\n                interpreter_config,\n                source: BuildConfigSource::CrossCompile,\n            })\n        } else {\n            let interpreter_config = InterpreterConfig::from_reader(Cursor::new(HOST_CONFIG))?;\n            Ok(BuildConfig {\n                interpreter_config,\n                source: BuildConfigSource::Host,\n            })\n        }\n    }\n\n    /// Helper to generate an error message when the configured Python version is newer\n    /// than PyO3's current supported version.\n    pub struct MaximumVersionExceeded {\n        message: String,\n    }\n\n    impl MaximumVersionExceeded {\n        pub fn new(\n            interpreter_config: &InterpreterConfig,\n            supported_version: PythonVersion,\n        ) -> Self {\n            let implementation = match interpreter_config.implementation {\n                PythonImplementation::CPython => \"Python\",\n                PythonImplementation::PyPy => \"PyPy\",\n                PythonImplementation::GraalPy => \"GraalPy\",\n            };\n            let version = &interpreter_config.version;\n            let message = format!(\n                \"the configured {implementation} version ({version}) is newer than PyO3's maximum supported version ({supported_version})\\n\\\n                = help: this package is being built with PyO3 version {current_version}\\n\\\n                = help: check https://crates.io/crates/pyo3 for the latest PyO3 version available\\n\\\n                = help: updating this package to the latest version of PyO3 may provide compatibility with this {implementation} version\",\n                current_version = env!(\"CARGO_PKG_VERSION\")\n            );\n            Self { message }\n        }\n\n        pub fn add_help(&mut self, help: &str) {\n            self.message.push_str(\"\\n= help: \");\n            self.message.push_str(help);\n        }\n\n        pub fn finish(self) -> String {\n            self.message\n        }\n    }\n}\n\nfn rustc_minor_version() -> Option<u32> {\n    static RUSTC_MINOR_VERSION: OnceLock<Option<u32>> = OnceLock::new();\n    *RUSTC_MINOR_VERSION.get_or_init(|| {\n        let rustc = env::var_os(\"RUSTC\")?;\n        let output = Command::new(rustc).arg(\"--version\").output().ok()?;\n        let version = core::str::from_utf8(&output.stdout).ok()?;\n        let mut pieces = version.split('.');\n        if pieces.next() != Some(\"rustc 1\") {\n            return None;\n        }\n        pieces.next()?.parse().ok()\n    })\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn extension_module_link_args() {\n        let mut buf = Vec::new();\n\n        // Does nothing on non-mac\n        _add_extension_module_link_args(\n            &Triple::from_str(\"x86_64-pc-windows-msvc\").unwrap(),\n            &mut buf,\n            None,\n        );\n        assert_eq!(buf, Vec::new());\n\n        _add_extension_module_link_args(\n            &Triple::from_str(\"x86_64-apple-darwin\").unwrap(),\n            &mut buf,\n            None,\n        );\n        assert_eq!(\n            std::str::from_utf8(&buf).unwrap(),\n            \"cargo:rustc-cdylib-link-arg=-undefined\\n\\\n             cargo:rustc-cdylib-link-arg=dynamic_lookup\\n\"\n        );\n\n        buf.clear();\n        _add_extension_module_link_args(\n            &Triple::from_str(\"wasm32-unknown-emscripten\").unwrap(),\n            &mut buf,\n            Some(94),\n        );\n        assert_eq!(\n            std::str::from_utf8(&buf).unwrap(),\n            \"cargo:rustc-cdylib-link-arg=-sSIDE_MODULE=2\\n\\\n             cargo:rustc-cdylib-link-arg=-sWASM_BIGINT\\n\"\n        );\n        buf.clear();\n        _add_extension_module_link_args(\n            &Triple::from_str(\"wasm32-unknown-emscripten\").unwrap(),\n            &mut buf,\n            Some(95),\n        );\n        assert_eq!(std::str::from_utf8(&buf).unwrap(), \"\");\n    }\n\n    #[cfg(feature = \"resolve-config\")]\n    #[test]\n    fn python_framework_link_args() {\n        let mut buf = Vec::new();\n\n        let interpreter_config = InterpreterConfig {\n            implementation: PythonImplementation::CPython,\n            version: PythonVersion {\n                major: 3,\n                minor: 13,\n            },\n            shared: true,\n            abi3: false,\n            lib_name: None,\n            lib_dir: None,\n            executable: None,\n            pointer_width: None,\n            build_flags: BuildFlags::default(),\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix: Some(\n                \"/Applications/Xcode.app/Contents/Developer/Library/Frameworks\".to_string(),\n            ),\n        };\n        // Does nothing on non-mac\n        _add_python_framework_link_args(\n            &interpreter_config,\n            &Triple::from_str(\"x86_64-pc-windows-msvc\").unwrap(),\n            true,\n            &mut buf,\n        );\n        assert_eq!(buf, Vec::new());\n\n        _add_python_framework_link_args(\n            &interpreter_config,\n            &Triple::from_str(\"x86_64-apple-darwin\").unwrap(),\n            true,\n            &mut buf,\n        );\n        assert_eq!(\n            std::str::from_utf8(&buf).unwrap(),\n            \"cargo:rustc-link-arg=-Wl,-rpath,/Applications/Xcode.app/Contents/Developer/Library/Frameworks\\n\"\n        );\n    }\n\n    #[test]\n    #[cfg(feature = \"resolve-config\")]\n    fn test_maximum_version_exceeded_formatting() {\n        let interpreter_config = InterpreterConfig {\n            implementation: PythonImplementation::CPython,\n            version: PythonVersion {\n                major: 3,\n                minor: 13,\n            },\n            shared: true,\n            abi3: false,\n            lib_name: None,\n            lib_dir: None,\n            executable: None,\n            pointer_width: None,\n            build_flags: BuildFlags::default(),\n            suppress_build_script_link_lines: false,\n            extra_build_script_lines: vec![],\n            python_framework_prefix: None,\n        };\n        let mut error = pyo3_build_script_impl::MaximumVersionExceeded::new(\n            &interpreter_config,\n            PythonVersion {\n                major: 3,\n                minor: 12,\n            },\n        );\n        error.add_help(\"this is a help message\");\n        let error = error.finish();\n        let expected = concat!(\"\\\n            the configured Python version (3.13) is newer than PyO3's maximum supported version (3.12)\\n\\\n            = help: this package is being built with PyO3 version \", env!(\"CARGO_PKG_VERSION\"), \"\\n\\\n            = help: check https://crates.io/crates/pyo3 for the latest PyO3 version available\\n\\\n            = help: updating this package to the latest version of PyO3 may provide compatibility with this Python version\\n\\\n            = help: this is a help message\"\n        );\n        assert_eq!(error, expected);\n    }\n}\n"
  },
  {
    "path": "pyo3-ffi/ACKNOWLEDGEMENTS",
    "content": "This is a Rust reimplementation of the CPython public header files as necessary\nfor binary compatibility, with additional metadata to support PyPy.\n\nFor original implementations please see:\n - https://github.com/python/cpython\n - https://github.com/pypy/pypy\n"
  },
  {
    "path": "pyo3-ffi/Cargo.toml",
    "content": "[package]\nname = \"pyo3-ffi\"\nversion = \"0.28.2\"\ndescription = \"Python-API bindings for the PyO3 ecosystem\"\nauthors = [\"PyO3 Project and Contributors <https://github.com/PyO3>\"]\nkeywords = [\"pyo3\", \"python\", \"cpython\", \"ffi\"]\nhomepage = \"https://github.com/pyo3/pyo3\"\nrepository = \"https://github.com/pyo3/pyo3\"\ncategories = [\"api-bindings\", \"development-tools::ffi\"]\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nlinks = \"python\"\nrust-version.workspace = true\n\n[dependencies]\nlibc = \"0.2.62\"\n\n[features]\n\ndefault = []\n\n# deprecated\nextension-module = [\"pyo3-build-config/extension-module\"]\n\n# Use the Python limited API. See https://www.python.org/dev/peps/pep-0384/ for more.\nabi3 = [\"pyo3-build-config/abi3\"]\n\n# With abi3, we can manually set the minimum Python version.\nabi3-py37 = [\"abi3-py38\", \"pyo3-build-config/abi3-py37\"]\nabi3-py38 = [\"abi3-py39\", \"pyo3-build-config/abi3-py38\"]\nabi3-py39 = [\"abi3-py310\", \"pyo3-build-config/abi3-py39\"]\nabi3-py310 = [\"abi3-py311\", \"pyo3-build-config/abi3-py310\"]\nabi3-py311 = [\"abi3-py312\", \"pyo3-build-config/abi3-py311\"]\nabi3-py312 = [\"abi3-py313\", \"pyo3-build-config/abi3-py312\"]\nabi3-py313 = [\"abi3-py314\", \"pyo3-build-config/abi3-py313\"]\nabi3-py314 = [\"abi3\", \"pyo3-build-config/abi3-py314\"]\n\n# deprecated: no longer needed, raw-dylib is used instead\ngenerate-import-lib = [\"pyo3-build-config/generate-import-lib\"]\n\n[dev-dependencies]\npaste = \"1\"\n\n[build-dependencies]\npyo3-build-config = { path = \"../pyo3-build-config\", version = \"=0.28.2\", features = [\"resolve-config\"] }\n\n[lints]\nworkspace = true\n\n[package.metadata.cpython]\nmin-version = \"3.7\"\nmax-version = \"3.15\" # inclusive\n\n[package.metadata.pypy]\nmin-version = \"3.11\"\nmax-version = \"3.11\" # inclusive\n"
  },
  {
    "path": "pyo3-ffi/README.md",
    "content": "# pyo3-ffi\n\nThis crate provides [Rust](https://www.rust-lang.org/) FFI declarations for Python 3.\nIt supports both the stable and the unstable component of the ABI through the use of cfg flags.\nPython Versions 3.7+ are supported.\nIt is meant for advanced users only - regular PyO3 users shouldn't\nneed to interact with this crate at all.\n\nThe contents of this crate are not documented here, as it would entail\nbasically copying the documentation from CPython. Consult the [Python/C API Reference\nManual][capi] for up-to-date documentation.\n\n# Minimum supported Rust and Python versions\n\nRequires Rust 1.63 or greater.\n\n`pyo3-ffi` supports the following Python distributions:\n  - CPython 3.7 or greater\n  - PyPy 7.3 (Python 3.9+)\n  - GraalPy 24.0 or greater (Python 3.10+)\n\n# Example: Building Python Native modules\n\nPyO3 can be used to generate a native Python module. The easiest way to try this out for the\nfirst time is to use [`maturin`]. `maturin` is a tool for building and publishing Rust-based\nPython packages with minimal configuration. The following steps set up some files for an example\nPython module, install `maturin`, and then show how to build and import the Python module.\n\nFirst, create a new folder (let's call it `string_sum`) containing the following two files:\n\n**`Cargo.toml`**\n\n```toml\n[lib]\nname = \"string_sum\"\n# \"cdylib\" is necessary to produce a shared library for Python to import from.\n#\n# Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able\n# to `use string_sum;` unless the \"rlib\" or \"lib\" crate type is also included, e.g.:\n# crate-type = [\"cdylib\", \"rlib\"]\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3-ffi = \"0.28.2\"\n\n[build-dependencies]\n# This is only necessary if you need to configure your build based on\n# the Python version or the compile-time configuration for the interpreter.\npyo3_build_config = \"0.28.2\"\n```\n\nIf you need to use conditional compilation based on Python version or how\nPython was compiled, you need to add `pyo3-build-config` as a\n`build-dependency` in your `Cargo.toml` as in the example above and either\ncreate a new `build.rs` file or modify an existing one so that\n`pyo3_build_config::use_pyo3_cfgs()` gets called at build time:\n\n**`build.rs`**\n\n```rust,ignore\nfn main() {\n    pyo3_build_config::use_pyo3_cfgs()\n}\n```\n\n**`src/lib.rs`**\n```rust,no_run\n#[cfg(Py_3_15)]\nuse std::ffi::c_void;\nuse std::ffi::{c_char, c_long};\nuse std::ptr;\n\nuse pyo3_ffi::*;\n\n#[cfg(not(Py_3_15))]\nstatic mut MODULE_DEF: PyModuleDef = PyModuleDef {\n    m_base: PyModuleDef_HEAD_INIT,\n    m_name: c\"string_sum\".as_ptr(),\n    m_doc: c\"A Python module written in Rust.\".as_ptr(),\n    m_size: 0,\n    m_methods: (&raw mut METHODS).cast(),\n    m_slots: (&raw mut SLOTS).cast(),\n    m_traverse: None,\n    m_clear: None,\n    m_free: None,\n};\n\nstatic mut METHODS: [PyMethodDef; 2] = [\n    PyMethodDef {\n        ml_name: c\"sum_as_string\".as_ptr(),\n        ml_meth: PyMethodDefPointer {\n            PyCFunctionFast: sum_as_string,\n        },\n        ml_flags: METH_FASTCALL,\n        ml_doc: c\"returns the sum of two integers as a string\".as_ptr(),\n    },\n    // A zeroed PyMethodDef to mark the end of the array.\n    PyMethodDef::zeroed(),\n];\n\n#[cfg(Py_3_15)]\nPyABIInfo_VAR!(ABI_INFO);\n\nconst SLOTS_LEN: usize =\n    1 + cfg!(Py_3_12) as usize + cfg!(Py_GIL_DISABLED) as usize + 4 * (cfg!(Py_3_15) as usize);\nstatic mut SLOTS: [PyModuleDef_Slot; SLOTS_LEN] = [\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_abi,\n        value: (&raw mut ABI_INFO).cast(),\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_name,\n        // safety: Python does not write to this field\n        value: c\"string_sum\".as_ptr() as *mut c_void,\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_doc,\n        // safety: Python does not write to this field\n        value: c\"A Python module written in Rust.\".as_ptr() as *mut c_void,\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_methods,\n        value: (&raw mut METHODS).cast(),\n    },\n    #[cfg(Py_3_12)]\n    PyModuleDef_Slot {\n        slot: Py_mod_multiple_interpreters,\n        value: Py_MOD_PER_INTERPRETER_GIL_SUPPORTED,\n    },\n    #[cfg(Py_GIL_DISABLED)]\n    PyModuleDef_Slot {\n        slot: Py_mod_gil,\n        value: Py_MOD_GIL_NOT_USED,\n    },\n    PyModuleDef_Slot {\n        slot: 0,\n        value: ptr::null_mut(),\n    },\n];\n\n// The module initialization function\n#[cfg(not(Py_3_15))]\n#[allow(non_snake_case, reason = \"must be named `PyInit_<your_module>`\")]\n#[no_mangle]\npub unsafe extern \"C\" fn PyInit_string_sum() -> *mut PyObject {\n    PyModuleDef_Init(&raw mut MODULE_DEF)\n}\n\n#[cfg(Py_3_15)]\n#[allow(non_snake_case, reason = \"must be named `PyModExport_<your_module>`\")]\n#[no_mangle]\npub unsafe extern \"C\" fn PyModExport_string_sum() -> *mut PyModuleDef_Slot {\n    (&raw mut SLOTS).cast()\n}\n\n/// A helper to parse function arguments\n/// If we used PyO3's proc macros they'd handle all of this boilerplate for us :)\nunsafe fn parse_arg_as_i32(obj: *mut PyObject, n_arg: usize) -> Option<i32> {\n    if PyLong_Check(obj) == 0 {\n        let msg = format!(\n            \"sum_as_string expected an int for positional argument {}\\0\",\n            n_arg\n        );\n        PyErr_SetString(PyExc_TypeError, msg.as_ptr().cast::<c_char>());\n        return None;\n    }\n\n    // Let's keep the behaviour consistent on platforms where `c_long` is bigger than 32 bits.\n    // In particular, it is an i32 on Windows but i64 on most Linux systems\n    let mut overflow = 0;\n    let i_long: c_long = PyLong_AsLongAndOverflow(obj, &mut overflow);\n\n    #[allow(\n        irrefutable_let_patterns,\n        reason = \"some platforms have c_long equal to i32\"\n    )]\n    if overflow != 0 {\n        raise_overflowerror(obj);\n        None\n    } else if let Ok(i) = i_long.try_into() {\n        Some(i)\n    } else {\n        raise_overflowerror(obj);\n        None\n    }\n}\n\nunsafe fn raise_overflowerror(obj: *mut PyObject) {\n    let obj_repr = PyObject_Str(obj);\n    if !obj_repr.is_null() {\n        let mut size = 0;\n        let p = PyUnicode_AsUTF8AndSize(obj_repr, &mut size);\n        if !p.is_null() {\n            let s = std::str::from_utf8_unchecked(std::slice::from_raw_parts(\n                p.cast::<u8>(),\n                size as usize,\n            ));\n            let msg = format!(\"cannot fit {} in 32 bits\\0\", s);\n\n            PyErr_SetString(PyExc_OverflowError, msg.as_ptr().cast::<c_char>());\n        }\n        Py_DECREF(obj_repr);\n    }\n}\n\npub unsafe extern \"C\" fn sum_as_string(\n    _self: *mut PyObject,\n    args: *mut *mut PyObject,\n    nargs: Py_ssize_t,\n) -> *mut PyObject {\n    if nargs != 2 {\n        PyErr_SetString(\n            PyExc_TypeError,\n            c\"sum_as_string expected 2 positional arguments\".as_ptr(),\n        );\n        return std::ptr::null_mut();\n    }\n\n    let (first, second) = (*args, *args.add(1));\n\n    let first = match parse_arg_as_i32(first, 1) {\n        Some(x) => x,\n        None => return std::ptr::null_mut(),\n    };\n    let second = match parse_arg_as_i32(second, 2) {\n        Some(x) => x,\n        None => return std::ptr::null_mut(),\n    };\n\n    match first.checked_add(second) {\n        Some(sum) => {\n            let string = sum.to_string();\n            PyUnicode_FromStringAndSize(string.as_ptr().cast::<c_char>(), string.len() as isize)\n        }\n        None => {\n            PyErr_SetString(PyExc_OverflowError, c\"arguments too large to add\".as_ptr());\n            std::ptr::null_mut()\n        }\n    }\n}\n```\n\nWith those two files in place, now `maturin` needs to be installed. This can be done using\nPython's package manager `pip`. First, load up a new Python `virtualenv`, and install `maturin`\ninto it:\n```bash\n$ cd string_sum\n$ python -m venv .env\n$ source .env/bin/activate\n$ pip install maturin\n```\n\nNow build and execute the module:\n```bash\n$ maturin develop\n# lots of progress output as maturin runs the compilation...\n$ python\n>>> import string_sum\n>>> string_sum.sum_as_string(5, 20)\n'25'\n```\n\nAs well as with `maturin`, it is possible to build using [setuptools-rust] or\n[manually][manual_builds]. Both offer more flexibility than `maturin` but require further\nconfiguration.\n\n\nWhile most projects use the safe wrapper provided by PyO3,\nyou can take a look at the [`orjson`] library as an example on how to use `pyo3-ffi` directly.\nFor those well versed in C and Rust the [tutorials] from the CPython documentation\ncan be easily converted to rust as well.\n\n[tutorials]: https://docs.python.org/3/extending/\n[`orjson`]: https://github.com/ijl/orjson\n[capi]: https://docs.python.org/3/c-api/index.html\n[`maturin`]: https://github.com/PyO3/maturin \"Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages\"\n[`pyo3-build-config`]: https://docs.rs/pyo3-build-config\n[feature flags]: https://doc.rust-lang.org/cargo/reference/features.html \"Features - The Cargo Book\"\n[manual_builds]: https://pyo3.rs/latest/building-and-distribution.html#manual-builds \"Manual builds - Building and Distribution - PyO3 user guide\"\n[setuptools-rust]: https://github.com/PyO3/setuptools-rust \"Setuptools plugin for Rust extensions\"\n[PEP 384]: https://www.python.org/dev/peps/pep-0384 \"PEP 384 -- Defining a Stable ABI\"\n[Features chapter of the guide]: https://pyo3.rs/latest/features.html#features-reference \"Features Reference - PyO3 user guide\"\n"
  },
  {
    "path": "pyo3-ffi/build.rs",
    "content": "use pyo3_build_config::{\n    bail, ensure, print_feature_cfgs,\n    pyo3_build_script_impl::{\n        cargo_env_var, env_var, errors::Result, is_linking_libpython_for_target,\n        resolve_build_config, target_triple_from_env, BuildConfig, BuildConfigSource,\n        InterpreterConfig, MaximumVersionExceeded, PythonVersion,\n    },\n    warn, PythonImplementation,\n};\n\n/// Minimum Python version PyO3 supports.\nstruct SupportedVersions {\n    min: PythonVersion,\n    max: PythonVersion,\n}\n\nconst SUPPORTED_VERSIONS_CPYTHON: SupportedVersions = SupportedVersions {\n    min: PythonVersion { major: 3, minor: 7 },\n    max: PythonVersion {\n        major: 3,\n        minor: 14,\n    },\n};\n\nconst SUPPORTED_VERSIONS_PYPY: SupportedVersions = SupportedVersions {\n    min: PythonVersion {\n        major: 3,\n        minor: 11,\n    },\n    max: SUPPORTED_VERSIONS_CPYTHON.max,\n};\n\nconst SUPPORTED_VERSIONS_GRAALPY: SupportedVersions = SupportedVersions {\n    min: PythonVersion {\n        major: 3,\n        minor: 10,\n    },\n    max: SUPPORTED_VERSIONS_CPYTHON.max,\n};\n\nfn ensure_python_version(interpreter_config: &InterpreterConfig) -> Result<()> {\n    // This is an undocumented env var which is only really intended to be used in CI / for testing\n    // and development.\n    if std::env::var(\"UNSAFE_PYO3_SKIP_VERSION_CHECK\").as_deref() == Ok(\"1\") {\n        return Ok(());\n    }\n\n    match interpreter_config.implementation {\n        PythonImplementation::CPython => {\n            let versions = SUPPORTED_VERSIONS_CPYTHON;\n            ensure!(\n                interpreter_config.version >= versions.min,\n                \"the configured Python interpreter version ({}) is lower than PyO3's minimum supported version ({})\",\n                interpreter_config.version,\n                versions.min,\n            );\n            let v_plus_1 = PythonVersion {\n                major: versions.max.major,\n                minor: versions.max.minor + 1,\n            };\n            if interpreter_config.version == v_plus_1 {\n                warn!(\n                    \"Using experimental support for the Python {}.{} ABI. \\\n                     Build artifacts may not be compatible with the final release of CPython, \\\n                     so do not distribute them.\",\n                    v_plus_1.major, v_plus_1.minor,\n                );\n            } else if interpreter_config.version > v_plus_1 {\n                let mut error = MaximumVersionExceeded::new(interpreter_config, versions.max);\n                if interpreter_config.is_free_threaded() {\n                    error.add_help(\n                        \"the free-threaded build of CPython does not support the limited API so this check cannot be suppressed.\",\n                    );\n                    return Err(error.finish().into());\n                }\n\n                if env_var(\"PYO3_USE_ABI3_FORWARD_COMPATIBILITY\").is_none_or(|os_str| os_str != \"1\")\n                {\n                    error.add_help(\"set PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 to suppress this check and build anyway using the stable ABI\");\n                    return Err(error.finish().into());\n                }\n            }\n\n            if interpreter_config.is_free_threaded() {\n                let min_free_threaded_version = PythonVersion {\n                    major: 3,\n                    minor: 14,\n                };\n                ensure!(\n                    interpreter_config.version >= min_free_threaded_version,\n                    \"PyO3 does not support the free-threaded build of CPython versions below {}, the selected Python version is {}\",\n                    min_free_threaded_version,\n                    interpreter_config.version,\n                );\n            }\n        }\n        PythonImplementation::PyPy => {\n            let versions = SUPPORTED_VERSIONS_PYPY;\n            ensure!(\n                interpreter_config.version >= versions.min,\n                \"the configured PyPy interpreter version ({}) is lower than PyO3's minimum supported version ({})\",\n                interpreter_config.version,\n                versions.min,\n            );\n            // PyO3 does not support abi3, so we cannot offer forward compatibility\n            if interpreter_config.version > versions.max {\n                let error = MaximumVersionExceeded::new(interpreter_config, versions.max);\n                return Err(error.finish().into());\n            }\n        }\n        PythonImplementation::GraalPy => {\n            let versions = SUPPORTED_VERSIONS_GRAALPY;\n            ensure!(\n                interpreter_config.version >= versions.min,\n                \"the configured GraalPy interpreter version ({}) is lower than PyO3's minimum supported version ({})\",\n                interpreter_config.version,\n                versions.min,\n            );\n            // GraalPy does not support abi3, so we cannot offer forward compatibility\n            if interpreter_config.version > versions.max {\n                let error = MaximumVersionExceeded::new(interpreter_config, versions.max);\n                return Err(error.finish().into());\n            }\n        }\n    }\n\n    if interpreter_config.abi3 {\n        match interpreter_config.implementation {\n            PythonImplementation::CPython => {\n                if interpreter_config.is_free_threaded() {\n                    warn!(\n                            \"The free-threaded build of CPython does not yet support abi3 so the build artifacts will be version-specific.\"\n                    )\n                }\n            }\n            PythonImplementation::PyPy => warn!(\n                \"PyPy does not yet support abi3 so the build artifacts will be version-specific. \\\n                See https://github.com/pypy/pypy/issues/3397 for more information.\"\n            ),\n            PythonImplementation::GraalPy => warn!(\n                \"GraalPy does not support abi3 so the build artifacts will be version-specific.\"\n            ),\n        }\n    }\n\n    Ok(())\n}\n\nfn ensure_target_pointer_width(interpreter_config: &InterpreterConfig) -> Result<()> {\n    if let Some(pointer_width) = interpreter_config.pointer_width {\n        // Try to check whether the target architecture matches the python library\n        let rust_target = match cargo_env_var(\"CARGO_CFG_TARGET_POINTER_WIDTH\")\n            .unwrap()\n            .as_str()\n        {\n            \"64\" => 64,\n            \"32\" => 32,\n            x => bail!(\"unexpected Rust target pointer width: {}\", x),\n        };\n\n        ensure!(\n            rust_target == pointer_width,\n            \"your Rust target architecture ({}-bit) does not match your python interpreter ({}-bit)\",\n            rust_target,\n            pointer_width\n        );\n    }\n    Ok(())\n}\n\nfn emit_link_config(build_config: &BuildConfig) -> Result<()> {\n    let interpreter_config = &build_config.interpreter_config;\n    let target_os = cargo_env_var(\"CARGO_CFG_TARGET_OS\").unwrap();\n\n    let lib_name = interpreter_config\n        .lib_name\n        .as_ref()\n        .ok_or(\"attempted to link to Python shared library but config does not contain lib_name\")?;\n\n    if target_os == \"windows\" {\n        // Use raw-dylib linking: emit a cfg so that `extern_libpython!` picks the\n        // right `#[link(name = \"...\", kind = \"raw-dylib\")]` attribute at compile time.\n        // This eliminates the need for import libraries (.lib files) entirely.\n        //\n        // Note: raw-dylib is inherently dynamic linking. Static embedding of the\n        // Python interpreter on Windows is not supported by this path (and is not\n        // officially supported by CPython on Windows).\n        println!(\"cargo:rustc-cfg=pyo3_dll=\\\"{lib_name}\\\"\");\n    } else {\n        println!(\n            \"cargo:rustc-link-lib={link_model}{lib_name}\",\n            link_model = if interpreter_config.shared {\n                \"\"\n            } else {\n                \"static=\"\n            },\n        );\n\n        if let Some(lib_dir) = &interpreter_config.lib_dir {\n            println!(\"cargo:rustc-link-search=native={lib_dir}\");\n        } else if matches!(build_config.source, BuildConfigSource::CrossCompile) {\n            warn!(\n                \"The output binary will link to libpython, \\\n                but PYO3_CROSS_LIB_DIR environment variable is not set. \\\n                Ensure that the target Python library directory is \\\n                in the rustc native library search path.\"\n            );\n        }\n    }\n\n    Ok(())\n}\n\n/// Prepares the PyO3 crate for compilation.\n///\n/// This loads the config from pyo3-build-config and then makes some additional checks to improve UX\n/// for users.\n///\n/// Emits the cargo configuration based on this config as well as a few checks of the Rust compiler\n/// version to enable features which aren't supported on MSRV.\nfn configure_pyo3() -> Result<()> {\n    let target = target_triple_from_env();\n    let build_config = resolve_build_config(&target)?;\n    let interpreter_config = &build_config.interpreter_config;\n\n    if env_var(\"PYO3_PRINT_CONFIG\").is_some_and(|os_str| os_str == \"1\") {\n        print_config_and_exit(interpreter_config);\n    }\n\n    ensure_python_version(interpreter_config)?;\n    ensure_target_pointer_width(interpreter_config)?;\n\n    // Serialize the whole interpreter config into DEP_PYTHON_PYO3_CONFIG env var.\n    interpreter_config.to_cargo_dep_env()?;\n\n    if is_linking_libpython_for_target(&target)\n        && !interpreter_config.suppress_build_script_link_lines\n    {\n        emit_link_config(&build_config)?;\n    }\n\n    for cfg in interpreter_config.build_script_outputs() {\n        println!(\"{cfg}\")\n    }\n\n    // Extra lines come last, to support last write wins.\n    for line in &interpreter_config.extra_build_script_lines {\n        println!(\"{line}\");\n    }\n\n    print_feature_cfgs();\n\n    Ok(())\n}\n\nfn print_config_and_exit(config: &InterpreterConfig) {\n    println!(\"\\n-- PYO3_PRINT_CONFIG=1 is set, printing configuration and halting compile --\");\n    config\n        .to_writer(std::io::stdout())\n        .expect(\"failed to print config to stdout\");\n    println!(\"\\nnote: unset the PYO3_PRINT_CONFIG environment variable and retry to compile with the above config\");\n    std::process::exit(101);\n}\n\nfn main() {\n    pyo3_build_config::print_expected_cfgs();\n    if let Err(e) = configure_pyo3() {\n        eprintln!(\"error: {}\", e.report());\n        std::process::exit(1)\n    }\n}\n"
  },
  {
    "path": "pyo3-ffi/examples/README.md",
    "content": "# `pyo3-ffi` Examples\n\nThese example crates are a collection of toy extension modules built with\n`pyo3-ffi`. They are all tested using `nox` in PyO3's CI.\n\nBelow is a brief description of each of these:\n\n| Example | Description |\n| `word-count` | Illustrates how to use pyo3-ffi to write a static rust extension |\n| `sequential` | Illustrates how to use pyo3-ffi to write subinterpreter-safe modules using multi-phase module initialization |\n\n## Creating new projects from these examples\n\nTo copy an example, use [`cargo-generate`](https://crates.io/crates/cargo-generate). Follow the commands below, replacing `<example>` with the example to start from:\n\n```bash\n$ cargo install cargo-generate\n$ cargo generate --git https://github.com/PyO3/pyo3 examples/<example>\n```\n\n(`cargo generate` will take a little while to clone the PyO3 repo first; be patient when waiting for the command to run.)\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/.template/Cargo.toml",
    "content": "[package]\nauthors = [\"{{authors}}\"]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\nname = \"sequential\"\ncrate-type = [\"cdylib\", \"lib\"]\n\n[dependencies]\npyo3-ffi = { version = \"{{PYO3_VERSION}}\" }\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/.template/pre-script.rhai",
    "content": "variable::set(\"PYO3_VERSION\", \"0.19.2\");\nfile::rename(\".template/Cargo.toml\", \"Cargo.toml\");\nfile::rename(\".template/pyproject.toml\", \"pyproject.toml\");\nfile::delete(\".template\");\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/.template/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/Cargo.toml",
    "content": "[package]\nname = \"sequential\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.83\"\n\n[lib]\nname = \"sequential\"\ncrate-type = [\"cdylib\", \"lib\"]\n\n[dependencies]\npyo3-ffi = { path = \"../../\" }\n\n[build-dependencies]\npyo3-build-config = { path = \"../../../pyo3-build-config\" }\n\n[workspace]\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/MANIFEST.in",
    "content": "include pyproject.toml Cargo.toml\nrecursive-include src *\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/README.md",
    "content": "# sequential\n\nA project built using only `pyo3_ffi`, without any of PyO3's safe api. It supports both subinterpreters and free-threaded Python.\n\n## Building and Testing\n\nTo build this package, first install `maturin`:\n\n```shell\npip install maturin\n```\n\nTo build and test use `maturin develop`:\n\n```shell\npip install -r requirements-dev.txt\nmaturin develop\npytest\n```\n\nAlternatively, install nox and run the tests inside an isolated environment:\n\n```shell\nnox\n```\n\n## Copying this example\n\nUse [`cargo-generate`](https://crates.io/crates/cargo-generate):\n\n```bash\n$ cargo install cargo-generate\n$ cargo generate --git https://github.com/PyO3/pyo3 examples/sequential\n```\n\n(`cargo generate` will take a little while to clone the PyO3 repo first; be patient when waiting for the command to run.)\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/build.rs",
    "content": "fn main() {\n    pyo3_build_config::use_pyo3_cfgs();\n}\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/cargo-generate.toml",
    "content": "[template]\nignore = [\".nox\"]\n\n[hooks]\npre = [\".template/pre-script.rhai\"]\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/noxfile.py",
    "content": "import sys\nimport nox\n\n\n@nox.session\ndef python(session):\n    if sys.version_info < (3, 12):\n        session.skip(\"Python 3.12+ is required\")\n    session.env[\"MATURIN_PEP517_ARGS\"] = \"--profile=dev\"\n    session.install(\".[dev]\")\n    session.run(\"pytest\")\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"sequential\"\nversion = \"0.1.0\"\nclassifiers = [\n    \"License :: OSI Approved :: MIT License\",\n    \"Development Status :: 3 - Alpha\",\n    \"Intended Audience :: Developers\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Rust\",\n    \"Operating System :: POSIX\",\n    \"Operating System :: MacOS :: MacOS X\",\n]\nrequires-python = \">=3.12\"\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/src/id.rs",
    "content": "use core::sync::atomic::{AtomicU64, Ordering};\nuse core::{mem, ptr};\nuse std::ffi::CString;\nuse std::ffi::{c_char, c_int, c_uint, c_ulonglong, c_void};\n\nuse pyo3_ffi::*;\n\n#[repr(C)]\npub struct PyId {\n    _ob_base: PyObject,\n    id: Id,\n}\n\nstatic COUNT: AtomicU64 = AtomicU64::new(0);\n\n#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]\npub struct Id(u64);\n\nimpl Id {\n    fn new() -> Self {\n        Id(COUNT.fetch_add(1, Ordering::Relaxed))\n    }\n}\n\nunsafe extern \"C\" fn id_new(\n    subtype: *mut PyTypeObject,\n    args: *mut PyObject,\n    kwds: *mut PyObject,\n) -> *mut PyObject {\n    if PyTuple_Size(args) != 0 || !kwds.is_null() {\n        // We use pyo3-ffi's `c_str!` macro to create null-terminated literals because\n        // Rust's string literals are not null-terminated\n        // On Rust 1.77 or newer you can use `c\"text\"` instead.\n        PyErr_SetString(PyExc_TypeError, c\"Id() takes no arguments\".as_ptr());\n        return ptr::null_mut();\n    }\n\n    let f: allocfunc = (*subtype).tp_alloc.unwrap_or(PyType_GenericAlloc);\n    let slf = f(subtype, 0);\n\n    if slf.is_null() {\n        return ptr::null_mut();\n    } else {\n        let id = Id::new();\n        let slf = slf.cast::<PyId>();\n        (&raw mut (*slf).id).write(id);\n    }\n\n    slf\n}\n\nunsafe extern \"C\" fn id_repr(slf: *mut PyObject) -> *mut PyObject {\n    let slf = slf.cast::<PyId>();\n    let id = (*slf).id.0;\n    let string = format!(\"Id({})\", id);\n    PyUnicode_FromStringAndSize(string.as_ptr().cast::<c_char>(), string.len() as Py_ssize_t)\n}\n\nunsafe extern \"C\" fn id_int(slf: *mut PyObject) -> *mut PyObject {\n    let slf = slf.cast::<PyId>();\n    let id = (*slf).id.0;\n    PyLong_FromUnsignedLongLong(id as c_ulonglong)\n}\n\nunsafe extern \"C\" fn id_richcompare(\n    slf: *mut PyObject,\n    other: *mut PyObject,\n    op: c_int,\n) -> *mut PyObject {\n    let pytype = Py_TYPE(slf); // guaranteed to be `sequential.Id`\n    if Py_TYPE(other) != pytype {\n        return Py_NewRef(Py_NotImplemented());\n    }\n    let slf = (*slf.cast::<PyId>()).id;\n    let other = (*other.cast::<PyId>()).id;\n\n    let cmp = match op {\n        pyo3_ffi::Py_LT => slf < other,\n        pyo3_ffi::Py_LE => slf <= other,\n        pyo3_ffi::Py_EQ => slf == other,\n        pyo3_ffi::Py_NE => slf != other,\n        pyo3_ffi::Py_GT => slf > other,\n        pyo3_ffi::Py_GE => slf >= other,\n        unrecognized => {\n            let msg = CString::new(&*format!(\n                \"unrecognized richcompare opcode {}\",\n                unrecognized\n            ))\n            .unwrap();\n            PyErr_SetString(PyExc_SystemError, msg.as_ptr());\n            return ptr::null_mut();\n        }\n    };\n\n    if cmp {\n        Py_NewRef(Py_True())\n    } else {\n        Py_NewRef(Py_False())\n    }\n}\n\nstatic mut SLOTS: [PyType_Slot; 6] = [\n    PyType_Slot {\n        slot: Py_tp_new,\n        pfunc: id_new as *mut c_void,\n    },\n    PyType_Slot {\n        slot: Py_tp_doc,\n        pfunc: c\"An id that is increased every time an instance is created\".as_ptr() as *mut c_void,\n    },\n    PyType_Slot {\n        slot: Py_tp_repr,\n        pfunc: id_repr as *mut c_void,\n    },\n    PyType_Slot {\n        slot: Py_nb_int,\n        pfunc: id_int as *mut c_void,\n    },\n    PyType_Slot {\n        slot: Py_tp_richcompare,\n        pfunc: id_richcompare as *mut c_void,\n    },\n    PyType_Slot {\n        slot: 0,\n        pfunc: ptr::null_mut(),\n    },\n];\n\npub static mut ID_SPEC: PyType_Spec = PyType_Spec {\n    name: c\"sequential.Id\".as_ptr(),\n    basicsize: mem::size_of::<PyId>() as c_int,\n    itemsize: 0,\n    flags: (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE) as c_uint,\n    slots: (&raw mut SLOTS).cast(),\n};\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/src/lib.rs",
    "content": "use pyo3_ffi::*;\n\nmod id;\nmod module;\n#[cfg(not(Py_3_15))]\nuse crate::module::MODULE_DEF;\n#[cfg(Py_3_15)]\nuse crate::module::SEQUENTIAL_SLOTS;\n\n#[cfg(not(Py_3_15))]\n#[allow(non_snake_case, reason = \"must be named `PyInit_<your_module>`\")]\n#[no_mangle]\npub unsafe extern \"C\" fn PyInit_sequential() -> *mut PyObject {\n    PyModuleDef_Init(&raw mut MODULE_DEF)\n}\n\n#[cfg(Py_3_15)]\n#[allow(non_snake_case, reason = \"must be named `PyModExport_<your_module>`\")]\n#[no_mangle]\npub unsafe extern \"C\" fn PyModExport_sequential() -> *mut PyModuleDef_Slot {\n    (&raw mut SEQUENTIAL_SLOTS).cast()\n}\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/src/module.rs",
    "content": "use core::{mem, ptr};\nuse pyo3_ffi::*;\nuse std::ffi::{c_int, c_void};\n\n#[cfg(not(Py_3_15))]\npub static mut MODULE_DEF: PyModuleDef = PyModuleDef {\n    m_base: PyModuleDef_HEAD_INIT,\n    m_name: c\"sequential\".as_ptr(),\n    m_doc: c\"A library for generating sequential ids, written in Rust.\".as_ptr(),\n    m_size: mem::size_of::<sequential_state>() as Py_ssize_t,\n    m_methods: std::ptr::null_mut(),\n    m_slots: (&raw mut SEQUENTIAL_SLOTS).cast(),\n    m_traverse: Some(sequential_traverse),\n    m_clear: Some(sequential_clear),\n    m_free: Some(sequential_free),\n};\n\n#[cfg(Py_3_15)]\nPyABIInfo_VAR!(ABI_INFO);\n\nconst SEQUENTIAL_SLOTS_LEN: usize =\n    2 + cfg!(Py_3_12) as usize + cfg!(Py_GIL_DISABLED) as usize + 7 * (cfg!(Py_3_15) as usize);\npub static mut SEQUENTIAL_SLOTS: [PyModuleDef_Slot; SEQUENTIAL_SLOTS_LEN] = [\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_abi,\n        value: (&raw mut ABI_INFO).cast(),\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_name,\n        // safety: Python does not write to this field\n        value: c\"sequential\".as_ptr() as *mut c_void,\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_doc,\n        // safety: Python does not write to this field\n        value: c\"A library for generating sequential ids, written in Rust.\".as_ptr() as *mut c_void,\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_state_size,\n        value: mem::size_of::<sequential_state>() as *mut c_void,\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_state_traverse,\n        value: sequential_traverse as *mut c_void,\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_state_clear,\n        value: sequential_clear as *mut c_void,\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_state_free,\n        value: sequential_free as *mut c_void,\n    },\n    PyModuleDef_Slot {\n        slot: Py_mod_exec,\n        value: sequential_exec as *mut c_void,\n    },\n    #[cfg(Py_3_12)]\n    PyModuleDef_Slot {\n        slot: Py_mod_multiple_interpreters,\n        value: Py_MOD_PER_INTERPRETER_GIL_SUPPORTED,\n    },\n    #[cfg(Py_GIL_DISABLED)]\n    PyModuleDef_Slot {\n        slot: Py_mod_gil,\n        value: Py_MOD_GIL_NOT_USED,\n    },\n    PyModuleDef_Slot {\n        slot: 0,\n        value: ptr::null_mut(),\n    },\n];\n\nunsafe extern \"C\" fn sequential_exec(module: *mut PyObject) -> c_int {\n    let state: *mut sequential_state = PyModule_GetState(module).cast();\n\n    let id_type = PyType_FromModuleAndSpec(module, &raw mut crate::id::ID_SPEC, ptr::null_mut());\n    if id_type.is_null() {\n        PyErr_SetString(PyExc_SystemError, c\"cannot locate type object\".as_ptr());\n        return -1;\n    }\n    (*state).id_type = id_type.cast::<PyTypeObject>();\n\n    PyModule_AddObjectRef(module, c\"Id\".as_ptr(), id_type)\n}\n\nunsafe extern \"C\" fn sequential_traverse(\n    module: *mut PyObject,\n    visit: visitproc,\n    arg: *mut c_void,\n) -> c_int {\n    let state: *mut sequential_state = PyModule_GetState(module.cast()).cast();\n    let id_type: *mut PyObject = (*state).id_type.cast();\n\n    if id_type.is_null() {\n        0\n    } else {\n        (visit)(id_type, arg)\n    }\n}\n\nunsafe extern \"C\" fn sequential_clear(module: *mut PyObject) -> c_int {\n    let state: *mut sequential_state = PyModule_GetState(module.cast()).cast();\n    Py_CLEAR((&raw mut (*state).id_type).cast());\n    0\n}\n\nunsafe extern \"C\" fn sequential_free(module: *mut c_void) {\n    sequential_clear(module.cast());\n}\n\n#[repr(C)]\nstruct sequential_state {\n    id_type: *mut PyTypeObject,\n}\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/tests/test.rs",
    "content": "use core::ffi::{c_char, CStr};\nuse core::ptr;\nuse std::thread;\n\nuse pyo3_ffi::*;\nuse sequential::PyInit_sequential;\n\nstatic COMMAND: &'static CStr= c\"\nfrom sequential import Id\n\ns = sum(int(Id()) for _ in range(12))\n\";\n\n// Newtype to be able to pass it to another thread.\nstruct State(*mut PyThreadState);\nunsafe impl Sync for State {}\nunsafe impl Send for State {}\n\n#[test]\nfn lets_go_fast() -> Result<(), String> {\n    unsafe {\n        let ret = PyImport_AppendInittab(c\"sequential\".as_ptr(), Some(PyInit_sequential));\n        if ret == -1 {\n            return Err(\"could not add module to inittab\".into());\n        }\n\n        Py_Initialize();\n\n        let main_state = PyThreadState_Swap(ptr::null_mut());\n\n        const NULL: State = State(ptr::null_mut());\n        let mut subs = [NULL; 12];\n\n        let config = PyInterpreterConfig {\n            use_main_obmalloc: 0,\n            allow_fork: 0,\n            allow_exec: 0,\n            allow_threads: 1,\n            allow_daemon_threads: 0,\n            check_multi_interp_extensions: 1,\n            gil: PyInterpreterConfig_OWN_GIL,\n        };\n\n        for State(state) in &mut subs {\n            let status = Py_NewInterpreterFromConfig(state, &config);\n            if PyStatus_IsError(status) == 1 {\n                let msg = if status.err_msg.is_null() {\n                    \"no error message\".into()\n                } else {\n                    CStr::from_ptr(status.err_msg).to_string_lossy()\n                };\n                PyThreadState_Swap(main_state);\n                Py_FinalizeEx();\n                return Err(format!(\"could not create new subinterpreter: {msg}\"));\n            }\n        }\n\n        PyThreadState_Swap(main_state);\n\n        let main_state = PyEval_SaveThread(); // a PyInterpreterConfig with shared gil would deadlock otherwise\n\n        let ints: Vec<_> = thread::scope(move |s| {\n            let mut handles = vec![];\n\n            for state in subs {\n                let handle = s.spawn(move || {\n                    let state = state;\n                    PyEval_RestoreThread(state.0);\n\n                    let ret = run_code();\n\n                    Py_EndInterpreter(state.0);\n                    ret\n                });\n\n                handles.push(handle);\n            }\n\n            handles.into_iter().map(|h| h.join().unwrap()).collect()\n        });\n\n        PyEval_RestoreThread(main_state);\n\n        let ret = Py_FinalizeEx();\n        if ret == -1 {\n            return Err(\"could not finalize interpreter\".into());\n        }\n\n        let mut sum: u64 = 0;\n        for i in ints {\n            let i = i?;\n            sum += i;\n        }\n\n        assert_eq!(sum, (0..).take(12 * 12).sum());\n    }\n\n    Ok(())\n}\n\nunsafe fn fetch() -> String {\n    let err = PyErr_GetRaisedException();\n    let err_repr = PyObject_Str(err);\n    if !err_repr.is_null() {\n        let mut size = 0;\n        let p = PyUnicode_AsUTF8AndSize(err_repr, &mut size);\n        if !p.is_null() {\n            let s = std::str::from_utf8_unchecked(std::slice::from_raw_parts(\n                p.cast::<u8>(),\n                size as usize,\n            ));\n            let s = String::from(s);\n            Py_DECREF(err_repr);\n            return s;\n        }\n    }\n    String::from(\"could not get error\")\n}\n\nfn run_code() -> Result<u64, String> {\n    unsafe {\n        let code_obj = Py_CompileString(COMMAND.as_ptr(), c\"program\".as_ptr(), Py_file_input);\n        if code_obj.is_null() {\n            return Err(fetch());\n        }\n        let globals = PyDict_New();\n        let res_ptr = PyEval_EvalCode(code_obj, globals, ptr::null_mut());\n        Py_DECREF(code_obj);\n        if res_ptr.is_null() {\n            return Err(fetch());\n        } else {\n            Py_DECREF(res_ptr);\n        }\n        let sum = PyDict_GetItemString(globals, c\"s\".as_ptr()); /* borrowed reference */\n        if sum.is_null() {\n            Py_DECREF(globals);\n            return Err(\"globals did not have `s`\".into());\n        }\n        let int = PyLong_AsUnsignedLongLong(sum) as u64;\n\n        Py_DECREF(globals);\n        Ok(int)\n    }\n}\n"
  },
  {
    "path": "pyo3-ffi/examples/sequential/tests/test_.py",
    "content": "import pytest\nfrom sequential import Id\n\n\ndef test_make_some():\n    for x in range(12):\n        i = Id()\n        assert x == int(i)\n\n\ndef test_args():\n    with pytest.raises(TypeError, match=\"Id\\\\(\\\\) takes no arguments\"):\n        Id(3, 4)\n\n\ndef test_cmp():\n    a = Id()\n    b = Id()\n    assert a <= b\n    assert a < b\n    assert a == a\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/.template/Cargo.toml",
    "content": "[package]\nauthors = [\"{{authors}}\"]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\nname = \"string_sum\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3-ffi = { version = \"{{PYO3_VERSION}}\" }\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/.template/pre-script.rhai",
    "content": "variable::set(\"PYO3_VERSION\", \"0.19.2\");\nfile::rename(\".template/Cargo.toml\", \"Cargo.toml\");\nfile::rename(\".template/pyproject.toml\", \"pyproject.toml\");\nfile::delete(\".template\");\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/.template/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"{{project-name}}\"\nversion = \"0.1.0\"\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/Cargo.toml",
    "content": "[package]\nname = \"string_sum\"\nversion = \"0.1.0\"\nedition = \"2021\"\nrust-version = \"1.83\"\n\n[lib]\nname = \"string_sum\"\ncrate-type = [\"cdylib\"]\n\n[dependencies]\npyo3-ffi = { path = \"../../\" }\n\n[build-dependencies]\npyo3-build-config = { path = \"../../../pyo3-build-config\" }\n\n[workspace]\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/MANIFEST.in",
    "content": "include pyproject.toml Cargo.toml\nrecursive-include src *\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/README.md",
    "content": "# string_sum\n\nA project built using only `pyo3_ffi`, without any of PyO3's safe api.\n\n## Building and Testing\n\nTo build this package, first install `maturin`:\n\n```shell\npip install maturin\n```\n\nTo build and test use `maturin develop`:\n\n```shell\npip install -r requirements-dev.txt\nmaturin develop\npytest\n```\n\nAlternatively, install nox and run the tests inside an isolated environment:\n\n```shell\nnox\n```\n\n## Copying this example\n\nUse [`cargo-generate`](https://crates.io/crates/cargo-generate):\n\n```bash\n$ cargo install cargo-generate\n$ cargo generate --git https://github.com/PyO3/pyo3 examples/string_sum\n```\n\n(`cargo generate` will take a little while to clone the PyO3 repo first; be patient when waiting for the command to run.)\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/build.rs",
    "content": "fn main() {\n    pyo3_build_config::use_pyo3_cfgs();\n}\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/cargo-generate.toml",
    "content": "[template]\nignore = [\".nox\"]\n\n[hooks]\npre = [\".template/pre-script.rhai\"]\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/noxfile.py",
    "content": "import nox\n\n\n@nox.session\ndef python(session: nox.Session):\n    session.env[\"MATURIN_PEP517_ARGS\"] = \"--profile=dev\"\n    session.install(\".[dev]\")\n    session.run(\"pytest\")\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1,<2\"]\nbuild-backend = \"maturin\"\n\n[project]\nname = \"string_sum\"\nversion = \"0.1.0\"\nclassifiers = [\n    \"License :: OSI Approved :: MIT License\",\n    \"Development Status :: 3 - Alpha\",\n    \"Intended Audience :: Developers\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Rust\",\n    \"Operating System :: POSIX\",\n    \"Operating System :: MacOS :: MacOS X\",\n]\n\n[project.optional-dependencies]\ndev = [\"pytest\"]\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/src/lib.rs",
    "content": "#[cfg(Py_3_15)]\nuse std::ffi::c_void;\nuse std::ffi::{c_char, c_long};\nuse std::ptr;\n\nuse pyo3_ffi::*;\n\n#[cfg(not(Py_3_15))]\nstatic mut MODULE_DEF: PyModuleDef = PyModuleDef {\n    m_base: PyModuleDef_HEAD_INIT,\n    m_name: c\"string_sum\".as_ptr(),\n    m_doc: c\"A Python module written in Rust.\".as_ptr(),\n    m_size: 0,\n    m_methods: (&raw mut METHODS).cast(),\n    m_slots: (&raw mut SLOTS).cast(),\n    m_traverse: None,\n    m_clear: None,\n    m_free: None,\n};\n\nstatic mut METHODS: [PyMethodDef; 2] = [\n    PyMethodDef {\n        ml_name: c\"sum_as_string\".as_ptr(),\n        ml_meth: PyMethodDefPointer {\n            PyCFunctionFast: sum_as_string,\n        },\n        ml_flags: METH_FASTCALL,\n        ml_doc: c\"returns the sum of two integers as a string\".as_ptr(),\n    },\n    // A zeroed PyMethodDef to mark the end of the array.\n    PyMethodDef::zeroed(),\n];\n\n#[cfg(Py_3_15)]\nPyABIInfo_VAR!(ABI_INFO);\n\nconst SLOTS_LEN: usize =\n    1 + cfg!(Py_3_12) as usize + cfg!(Py_GIL_DISABLED) as usize + 4 * (cfg!(Py_3_15) as usize);\nstatic mut SLOTS: [PyModuleDef_Slot; SLOTS_LEN] = [\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_abi,\n        value: (&raw mut ABI_INFO).cast(),\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_name,\n        // safety: Python does not write to this field\n        value: c\"string_sum\".as_ptr() as *mut c_void,\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_doc,\n        // safety: Python does not write to this field\n        value: c\"A Python module written in Rust.\".as_ptr() as *mut c_void,\n    },\n    #[cfg(Py_3_15)]\n    PyModuleDef_Slot {\n        slot: Py_mod_methods,\n        value: (&raw mut METHODS).cast(),\n    },\n    #[cfg(Py_3_12)]\n    PyModuleDef_Slot {\n        slot: Py_mod_multiple_interpreters,\n        value: Py_MOD_PER_INTERPRETER_GIL_SUPPORTED,\n    },\n    #[cfg(Py_GIL_DISABLED)]\n    PyModuleDef_Slot {\n        slot: Py_mod_gil,\n        value: Py_MOD_GIL_NOT_USED,\n    },\n    PyModuleDef_Slot {\n        slot: 0,\n        value: ptr::null_mut(),\n    },\n];\n\n// The module initialization function\n#[cfg(not(Py_3_15))]\n#[allow(non_snake_case, reason = \"must be named `PyInit_<your_module>`\")]\n#[no_mangle]\npub unsafe extern \"C\" fn PyInit_string_sum() -> *mut PyObject {\n    PyModuleDef_Init(&raw mut MODULE_DEF)\n}\n\n#[cfg(Py_3_15)]\n#[allow(non_snake_case, reason = \"must be named `PyModExport_<your_module>`\")]\n#[no_mangle]\npub unsafe extern \"C\" fn PyModExport_string_sum() -> *mut PyModuleDef_Slot {\n    (&raw mut SLOTS).cast()\n}\n\n/// A helper to parse function arguments\n/// If we used PyO3's proc macros they'd handle all of this boilerplate for us :)\nunsafe fn parse_arg_as_i32(obj: *mut PyObject, n_arg: usize) -> Option<i32> {\n    if PyLong_Check(obj) == 0 {\n        let msg = format!(\n            \"sum_as_string expected an int for positional argument {}\\0\",\n            n_arg\n        );\n        PyErr_SetString(PyExc_TypeError, msg.as_ptr().cast::<c_char>());\n        return None;\n    }\n\n    // Let's keep the behaviour consistent on platforms where `c_long` is bigger than 32 bits.\n    // In particular, it is an i32 on Windows but i64 on most Linux systems\n    let mut overflow = 0;\n    let i_long: c_long = PyLong_AsLongAndOverflow(obj, &mut overflow);\n\n    #[allow(\n        irrefutable_let_patterns,\n        reason = \"some platforms have c_long equal to i32\"\n    )]\n    if overflow != 0 {\n        raise_overflowerror(obj);\n        None\n    } else if let Ok(i) = i_long.try_into() {\n        Some(i)\n    } else {\n        raise_overflowerror(obj);\n        None\n    }\n}\n\nunsafe fn raise_overflowerror(obj: *mut PyObject) {\n    let obj_repr = PyObject_Str(obj);\n    if !obj_repr.is_null() {\n        let mut size = 0;\n        let p = PyUnicode_AsUTF8AndSize(obj_repr, &mut size);\n        if !p.is_null() {\n            let s = std::str::from_utf8_unchecked(std::slice::from_raw_parts(\n                p.cast::<u8>(),\n                size as usize,\n            ));\n            let msg = format!(\"cannot fit {} in 32 bits\\0\", s);\n\n            PyErr_SetString(PyExc_OverflowError, msg.as_ptr().cast::<c_char>());\n        }\n        Py_DECREF(obj_repr);\n    }\n}\n\npub unsafe extern \"C\" fn sum_as_string(\n    _self: *mut PyObject,\n    args: *mut *mut PyObject,\n    nargs: Py_ssize_t,\n) -> *mut PyObject {\n    if nargs != 2 {\n        PyErr_SetString(\n            PyExc_TypeError,\n            c\"sum_as_string expected 2 positional arguments\".as_ptr(),\n        );\n        return std::ptr::null_mut();\n    }\n\n    let (first, second) = (*args, *args.add(1));\n\n    let first = match parse_arg_as_i32(first, 1) {\n        Some(x) => x,\n        None => return std::ptr::null_mut(),\n    };\n    let second = match parse_arg_as_i32(second, 2) {\n        Some(x) => x,\n        None => return std::ptr::null_mut(),\n    };\n\n    match first.checked_add(second) {\n        Some(sum) => {\n            let string = sum.to_string();\n            PyUnicode_FromStringAndSize(string.as_ptr().cast::<c_char>(), string.len() as isize)\n        }\n        None => {\n            PyErr_SetString(PyExc_OverflowError, c\"arguments too large to add\".as_ptr());\n            std::ptr::null_mut()\n        }\n    }\n}\n"
  },
  {
    "path": "pyo3-ffi/examples/string-sum/tests/test_.py",
    "content": "import pytest\nfrom string_sum import sum_as_string\n\n\ndef test_sum():\n    a, b = 12, 42\n\n    added = sum_as_string(a, b)\n    assert added == \"54\"\n\n\ndef test_err1():\n    a, b = \"abc\", 42\n\n    with pytest.raises(\n        TypeError, match=\"sum_as_string expected an int for positional argument 1\"\n    ):\n        sum_as_string(a, b)\n\n\ndef test_err2():\n    a, b = 0, {}\n\n    with pytest.raises(\n        TypeError, match=\"sum_as_string expected an int for positional argument 2\"\n    ):\n        sum_as_string(a, b)\n\n\ndef test_overflow1():\n    a, b = 0, 1 << 43\n\n    with pytest.raises(OverflowError, match=\"cannot fit 8796093022208 in 32 bits\"):\n        sum_as_string(a, b)\n\n\ndef test_overflow2():\n    a, b = 1 << 30, 1 << 30\n\n    with pytest.raises(OverflowError, match=\"arguments too large to add\"):\n        sum_as_string(a, b)\n"
  },
  {
    "path": "pyo3-ffi/src/abstract_.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\n#[cfg(any(Py_3_12, all(Py_3_8, not(Py_LIMITED_API))))]\nuse libc::size_t;\nuse std::ffi::{c_char, c_int};\n\n#[inline]\n#[cfg(all(\n    not(Py_3_13), // CPython exposed as a function in 3.13, in object.h\n    not(all(PyPy, not(Py_3_11))) // PyPy exposed as a function until PyPy 3.10, macro in 3.11+\n))]\npub unsafe fn PyObject_DelAttrString(o: *mut PyObject, attr_name: *const c_char) -> c_int {\n    PyObject_SetAttrString(o, attr_name, std::ptr::null_mut())\n}\n\n#[inline]\n#[cfg(all(\n    not(Py_3_13), // CPython exposed as a function in 3.13, in object.h\n    not(all(PyPy, not(Py_3_11))) // PyPy exposed as a function until PyPy 3.10, macro in 3.11+\n))]\npub unsafe fn PyObject_DelAttr(o: *mut PyObject, attr_name: *mut PyObject) -> c_int {\n    PyObject_SetAttr(o, attr_name, std::ptr::null_mut())\n}\n\nextern_libpython! {\n    #[cfg(all(\n        not(PyPy),\n        any(Py_3_10, all(not(Py_LIMITED_API), Py_3_9)) // Added to python in 3.9 but to limited API in 3.10\n    ))]\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_CallNoArgs\")]\n    pub fn PyObject_CallNoArgs(func: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Call\")]\n    pub fn PyObject_Call(\n        callable_object: *mut PyObject,\n        args: *mut PyObject,\n        kw: *mut PyObject,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_CallObject\")]\n    pub fn PyObject_CallObject(\n        callable_object: *mut PyObject,\n        args: *mut PyObject,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_CallFunction\")]\n    pub fn PyObject_CallFunction(\n        callable_object: *mut PyObject,\n        format: *const c_char,\n        ...\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_CallMethod\")]\n    pub fn PyObject_CallMethod(\n        o: *mut PyObject,\n        method: *const c_char,\n        format: *const c_char,\n        ...\n    ) -> *mut PyObject;\n\n    #[cfg(not(Py_3_13))]\n    #[cfg_attr(PyPy, link_name = \"_PyPyObject_CallFunction_SizeT\")]\n    pub fn _PyObject_CallFunction_SizeT(\n        callable_object: *mut PyObject,\n        format: *const c_char,\n        ...\n    ) -> *mut PyObject;\n    #[cfg(not(Py_3_13))]\n    #[cfg_attr(PyPy, link_name = \"_PyPyObject_CallMethod_SizeT\")]\n    pub fn _PyObject_CallMethod_SizeT(\n        o: *mut PyObject,\n        method: *const c_char,\n        format: *const c_char,\n        ...\n    ) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_CallFunctionObjArgs\")]\n    pub fn PyObject_CallFunctionObjArgs(callable: *mut PyObject, ...) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_CallMethodObjArgs\")]\n    pub fn PyObject_CallMethodObjArgs(\n        o: *mut PyObject,\n        method: *mut PyObject,\n        ...\n    ) -> *mut PyObject;\n}\n#[cfg(any(Py_3_12, all(Py_3_8, not(Py_LIMITED_API))))]\npub const PY_VECTORCALL_ARGUMENTS_OFFSET: size_t =\n    1 << (8 * std::mem::size_of::<size_t>() as size_t - 1);\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Vectorcall\")]\n    #[cfg(any(Py_3_12, all(Py_3_11, not(Py_LIMITED_API))))]\n    pub fn PyObject_Vectorcall(\n        callable: *mut PyObject,\n        args: *const *mut PyObject,\n        nargsf: size_t,\n        kwnames: *mut PyObject,\n    ) -> *mut PyObject;\n\n    #[cfg(any(Py_3_12, all(Py_3_9, not(any(Py_LIMITED_API, PyPy)))))]\n    pub fn PyObject_VectorcallMethod(\n        name: *mut PyObject,\n        args: *const *mut PyObject,\n        nargsf: size_t,\n        kwnames: *mut PyObject,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Type\")]\n    pub fn PyObject_Type(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Size\")]\n    pub fn PyObject_Size(o: *mut PyObject) -> Py_ssize_t;\n}\n\n#[inline]\npub unsafe fn PyObject_Length(o: *mut PyObject) -> Py_ssize_t {\n    PyObject_Size(o)\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GetItem\")]\n    pub fn PyObject_GetItem(o: *mut PyObject, key: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_SetItem\")]\n    pub fn PyObject_SetItem(o: *mut PyObject, key: *mut PyObject, v: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_DelItemString\")]\n    pub fn PyObject_DelItemString(o: *mut PyObject, key: *const c_char) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_DelItem\")]\n    pub fn PyObject_DelItem(o: *mut PyObject, key: *mut PyObject) -> c_int;\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Format\")]\n    pub fn PyObject_Format(obj: *mut PyObject, format_spec: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GetIter\")]\n    pub fn PyObject_GetIter(arg1: *mut PyObject) -> *mut PyObject;\n}\n\n// Before 3.8 PyIter_Check was defined in CPython as a macro,\n// but the implementation of that in PyO3 did not work, see\n// https://github.com/PyO3/pyo3/pull/2914\n//\n// This is a slow implementation which should function equivalently.\n#[cfg(not(any(Py_3_8, PyPy)))]\n#[inline]\npub unsafe fn PyIter_Check(o: *mut PyObject) -> c_int {\n    crate::PyObject_HasAttrString(crate::Py_TYPE(o).cast(), c\"__next__\".as_ptr())\n}\n\nextern_libpython! {\n    #[cfg(any(Py_3_8, PyPy))]\n    #[cfg_attr(PyPy, link_name = \"PyPyIter_Check\")]\n    pub fn PyIter_Check(obj: *mut PyObject) -> c_int;\n\n    #[cfg(Py_3_14)]\n    #[cfg_attr(PyPy, link_name = \"PyPyIter_NextItem\")]\n    pub fn PyIter_NextItem(iter: *mut PyObject, item: *mut *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyIter_Next\")]\n    pub fn PyIter_Next(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg(all(not(PyPy), Py_3_10))]\n    #[cfg_attr(PyPy, link_name = \"PyPyIter_Send\")]\n    pub fn PyIter_Send(\n        iter: *mut PyObject,\n        arg: *mut PyObject,\n        presult: *mut *mut PyObject,\n    ) -> PySendResult;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Check\")]\n    pub fn PyNumber_Check(o: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Add\")]\n    pub fn PyNumber_Add(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Subtract\")]\n    pub fn PyNumber_Subtract(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Multiply\")]\n    pub fn PyNumber_Multiply(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_MatrixMultiply\")]\n    pub fn PyNumber_MatrixMultiply(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_FloorDivide\")]\n    pub fn PyNumber_FloorDivide(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_TrueDivide\")]\n    pub fn PyNumber_TrueDivide(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Remainder\")]\n    pub fn PyNumber_Remainder(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Divmod\")]\n    pub fn PyNumber_Divmod(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Power\")]\n    pub fn PyNumber_Power(o1: *mut PyObject, o2: *mut PyObject, o3: *mut PyObject)\n        -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Negative\")]\n    pub fn PyNumber_Negative(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Positive\")]\n    pub fn PyNumber_Positive(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Absolute\")]\n    pub fn PyNumber_Absolute(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Invert\")]\n    pub fn PyNumber_Invert(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Lshift\")]\n    pub fn PyNumber_Lshift(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Rshift\")]\n    pub fn PyNumber_Rshift(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_And\")]\n    pub fn PyNumber_And(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Xor\")]\n    pub fn PyNumber_Xor(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Or\")]\n    pub fn PyNumber_Or(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n}\n\n// Defined as this macro in Python limited API, but relies on\n// non-limited PyTypeObject. Don't expose this since it cannot be used.\n#[cfg(not(any(Py_LIMITED_API, PyPy)))]\n#[inline]\npub unsafe fn PyIndex_Check(o: *mut PyObject) -> c_int {\n    let tp_as_number = (*Py_TYPE(o)).tp_as_number;\n    (!tp_as_number.is_null() && (*tp_as_number).nb_index.is_some()) as c_int\n}\n\nextern_libpython! {\n    #[cfg(any(all(Py_3_8, Py_LIMITED_API), PyPy))]\n    #[link_name = \"PyPyIndex_Check\"]\n    pub fn PyIndex_Check(o: *mut PyObject) -> c_int;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Index\")]\n    pub fn PyNumber_Index(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_AsSsize_t\")]\n    pub fn PyNumber_AsSsize_t(o: *mut PyObject, exc: *mut PyObject) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Long\")]\n    pub fn PyNumber_Long(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_Float\")]\n    pub fn PyNumber_Float(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceAdd\")]\n    pub fn PyNumber_InPlaceAdd(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceSubtract\")]\n    pub fn PyNumber_InPlaceSubtract(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceMultiply\")]\n    pub fn PyNumber_InPlaceMultiply(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceMatrixMultiply\")]\n    pub fn PyNumber_InPlaceMatrixMultiply(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceFloorDivide\")]\n    pub fn PyNumber_InPlaceFloorDivide(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceTrueDivide\")]\n    pub fn PyNumber_InPlaceTrueDivide(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceRemainder\")]\n    pub fn PyNumber_InPlaceRemainder(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlacePower\")]\n    pub fn PyNumber_InPlacePower(\n        o1: *mut PyObject,\n        o2: *mut PyObject,\n        o3: *mut PyObject,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceLshift\")]\n    pub fn PyNumber_InPlaceLshift(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceRshift\")]\n    pub fn PyNumber_InPlaceRshift(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceAnd\")]\n    pub fn PyNumber_InPlaceAnd(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceXor\")]\n    pub fn PyNumber_InPlaceXor(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyNumber_InPlaceOr\")]\n    pub fn PyNumber_InPlaceOr(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    pub fn PyNumber_ToBase(n: *mut PyObject, base: c_int) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_Check\")]\n    pub fn PySequence_Check(o: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_Size\")]\n    pub fn PySequence_Size(o: *mut PyObject) -> Py_ssize_t;\n\n    #[cfg(PyPy)]\n    #[link_name = \"PyPySequence_Length\"]\n    pub fn PySequence_Length(o: *mut PyObject) -> Py_ssize_t;\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PySequence_Length(o: *mut PyObject) -> Py_ssize_t {\n    PySequence_Size(o)\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_Concat\")]\n    pub fn PySequence_Concat(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_Repeat\")]\n    pub fn PySequence_Repeat(o: *mut PyObject, count: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_GetItem\")]\n    pub fn PySequence_GetItem(o: *mut PyObject, i: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_GetSlice\")]\n    pub fn PySequence_GetSlice(o: *mut PyObject, i1: Py_ssize_t, i2: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_SetItem\")]\n    pub fn PySequence_SetItem(o: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_DelItem\")]\n    pub fn PySequence_DelItem(o: *mut PyObject, i: Py_ssize_t) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_SetSlice\")]\n    pub fn PySequence_SetSlice(\n        o: *mut PyObject,\n        i1: Py_ssize_t,\n        i2: Py_ssize_t,\n        v: *mut PyObject,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_DelSlice\")]\n    pub fn PySequence_DelSlice(o: *mut PyObject, i1: Py_ssize_t, i2: Py_ssize_t) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_Tuple\")]\n    pub fn PySequence_Tuple(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_List\")]\n    pub fn PySequence_List(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_Fast\")]\n    pub fn PySequence_Fast(o: *mut PyObject, m: *const c_char) -> *mut PyObject;\n    // skipped PySequence_Fast_GET_SIZE\n    // skipped PySequence_Fast_GET_ITEM\n    // skipped PySequence_Fast_GET_ITEMS\n    pub fn PySequence_Count(o: *mut PyObject, value: *mut PyObject) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_Contains\")]\n    pub fn PySequence_Contains(seq: *mut PyObject, ob: *mut PyObject) -> c_int;\n}\n\n#[inline]\npub unsafe fn PySequence_In(o: *mut PyObject, value: *mut PyObject) -> c_int {\n    PySequence_Contains(o, value)\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_Index\")]\n    pub fn PySequence_Index(o: *mut PyObject, value: *mut PyObject) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_InPlaceConcat\")]\n    pub fn PySequence_InPlaceConcat(o1: *mut PyObject, o2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPySequence_InPlaceRepeat\")]\n    pub fn PySequence_InPlaceRepeat(o: *mut PyObject, count: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyMapping_Check\")]\n    pub fn PyMapping_Check(o: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyMapping_Size\")]\n    pub fn PyMapping_Size(o: *mut PyObject) -> Py_ssize_t;\n\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyMapping_Length\"]\n    pub fn PyMapping_Length(o: *mut PyObject) -> Py_ssize_t;\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyMapping_Length(o: *mut PyObject) -> Py_ssize_t {\n    PyMapping_Size(o)\n}\n\n#[inline]\npub unsafe fn PyMapping_DelItemString(o: *mut PyObject, key: *mut c_char) -> c_int {\n    PyObject_DelItemString(o, key)\n}\n\n#[inline]\npub unsafe fn PyMapping_DelItem(o: *mut PyObject, key: *mut PyObject) -> c_int {\n    PyObject_DelItem(o, key)\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyMapping_HasKeyString\")]\n    pub fn PyMapping_HasKeyString(o: *mut PyObject, key: *const c_char) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyMapping_HasKey\")]\n    pub fn PyMapping_HasKey(o: *mut PyObject, key: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyMapping_Keys\")]\n    pub fn PyMapping_Keys(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyMapping_Values\")]\n    pub fn PyMapping_Values(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyMapping_Items\")]\n    pub fn PyMapping_Items(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyMapping_GetItemString\")]\n    pub fn PyMapping_GetItemString(o: *mut PyObject, key: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyMapping_SetItemString\")]\n    pub fn PyMapping_SetItemString(\n        o: *mut PyObject,\n        key: *const c_char,\n        value: *mut PyObject,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_IsInstance\")]\n    pub fn PyObject_IsInstance(object: *mut PyObject, typeorclass: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_IsSubclass\")]\n    pub fn PyObject_IsSubclass(object: *mut PyObject, typeorclass: *mut PyObject) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/bltinmodule.rs",
    "content": "use crate::object::PyTypeObject;\n\nextern_libpython! {\n    pub static mut PyFilter_Type: PyTypeObject;\n    pub static mut PyMap_Type: PyTypeObject;\n    pub static mut PyZip_Type: PyTypeObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/boolobject.rs",
    "content": "#[cfg(not(GraalPy))]\nuse crate::longobject::PyLongObject;\nuse crate::object::*;\nuse std::ffi::{c_int, c_long};\n\n#[inline]\npub unsafe fn PyBool_Check(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyBool_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg(not(GraalPy))]\n    #[cfg_attr(PyPy, link_name = \"_PyPy_FalseStruct\")]\n    static mut _Py_FalseStruct: PyLongObject;\n    #[cfg(not(GraalPy))]\n    #[cfg_attr(PyPy, link_name = \"_PyPy_TrueStruct\")]\n    static mut _Py_TrueStruct: PyLongObject;\n\n    #[cfg(GraalPy)]\n    static mut _Py_FalseStructReference: *mut PyObject;\n    #[cfg(GraalPy)]\n    static mut _Py_TrueStructReference: *mut PyObject;\n}\n\n#[inline]\npub unsafe fn Py_False() -> *mut PyObject {\n    #[cfg(not(GraalPy))]\n    return (&raw mut _Py_FalseStruct).cast();\n    #[cfg(GraalPy)]\n    return _Py_FalseStructReference;\n}\n\n#[inline]\npub unsafe fn Py_True() -> *mut PyObject {\n    #[cfg(not(GraalPy))]\n    return (&raw mut _Py_TrueStruct).cast();\n    #[cfg(GraalPy)]\n    return _Py_TrueStructReference;\n}\n\n#[inline]\npub unsafe fn Py_IsTrue(x: *mut PyObject) -> c_int {\n    Py_Is(x, Py_True())\n}\n\n#[inline]\npub unsafe fn Py_IsFalse(x: *mut PyObject) -> c_int {\n    Py_Is(x, Py_False())\n}\n\n// skipped Py_RETURN_TRUE\n// skipped Py_RETURN_FALSE\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyBool_FromLong\")]\n    pub fn PyBool_FromLong(arg1: c_long) -> *mut PyObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/bytearrayobject.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::{c_char, c_int};\n\n#[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))]\n#[repr(C)]\npub struct PyByteArrayObject {\n    pub ob_base: PyVarObject,\n    pub ob_alloc: Py_ssize_t,\n    pub ob_bytes: *mut c_char,\n    pub ob_start: *mut c_char,\n    #[cfg(Py_3_9)]\n    pub ob_exports: Py_ssize_t,\n    #[cfg(not(Py_3_9))]\n    pub ob_exports: c_int,\n    #[cfg(Py_3_15)]\n    pub ob_bytes_object: *mut PyObject,\n}\n\n#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))]\nopaque_struct!(pub PyByteArrayObject);\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyByteArray_Type\")]\n    pub static mut PyByteArray_Type: PyTypeObject;\n\n    pub static mut PyByteArrayIter_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyByteArray_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyByteArray_Type)\n}\n\n#[inline]\npub unsafe fn PyByteArray_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyByteArray_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyByteArray_FromObject\")]\n    pub fn PyByteArray_FromObject(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyByteArray_Concat\")]\n    pub fn PyByteArray_Concat(a: *mut PyObject, b: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyByteArray_FromStringAndSize\")]\n    pub fn PyByteArray_FromStringAndSize(string: *const c_char, len: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyByteArray_Size\")]\n    pub fn PyByteArray_Size(bytearray: *mut PyObject) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyByteArray_AsString\")]\n    pub fn PyByteArray_AsString(bytearray: *mut PyObject) -> *mut c_char;\n    #[cfg_attr(PyPy, link_name = \"PyPyByteArray_Resize\")]\n    pub fn PyByteArray_Resize(bytearray: *mut PyObject, len: Py_ssize_t) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/bytesobject.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::{c_char, c_int};\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyBytes_Type\")]\n    pub static mut PyBytes_Type: PyTypeObject;\n    pub static mut PyBytesIter_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyBytes_Check(op: *mut PyObject) -> c_int {\n    PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_BYTES_SUBCLASS)\n}\n\n#[inline]\npub unsafe fn PyBytes_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyBytes_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyBytes_FromStringAndSize\")]\n    pub fn PyBytes_FromStringAndSize(arg1: *const c_char, arg2: Py_ssize_t) -> *mut PyObject;\n    pub fn PyBytes_FromString(arg1: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyBytes_FromObject\")]\n    pub fn PyBytes_FromObject(arg1: *mut PyObject) -> *mut PyObject;\n    // skipped PyBytes_FromFormatV\n    //#[cfg_attr(PyPy, link_name = \"PyPyBytes_FromFormatV\")]\n    //pub fn PyBytes_FromFormatV(arg1: *const c_char, arg2: va_list)\n    // -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyBytes_FromFormat\")]\n    pub fn PyBytes_FromFormat(arg1: *const c_char, ...) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyBytes_Size\")]\n    pub fn PyBytes_Size(arg1: *mut PyObject) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyBytes_AsString\")]\n    pub fn PyBytes_AsString(arg1: *mut PyObject) -> *mut c_char;\n    pub fn PyBytes_Repr(arg1: *mut PyObject, arg2: c_int) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyBytes_Concat\")]\n    pub fn PyBytes_Concat(arg1: *mut *mut PyObject, arg2: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPyBytes_ConcatAndDel\")]\n    pub fn PyBytes_ConcatAndDel(arg1: *mut *mut PyObject, arg2: *mut PyObject);\n    pub fn PyBytes_DecodeEscape(\n        arg1: *const c_char,\n        arg2: Py_ssize_t,\n        arg3: *const c_char,\n        arg4: Py_ssize_t,\n        arg5: *const c_char,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyBytes_AsStringAndSize\")]\n    pub fn PyBytes_AsStringAndSize(\n        obj: *mut PyObject,\n        s: *mut *mut c_char,\n        len: *mut Py_ssize_t,\n    ) -> c_int;\n}\n\n// skipped F_LJUST\n// skipped F_SIGN\n// skipped F_BLANK\n// skipped F_ALT\n// skipped F_ZERO\n"
  },
  {
    "path": "pyo3-ffi/src/ceval.rs",
    "content": "use crate::object::PyObject;\nuse crate::pytypedefs::PyThreadState;\nuse std::ffi::{c_char, c_int, c_void};\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_EvalCode\")]\n    pub fn PyEval_EvalCode(\n        arg1: *mut PyObject,\n        arg2: *mut PyObject,\n        arg3: *mut PyObject,\n    ) -> *mut PyObject;\n\n    pub fn PyEval_EvalCodeEx(\n        co: *mut PyObject,\n        globals: *mut PyObject,\n        locals: *mut PyObject,\n        args: *const *mut PyObject,\n        argc: c_int,\n        kwds: *const *mut PyObject,\n        kwdc: c_int,\n        defs: *const *mut PyObject,\n        defc: c_int,\n        kwdefs: *mut PyObject,\n        closure: *mut PyObject,\n    ) -> *mut PyObject;\n\n    #[cfg(not(Py_3_13))]\n    #[cfg_attr(Py_3_9, deprecated(note = \"Python 3.9\"))]\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_CallObjectWithKeywords\")]\n    pub fn PyEval_CallObjectWithKeywords(\n        func: *mut PyObject,\n        obj: *mut PyObject,\n        kwargs: *mut PyObject,\n    ) -> *mut PyObject;\n}\n\n#[cfg(not(Py_3_13))]\n#[cfg_attr(Py_3_9, deprecated(note = \"Python 3.9\"))]\n#[inline]\npub unsafe fn PyEval_CallObject(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject {\n    #[allow(deprecated)]\n    PyEval_CallObjectWithKeywords(func, arg, std::ptr::null_mut())\n}\n\nextern_libpython! {\n    #[cfg(not(Py_3_13))]\n    #[cfg_attr(Py_3_9, deprecated(note = \"Python 3.9\"))]\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_CallFunction\")]\n    pub fn PyEval_CallFunction(obj: *mut PyObject, format: *const c_char, ...) -> *mut PyObject;\n    #[cfg(not(Py_3_13))]\n    #[cfg_attr(Py_3_9, deprecated(note = \"Python 3.9\"))]\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_CallMethod\")]\n    pub fn PyEval_CallMethod(\n        obj: *mut PyObject,\n        methodname: *const c_char,\n        format: *const c_char,\n        ...\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_GetBuiltins\")]\n    pub fn PyEval_GetBuiltins() -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_GetGlobals\")]\n    pub fn PyEval_GetGlobals() -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_GetLocals\")]\n    pub fn PyEval_GetLocals() -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_GetFrame\")]\n    pub fn PyEval_GetFrame() -> *mut crate::PyFrameObject;\n\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_GetFrameBuiltins\")]\n    pub fn PyEval_GetFrameBuiltins() -> *mut PyObject;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_GetFrameGlobals\")]\n    pub fn PyEval_GetFrameGlobals() -> *mut PyObject;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_GetFrameLocals\")]\n    pub fn PyEval_GetFrameLocals() -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPy_AddPendingCall\")]\n    pub fn Py_AddPendingCall(\n        func: Option<extern \"C\" fn(arg1: *mut c_void) -> c_int>,\n        arg: *mut c_void,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPy_MakePendingCalls\")]\n    pub fn Py_MakePendingCalls() -> c_int;\n\n    #[cfg_attr(PyPy, link_name = \"PyPy_SetRecursionLimit\")]\n    pub fn Py_SetRecursionLimit(arg1: c_int);\n    #[cfg_attr(PyPy, link_name = \"PyPy_GetRecursionLimit\")]\n    pub fn Py_GetRecursionLimit() -> c_int;\n\n    #[cfg(Py_3_9)]\n    #[cfg_attr(PyPy, link_name = \"PyPy_EnterRecursiveCall\")]\n    pub fn Py_EnterRecursiveCall(arg1: *const c_char) -> c_int;\n    #[cfg(Py_3_9)]\n    #[cfg_attr(PyPy, link_name = \"PyPy_LeaveRecursiveCall\")]\n    pub fn Py_LeaveRecursiveCall();\n\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_GetFuncName\")]\n    pub fn PyEval_GetFuncName(arg1: *mut PyObject) -> *const c_char;\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_GetFuncDesc\")]\n    pub fn PyEval_GetFuncDesc(arg1: *mut PyObject) -> *const c_char;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_EvalFrame\")]\n    pub fn PyEval_EvalFrame(arg1: *mut crate::PyFrameObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_EvalFrameEx\")]\n    pub fn PyEval_EvalFrameEx(f: *mut crate::PyFrameObject, exc: c_int) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_SaveThread\")]\n    pub fn PyEval_SaveThread() -> *mut PyThreadState;\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_RestoreThread\")]\n    pub fn PyEval_RestoreThread(arg1: *mut PyThreadState);\n\n    #[cfg(not(Py_3_13))]\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_ThreadsInitialized\")]\n    #[cfg_attr(\n        Py_3_9,\n        deprecated(\n            note = \"Deprecated in Python 3.9, this function always returns true in Python 3.7 or newer.\"\n        )\n    )]\n    pub fn PyEval_ThreadsInitialized() -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_InitThreads\")]\n    #[cfg_attr(\n        Py_3_9,\n        deprecated(\n            note = \"Deprecated in Python 3.9, this function does nothing in Python 3.7 or newer.\"\n        )\n    )]\n    pub fn PyEval_InitThreads();\n    #[cfg(not(Py_3_13))]\n    #[deprecated(note = \"Deprecated in Python 3.2\")]\n    pub fn PyEval_AcquireLock();\n    #[cfg(not(Py_3_13))]\n    #[deprecated(note = \"Deprecated in Python 3.2\")]\n    pub fn PyEval_ReleaseLock();\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_AcquireThread\")]\n    pub fn PyEval_AcquireThread(tstate: *mut PyThreadState);\n    #[cfg_attr(PyPy, link_name = \"PyPyEval_ReleaseThread\")]\n    pub fn PyEval_ReleaseThread(tstate: *mut PyThreadState);\n    #[cfg(not(Py_3_8))]\n    pub fn PyEval_ReInitThreads();\n}\n\n// skipped Py_BEGIN_ALLOW_THREADS\n// skipped Py_BLOCK_THREADS\n// skipped Py_UNBLOCK_THREADS\n// skipped Py_END_ALLOW_THREADS\n// skipped FVC_MASK\n// skipped FVC_NONE\n// skipped FVC_STR\n// skipped FVC_REPR\n// skipped FVC_ASCII\n// skipped FVS_MASK\n// skipped FVS_HAVE_SPEC\n"
  },
  {
    "path": "pyo3-ffi/src/codecs.rs",
    "content": "use crate::object::PyObject;\nuse std::ffi::{c_char, c_int};\n\nextern_libpython! {\n    pub fn PyCodec_Register(search_function: *mut PyObject) -> c_int;\n    #[cfg(Py_3_10)]\n    #[cfg(not(PyPy))]\n    pub fn PyCodec_Unregister(search_function: *mut PyObject) -> c_int;\n    // skipped non-limited _PyCodec_Lookup from Include/codecs.h\n    // skipped non-limited _PyCodec_Forget from Include/codecs.h\n    pub fn PyCodec_KnownEncoding(encoding: *const c_char) -> c_int;\n    pub fn PyCodec_Encode(\n        object: *mut PyObject,\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyCodec_Decode(\n        object: *mut PyObject,\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    // skipped non-limited _PyCodec_LookupTextEncoding from Include/codecs.h\n    // skipped non-limited _PyCodec_EncodeText from Include/codecs.h\n    // skipped non-limited _PyCodec_DecodeText from Include/codecs.h\n    // skipped non-limited _PyCodecInfo_GetIncrementalDecoder from Include/codecs.h\n    // skipped non-limited _PyCodecInfo_GetIncrementalEncoder from Include/codecs.h\n    pub fn PyCodec_Encoder(encoding: *const c_char) -> *mut PyObject;\n    pub fn PyCodec_Decoder(encoding: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyCodec_IncrementalEncoder\")]\n    pub fn PyCodec_IncrementalEncoder(\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyCodec_IncrementalDecoder\")]\n    pub fn PyCodec_IncrementalDecoder(\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyCodec_StreamReader(\n        encoding: *const c_char,\n        stream: *mut PyObject,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyCodec_StreamWriter(\n        encoding: *const c_char,\n        stream: *mut PyObject,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyCodec_RegisterError(name: *const c_char, error: *mut PyObject) -> c_int;\n    pub fn PyCodec_LookupError(name: *const c_char) -> *mut PyObject;\n    pub fn PyCodec_StrictErrors(exc: *mut PyObject) -> *mut PyObject;\n    pub fn PyCodec_IgnoreErrors(exc: *mut PyObject) -> *mut PyObject;\n    pub fn PyCodec_ReplaceErrors(exc: *mut PyObject) -> *mut PyObject;\n    pub fn PyCodec_XMLCharRefReplaceErrors(exc: *mut PyObject) -> *mut PyObject;\n    pub fn PyCodec_BackslashReplaceErrors(exc: *mut PyObject) -> *mut PyObject;\n    // skipped non-limited PyCodec_NameReplaceErrors from Include/codecs.h\n    // skipped non-limited Py_hexdigits from Include/codecs.h\n}\n"
  },
  {
    "path": "pyo3-ffi/src/compat/mod.rs",
    "content": "//! C API Compatibility Shims\n//!\n//! Some CPython C API functions added in recent versions of Python are\n//! inherently safer to use than older C API constructs. This module\n//! exposes functions available on all Python versions that wrap the\n//! old C API on old Python versions and wrap the function directly\n//! on newer Python versions.\n\n// Unless otherwise noted, the compatibility shims are adapted from\n// the pythoncapi-compat project: https://github.com/python/pythoncapi-compat\n\n/// Internal helper macro which defines compatibility shims for C API functions, deferring to a\n/// re-export when that's available.\nmacro_rules! compat_function {\n    (\n        originally_defined_for($cfg:meta);\n\n        $(#[$attrs:meta])*\n        pub unsafe fn $name:ident($($arg_names:ident: $arg_types:ty),* $(,)?) -> $ret:ty $body:block\n    ) => {\n        // Define as a standalone function under docsrs cfg so that this shows as a unique function in the docs,\n        // not a re-export (the re-export has the wrong visibility)\n        #[cfg(any(docsrs, not($cfg)))]\n        #[cfg_attr(docsrs, doc(cfg(all())))]\n        $(#[$attrs])*\n        pub unsafe fn $name(\n            $($arg_names: $arg_types,)*\n        ) -> $ret $body\n\n        #[cfg(all($cfg, not(docsrs)))]\n        pub use $crate::$name;\n\n        #[cfg(test)]\n        paste::paste! {\n            // Test that the compat function does not overlap with the original function. If the\n            // cfgs line up, then the the two glob imports will resolve to the same item via the\n            // re-export. If the cfgs mismatch, then the use of $name will be ambiguous in cases\n            // where the function is defined twice, and the test will fail to compile.\n            #[allow(unused_imports, reason = \"imports exist to try to trigger name conflicts\")]\n            mod [<test_ $name _export>] {\n                use $crate::*;\n                use $crate::compat::*;\n\n                #[test]\n                fn test_export() {\n                    let _ = $name;\n                }\n            }\n        }\n    };\n}\n\nmod py_3_10;\nmod py_3_13;\nmod py_3_14;\nmod py_3_15;\nmod py_3_9;\n\npub use self::py_3_10::*;\npub use self::py_3_13::*;\npub use self::py_3_14::*;\n#[allow(unused_imports)]\npub use self::py_3_15::*;\npub use self::py_3_9::*;\n"
  },
  {
    "path": "pyo3-ffi/src/compat/py_3_10.rs",
    "content": "compat_function!(\n    originally_defined_for(Py_3_10);\n\n    #[inline]\n    pub unsafe fn Py_NewRef(obj: *mut crate::PyObject) -> *mut crate::PyObject {\n        crate::Py_INCREF(obj);\n        obj\n    }\n);\n\ncompat_function!(\n    originally_defined_for(Py_3_10);\n\n    #[inline]\n    pub unsafe fn Py_XNewRef(obj: *mut crate::PyObject) -> *mut crate::PyObject {\n        crate::Py_XINCREF(obj);\n        obj\n    }\n);\n\ncompat_function!(\n    originally_defined_for(Py_3_10);\n\n    #[inline]\n    pub unsafe fn PyModule_AddObjectRef(\n        module: *mut crate::PyObject,\n        name: *const std::ffi::c_char,\n        value: *mut crate::PyObject,\n    ) -> std::ffi::c_int {\n        if value.is_null() && crate::PyErr_Occurred().is_null() {\n            crate::PyErr_SetString(\n                crate::PyExc_SystemError,\n                c\"PyModule_AddObjectRef() must be called with an exception raised if value is NULL\".as_ptr(),\n            );\n            return -1;\n        }\n\n        crate::Py_XINCREF(value);\n        let result = crate::PyModule_AddObject(module, name, value);\n        if result < 0 {\n            crate::Py_XDECREF(value);\n        }\n        result\n    }\n);\n"
  },
  {
    "path": "pyo3-ffi/src/compat/py_3_13.rs",
    "content": "compat_function!(\n    originally_defined_for(Py_3_13);\n\n    #[inline]\n    pub unsafe fn PyDict_GetItemRef(\n        dp: *mut crate::PyObject,\n        key: *mut crate::PyObject,\n        result: *mut *mut crate::PyObject,\n    ) -> std::ffi::c_int {\n        use crate::{compat::Py_NewRef, PyDict_GetItemWithError, PyErr_Occurred};\n\n        let item = PyDict_GetItemWithError(dp, key);\n        if !item.is_null() {\n            *result = Py_NewRef(item);\n            return 1; // found\n        }\n        *result = std::ptr::null_mut();\n        if PyErr_Occurred().is_null() {\n            return 0; // not found\n        }\n        -1\n    }\n);\n\ncompat_function!(\n    originally_defined_for(Py_3_13);\n\n    #[inline]\n    pub unsafe fn PyList_GetItemRef(\n        arg1: *mut crate::PyObject,\n        arg2: crate::Py_ssize_t,\n    ) -> *mut crate::PyObject {\n        use crate::{PyList_GetItem, Py_XINCREF};\n\n        let item = PyList_GetItem(arg1, arg2);\n        Py_XINCREF(item);\n        item\n    }\n);\n\ncompat_function!(\n    originally_defined_for(Py_3_13);\n\n    #[inline]\n    pub unsafe fn PyImport_AddModuleRef(\n        name: *const std::ffi::c_char,\n    ) -> *mut crate::PyObject {\n        use crate::{compat::Py_XNewRef, PyImport_AddModule};\n\n        Py_XNewRef(PyImport_AddModule(name))\n    }\n);\n\ncompat_function!(\n    originally_defined_for(Py_3_13);\n\n    #[inline]\n    pub unsafe fn PyWeakref_GetRef(\n        reference: *mut crate::PyObject,\n        pobj: *mut *mut crate::PyObject,\n    ) -> std::ffi::c_int {\n        use crate::{\n            compat::Py_NewRef, PyErr_SetString, PyExc_TypeError, PyWeakref_Check,\n            PyWeakref_GetObject, Py_None,\n        };\n\n        if !reference.is_null() && PyWeakref_Check(reference) == 0 {\n            *pobj = std::ptr::null_mut();\n            PyErr_SetString(PyExc_TypeError, c\"expected a weakref\".as_ptr());\n            return -1;\n        }\n        let obj = PyWeakref_GetObject(reference);\n        if obj.is_null() {\n            // SystemError if reference is NULL\n            *pobj = std::ptr::null_mut();\n            return -1;\n        }\n        if obj == Py_None() {\n            *pobj = std::ptr::null_mut();\n            return 0;\n        }\n        *pobj = Py_NewRef(obj);\n        1\n    }\n);\n\ncompat_function!(\n    originally_defined_for(Py_3_13);\n\n    #[inline]\n    pub unsafe fn PyList_Extend(\n        list: *mut crate::PyObject,\n        iterable: *mut crate::PyObject,\n    ) -> std::ffi::c_int {\n        crate::PyList_SetSlice(list, crate::PY_SSIZE_T_MAX, crate::PY_SSIZE_T_MAX, iterable)\n    }\n);\n\ncompat_function!(\n    originally_defined_for(Py_3_13);\n\n    #[inline]\n    pub unsafe fn PyList_Clear(list: *mut crate::PyObject) -> std::ffi::c_int {\n        crate::PyList_SetSlice(list, 0, crate::PY_SSIZE_T_MAX, std::ptr::null_mut())\n    }\n);\n\ncompat_function!(\n    originally_defined_for(Py_3_13);\n\n    #[inline]\n    pub unsafe fn PyModule_Add(\n        module: *mut crate::PyObject,\n        name: *const std::ffi::c_char,\n        value: *mut crate::PyObject,\n    ) -> std::ffi::c_int {\n        let result = crate::compat::PyModule_AddObjectRef(module, name, value);\n        crate::Py_XDECREF(value);\n        result\n    }\n);\n\n#[cfg(not(Py_LIMITED_API))]\ncompat_function!(\n    originally_defined_for(Py_3_13);\n\n    #[inline]\n    pub unsafe fn PyThreadState_GetUnchecked(\n    ) -> *mut crate::PyThreadState {\n        crate::_PyThreadState_UncheckedGet()\n    }\n);\n"
  },
  {
    "path": "pyo3-ffi/src/compat/py_3_14.rs",
    "content": "compat_function!(\n    originally_defined_for(all(Py_3_14, not(Py_LIMITED_API)));\n\n    #[inline]\n    pub unsafe fn Py_HashBuffer(\n        ptr: *const std::ffi::c_void,\n        len: crate::Py_ssize_t,\n    ) -> crate::Py_hash_t {\n        #[cfg(not(any(Py_LIMITED_API, PyPy)))]\n        {\n            crate::_Py_HashBytes(ptr, len)\n        }\n\n        #[cfg(any(Py_LIMITED_API, PyPy))]\n        {\n            let bytes = crate::PyBytes_FromStringAndSize(ptr as *const std::ffi::c_char, len);\n            if bytes.is_null() {\n                -1\n            } else {\n                let result = crate::PyObject_Hash(bytes);\n                crate::Py_DECREF(bytes);\n                result\n            }\n        }\n    }\n);\n\ncompat_function!(\n    originally_defined_for(Py_3_14);\n\n    #[inline]\n    pub unsafe fn PyIter_NextItem(\n        iter: *mut crate::PyObject,\n        item: *mut *mut crate::PyObject,\n    ) -> std::ffi::c_int {\n        *item = crate::PyIter_Next(iter);\n        if !(*item).is_null() {\n            1\n        } else if crate::PyErr_Occurred().is_null() {\n            0\n        } else {\n            -1\n        }\n    }\n);\n"
  },
  {
    "path": "pyo3-ffi/src/compat/py_3_15.rs",
    "content": "#[cfg(all(Py_3_15, not(Py_LIMITED_API)))]\npub use crate::PyBytesWriter;\n\n#[cfg(not(Py_LIMITED_API))]\ncompat_function!(\n    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));\n\n    #[inline]\n    pub unsafe fn PyBytesWriter_Create(\n        size: crate::Py_ssize_t,\n    ) -> *mut PyBytesWriter {\n\n        if size < 0 {\n            crate::PyErr_SetString(crate::PyExc_ValueError, c\"size must be >= 0\".as_ptr() as *const _);\n            return std::ptr::null_mut();\n        }\n\n        let writer: *mut PyBytesWriter = crate::PyMem_Malloc(std::mem::size_of::<PyBytesWriter>()).cast();\n        if writer.is_null() {\n            crate::PyErr_NoMemory();\n            return std::ptr::null_mut();\n        }\n\n        (*writer).obj = std::ptr::null_mut();\n        (*writer).size = 0;\n\n        if size >=1 {\n            if _PyBytesWriter_Resize_impl(writer, size, 0) < 0 {\n                PyBytesWriter_Discard(writer);\n                return std::ptr::null_mut();\n            }\n\n            (*writer).size = size;\n        }\n\n        writer\n    }\n);\n\n#[cfg(not(Py_LIMITED_API))]\ncompat_function!(\n    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));\n\n    #[inline]\n    pub unsafe fn PyBytesWriter_Discard(writer: *mut PyBytesWriter) -> () {\n        if writer.is_null() {\n            return;\n        }\n\n        crate::Py_XDECREF((*writer).obj);\n        crate::PyMem_Free(writer.cast());\n    }\n);\n\n#[cfg(not(Py_LIMITED_API))]\ncompat_function!(\n    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));\n\n    #[inline]\n    pub unsafe fn PyBytesWriter_Finish(writer: *mut PyBytesWriter) -> *mut crate::PyObject {\n        PyBytesWriter_FinishWithSize(writer, (*writer).size)\n    }\n);\n\n#[cfg(not(Py_LIMITED_API))]\ncompat_function!(\n    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));\n\n    #[inline]\n    pub unsafe fn PyBytesWriter_FinishWithSize(writer: *mut PyBytesWriter, size: crate::Py_ssize_t) -> *mut crate::PyObject {\n        let result = if size == 0 {\n            crate::PyBytes_FromStringAndSize(c\"\".as_ptr(), 0)\n        } else if (*writer).obj.is_null() {\n            crate::PyBytes_FromStringAndSize((*writer).small_buffer.as_ptr(), size)\n        } else {\n            if size != crate::PyBytes_Size((*writer).obj) && crate::_PyBytes_Resize(&mut (*writer).obj, size) < 0 {\n                    PyBytesWriter_Discard(writer);\n                    return std::ptr::null_mut();\n            }\n            std::mem::replace(&mut (*writer).obj, std::ptr::null_mut())\n        };\n\n        PyBytesWriter_Discard(writer);\n        result\n    }\n);\n\n#[cfg(not(Py_LIMITED_API))]\ncompat_function!(\n    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));\n\n    #[inline]\n    pub unsafe fn PyBytesWriter_GetData(writer: *mut PyBytesWriter) -> *mut std::ffi::c_void {\n        if (*writer).obj.is_null() {\n            (*writer).small_buffer.as_ptr() as *mut _\n        } else {\n                crate::PyBytes_AS_STRING((*writer).obj) as *mut _\n        }\n    }\n);\n\n#[cfg(not(Py_LIMITED_API))]\ncompat_function!(\n    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));\n\n    #[inline]\n    pub unsafe fn PyBytesWriter_GetSize(writer: *mut PyBytesWriter) -> crate::Py_ssize_t {\n        (*writer).size\n    }\n);\n\n#[cfg(not(Py_LIMITED_API))]\ncompat_function!(\n    originally_defined_for(all(Py_3_15, not(Py_LIMITED_API)));\n\n    #[inline]\n    pub unsafe fn PyBytesWriter_Resize(writer: *mut PyBytesWriter, size: crate::Py_ssize_t) -> std::ffi::c_int {\n        if size < 0 {\n            crate::PyErr_SetString(crate::PyExc_ValueError, c\"size must be >= 0\".as_ptr());\n            return -1;\n        }\n        if _PyBytesWriter_Resize_impl(writer, size, 1) < 0 {\n            return -1;\n        }\n        (*writer).size = size;\n        0\n    }\n);\n\n#[repr(C)]\n#[cfg(not(any(Py_3_15, Py_LIMITED_API)))]\npub struct PyBytesWriter {\n    small_buffer: [std::ffi::c_char; 256],\n    obj: *mut crate::PyObject,\n    size: crate::Py_ssize_t,\n}\n\n#[inline]\n#[cfg(not(any(Py_3_15, Py_LIMITED_API)))]\nunsafe fn _PyBytesWriter_Resize_impl(\n    writer: *mut PyBytesWriter,\n    mut size: crate::Py_ssize_t,\n    resize: std::ffi::c_int,\n) -> std::ffi::c_int {\n    let overallocate = resize;\n    assert!(size >= 0);\n\n    let allocated = if (*writer).obj.is_null() {\n        std::mem::size_of_val(&(*writer).small_buffer) as _\n    } else {\n        crate::PyBytes_Size((*writer).obj)\n    };\n\n    if size <= allocated {\n        return 0;\n    }\n\n    if overallocate > 0 {\n        #[cfg(windows)]\n        if size <= (crate::PY_SSIZE_T_MAX - size / 2) {\n            size += size / 2;\n        }\n\n        #[cfg(not(windows))]\n        if size <= (crate::PY_SSIZE_T_MAX - size / 4) {\n            size += size / 4;\n        }\n    }\n\n    if !(*writer).obj.is_null() {\n        if crate::_PyBytes_Resize(&mut (*writer).obj, size) > 0 {\n            return -1;\n        }\n        assert!(!(*writer).obj.is_null())\n    } else {\n        (*writer).obj = crate::PyBytes_FromStringAndSize(std::ptr::null_mut(), size);\n        if (*writer).obj.is_null() {\n            return -1;\n        }\n\n        if resize > 0 {\n            assert!((size as usize) > std::mem::size_of_val(&(*writer).small_buffer));\n\n            std::ptr::copy_nonoverlapping(\n                (*writer).small_buffer.as_ptr(),\n                crate::PyBytes_AS_STRING((*writer).obj) as *mut _,\n                std::mem::size_of_val(&(*writer).small_buffer),\n            );\n        }\n    }\n\n    0\n}\n"
  },
  {
    "path": "pyo3-ffi/src/compat/py_3_9.rs",
    "content": "compat_function!(\n    originally_defined_for(all(\n        not(PyPy),\n        any(Py_3_10, all(not(Py_LIMITED_API), Py_3_9)) // Added to python in 3.9 but to limited API in 3.10\n    ));\n\n    #[inline]\n    pub unsafe fn PyObject_CallNoArgs(obj: *mut crate::PyObject) -> *mut crate::PyObject {\n        crate::PyObject_CallObject(obj, std::ptr::null_mut())\n    }\n);\n\ncompat_function!(\n    originally_defined_for(all(Py_3_9, not(any(Py_LIMITED_API, PyPy))));\n\n    #[inline]\n    pub unsafe fn PyObject_CallMethodNoArgs(obj: *mut crate::PyObject, name: *mut crate::PyObject) -> *mut crate::PyObject {\n        crate::PyObject_CallMethodObjArgs(obj, name, std::ptr::null_mut::<crate::PyObject>())\n    }\n);\n"
  },
  {
    "path": "pyo3-ffi/src/compile.rs",
    "content": "use std::ffi::c_int;\n\npub const Py_single_input: c_int = 256;\npub const Py_file_input: c_int = 257;\npub const Py_eval_input: c_int = 258;\n#[cfg(Py_3_8)]\npub const Py_func_type_input: c_int = 345;\n\n#[cfg(Py_3_9)]\npub const Py_fstring_input: c_int = 800;\n"
  },
  {
    "path": "pyo3-ffi/src/complexobject.rs",
    "content": "use crate::object::*;\nuse std::ffi::{c_double, c_int};\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyComplex_Type\")]\n    pub static mut PyComplex_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyComplex_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyComplex_Type)\n}\n\n#[inline]\npub unsafe fn PyComplex_CheckExact(op: *mut PyObject) -> c_int {\n    Py_IS_TYPE(op, &raw mut PyComplex_Type)\n}\n\nextern_libpython! {\n    // skipped non-limited PyComplex_FromCComplex\n    #[cfg_attr(PyPy, link_name = \"PyPyComplex_FromDoubles\")]\n    pub fn PyComplex_FromDoubles(real: c_double, imag: c_double) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyComplex_RealAsDouble\")]\n    pub fn PyComplex_RealAsDouble(op: *mut PyObject) -> c_double;\n    #[cfg_attr(PyPy, link_name = \"PyPyComplex_ImagAsDouble\")]\n    pub fn PyComplex_ImagAsDouble(op: *mut PyObject) -> c_double;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/context.rs",
    "content": "use crate::object::{PyObject, PyTypeObject, Py_TYPE};\nuse std::ffi::{c_char, c_int};\n\nextern_libpython! {\n    pub static mut PyContext_Type: PyTypeObject;\n    // skipped non-limited opaque PyContext\n    pub static mut PyContextVar_Type: PyTypeObject;\n    // skipped non-limited opaque PyContextVar\n    pub static mut PyContextToken_Type: PyTypeObject;\n    // skipped non-limited opaque PyContextToken\n}\n\n#[inline]\npub unsafe fn PyContext_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyContext_Type) as c_int\n}\n\n#[inline]\npub unsafe fn PyContextVar_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyContextVar_Type) as c_int\n}\n\n#[inline]\npub unsafe fn PyContextToken_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyContextToken_Type) as c_int\n}\n\nextern_libpython! {\n    pub fn PyContext_New() -> *mut PyObject;\n    pub fn PyContext_Copy(ctx: *mut PyObject) -> *mut PyObject;\n    pub fn PyContext_CopyCurrent() -> *mut PyObject;\n\n    pub fn PyContext_Enter(ctx: *mut PyObject) -> c_int;\n    pub fn PyContext_Exit(ctx: *mut PyObject) -> c_int;\n\n    pub fn PyContextVar_New(name: *const c_char, def: *mut PyObject) -> *mut PyObject;\n    pub fn PyContextVar_Get(\n        var: *mut PyObject,\n        default_value: *mut PyObject,\n        value: *mut *mut PyObject,\n    ) -> c_int;\n    pub fn PyContextVar_Set(var: *mut PyObject, value: *mut PyObject) -> *mut PyObject;\n    pub fn PyContextVar_Reset(var: *mut PyObject, token: *mut PyObject) -> c_int;\n    // skipped non-limited _PyContext_NewHamtForTests\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/abstract_.rs",
    "content": "use crate::{PyObject, Py_ssize_t};\n#[cfg(any(all(Py_3_8, not(PyPy)), not(Py_3_11)))]\nuse std::ffi::c_char;\nuse std::ffi::c_int;\n\n#[cfg(not(Py_3_11))]\nuse crate::Py_buffer;\n\n#[cfg(all(Py_3_8, not(PyPy)))]\nuse crate::{\n    vectorcallfunc, PyCallable_Check, PyThreadState, PyThreadState_GET, PyTuple_Check,\n    PyType_HasFeature, Py_TPFLAGS_HAVE_VECTORCALL,\n};\n#[cfg(Py_3_8)]\nuse libc::size_t;\n\nextern_libpython! {\n    #[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]\n    pub fn _PyStack_AsDict(values: *const *mut PyObject, kwnames: *mut PyObject) -> *mut PyObject;\n}\n\n#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]\nconst _PY_FASTCALL_SMALL_STACK: size_t = 5;\n\nextern_libpython! {\n    #[cfg(all(Py_3_8, not(PyPy)))]\n    pub fn _Py_CheckFunctionResult(\n        tstate: *mut PyThreadState,\n        callable: *mut PyObject,\n        result: *mut PyObject,\n        where_: *const c_char,\n    ) -> *mut PyObject;\n\n    #[cfg(all(Py_3_8, not(PyPy)))]\n    pub fn _PyObject_MakeTpCall(\n        tstate: *mut PyThreadState,\n        callable: *mut PyObject,\n        args: *const *mut PyObject,\n        nargs: Py_ssize_t,\n        keywords: *mut PyObject,\n    ) -> *mut PyObject;\n}\n\n#[cfg(Py_3_8)] // NB exported as public in abstract.rs from 3.12\nconst PY_VECTORCALL_ARGUMENTS_OFFSET: size_t =\n    1 << (8 * std::mem::size_of::<size_t>() as size_t - 1);\n\n#[cfg(Py_3_8)]\n#[inline(always)]\npub unsafe fn PyVectorcall_NARGS(n: size_t) -> Py_ssize_t {\n    let n = n & !PY_VECTORCALL_ARGUMENTS_OFFSET;\n    n.try_into().expect(\"cannot fail due to mask\")\n}\n\n#[cfg(all(Py_3_8, not(PyPy)))]\n#[inline(always)]\npub unsafe fn PyVectorcall_Function(callable: *mut PyObject) -> Option<vectorcallfunc> {\n    assert!(!callable.is_null());\n    let tp = crate::Py_TYPE(callable);\n    if PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL) == 0 {\n        return None;\n    }\n    assert!(PyCallable_Check(callable) > 0);\n    let offset = (*tp).tp_vectorcall_offset;\n    assert!(offset > 0);\n    let ptr = callable.cast::<c_char>().offset(offset).cast();\n    *ptr\n}\n\n#[cfg(all(Py_3_8, not(PyPy)))]\n#[inline(always)]\npub unsafe fn _PyObject_VectorcallTstate(\n    tstate: *mut PyThreadState,\n    callable: *mut PyObject,\n    args: *const *mut PyObject,\n    nargsf: size_t,\n    kwnames: *mut PyObject,\n) -> *mut PyObject {\n    assert!(kwnames.is_null() || PyTuple_Check(kwnames) > 0);\n    assert!(!args.is_null() || PyVectorcall_NARGS(nargsf) == 0);\n\n    match PyVectorcall_Function(callable) {\n        None => {\n            let nargs = PyVectorcall_NARGS(nargsf);\n            _PyObject_MakeTpCall(tstate, callable, args, nargs, kwnames)\n        }\n        Some(func) => {\n            let res = func(callable, args, nargsf, kwnames);\n            _Py_CheckFunctionResult(tstate, callable, res, std::ptr::null_mut())\n        }\n    }\n}\n\n#[cfg(all(Py_3_8, not(any(PyPy, GraalPy, Py_3_11))))] // exported as a function from 3.11, see abstract.rs\n#[inline(always)]\npub unsafe fn PyObject_Vectorcall(\n    callable: *mut PyObject,\n    args: *const *mut PyObject,\n    nargsf: size_t,\n    kwnames: *mut PyObject,\n) -> *mut PyObject {\n    _PyObject_VectorcallTstate(PyThreadState_GET(), callable, args, nargsf, kwnames)\n}\n\nextern_libpython! {\n    #[cfg(Py_3_8)]\n    #[cfg_attr(\n        all(not(any(PyPy, GraalPy)), not(Py_3_9)),\n        link_name = \"_PyObject_VectorcallDict\"\n    )]\n    #[cfg_attr(all(PyPy, not(Py_3_9)), link_name = \"_PyPyObject_VectorcallDict\")]\n    #[cfg_attr(all(PyPy, Py_3_9), link_name = \"PyPyObject_VectorcallDict\")]\n    pub fn PyObject_VectorcallDict(\n        callable: *mut PyObject,\n        args: *const *mut PyObject,\n        nargsf: size_t,\n        kwdict: *mut PyObject,\n    ) -> *mut PyObject;\n\n    #[cfg(Py_3_8)]\n    #[cfg_attr(not(any(Py_3_9, PyPy)), link_name = \"_PyVectorcall_Call\")]\n    #[cfg_attr(PyPy, link_name = \"PyPyVectorcall_Call\")]\n    pub fn PyVectorcall_Call(\n        callable: *mut PyObject,\n        tuple: *mut PyObject,\n        dict: *mut PyObject,\n    ) -> *mut PyObject;\n}\n\n#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]\n#[inline(always)]\npub unsafe fn _PyObject_FastCallTstate(\n    tstate: *mut PyThreadState,\n    func: *mut PyObject,\n    args: *const *mut PyObject,\n    nargs: Py_ssize_t,\n) -> *mut PyObject {\n    _PyObject_VectorcallTstate(tstate, func, args, nargs as size_t, std::ptr::null_mut())\n}\n\n#[cfg(all(Py_3_8, not(any(PyPy, GraalPy))))]\n#[inline(always)]\npub unsafe fn _PyObject_FastCall(\n    func: *mut PyObject,\n    args: *const *mut PyObject,\n    nargs: Py_ssize_t,\n) -> *mut PyObject {\n    _PyObject_FastCallTstate(PyThreadState_GET(), func, args, nargs)\n}\n\n#[cfg(all(Py_3_8, not(PyPy)))]\n#[inline(always)]\npub unsafe fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject {\n    _PyObject_VectorcallTstate(\n        PyThreadState_GET(),\n        func,\n        std::ptr::null_mut(),\n        0,\n        std::ptr::null_mut(),\n    )\n}\n\nextern_libpython! {\n    #[cfg(PyPy)]\n    #[link_name = \"_PyPyObject_CallNoArg\"]\n    pub fn _PyObject_CallNoArg(func: *mut PyObject) -> *mut PyObject;\n}\n\n#[cfg(all(Py_3_8, not(PyPy)))]\n#[inline(always)]\npub unsafe fn PyObject_CallOneArg(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject {\n    assert!(!arg.is_null());\n    let args_array = [std::ptr::null_mut(), arg];\n    let args = args_array.as_ptr().offset(1); // For PY_VECTORCALL_ARGUMENTS_OFFSET\n    let tstate = PyThreadState_GET();\n    let nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;\n    _PyObject_VectorcallTstate(tstate, func, args, nargsf, std::ptr::null_mut())\n}\n\n#[cfg(all(Py_3_9, not(PyPy)))]\n#[inline(always)]\npub unsafe fn PyObject_CallMethodNoArgs(\n    self_: *mut PyObject,\n    name: *mut PyObject,\n) -> *mut PyObject {\n    crate::PyObject_VectorcallMethod(\n        name,\n        &self_,\n        1 | PY_VECTORCALL_ARGUMENTS_OFFSET,\n        std::ptr::null_mut(),\n    )\n}\n\n#[cfg(all(Py_3_9, not(PyPy)))]\n#[inline(always)]\npub unsafe fn PyObject_CallMethodOneArg(\n    self_: *mut PyObject,\n    name: *mut PyObject,\n    arg: *mut PyObject,\n) -> *mut PyObject {\n    let args = [self_, arg];\n    assert!(!arg.is_null());\n    crate::PyObject_VectorcallMethod(\n        name,\n        args.as_ptr(),\n        2 | PY_VECTORCALL_ARGUMENTS_OFFSET,\n        std::ptr::null_mut(),\n    )\n}\n\n// skipped _PyObject_VectorcallMethodId\n// skipped _PyObject_CallMethodIdNoArgs\n// skipped _PyObject_CallMethodIdOneArg\n\n// skipped _PyObject_HasLen\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_LengthHint\")]\n    pub fn PyObject_LengthHint(o: *mut PyObject, arg1: Py_ssize_t) -> Py_ssize_t;\n\n    #[cfg(not(Py_3_11))] // moved to src/buffer.rs from 3.11\n    #[cfg(all(Py_3_9, not(PyPy)))]\n    pub fn PyObject_CheckBuffer(obj: *mut PyObject) -> c_int;\n}\n\n#[cfg(not(any(Py_3_9, PyPy)))]\n#[inline]\npub unsafe fn PyObject_CheckBuffer(o: *mut PyObject) -> c_int {\n    let tp_as_buffer = (*crate::Py_TYPE(o)).tp_as_buffer;\n    (!tp_as_buffer.is_null() && (*tp_as_buffer).bf_getbuffer.is_some()) as c_int\n}\n\n#[cfg(not(Py_3_11))] // moved to src/buffer.rs from 3.11\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GetBuffer\")]\n    pub fn PyObject_GetBuffer(obj: *mut PyObject, view: *mut Py_buffer, flags: c_int) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_GetPointer\")]\n    pub fn PyBuffer_GetPointer(\n        view: *mut Py_buffer,\n        indices: *mut Py_ssize_t,\n    ) -> *mut std::ffi::c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_SizeFromFormat\")]\n    pub fn PyBuffer_SizeFromFormat(format: *const c_char) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_ToContiguous\")]\n    pub fn PyBuffer_ToContiguous(\n        buf: *mut std::ffi::c_void,\n        view: *mut Py_buffer,\n        len: Py_ssize_t,\n        order: c_char,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_FromContiguous\")]\n    pub fn PyBuffer_FromContiguous(\n        view: *mut Py_buffer,\n        buf: *mut std::ffi::c_void,\n        len: Py_ssize_t,\n        order: c_char,\n    ) -> c_int;\n    pub fn PyObject_CopyData(dest: *mut PyObject, src: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_IsContiguous\")]\n    pub fn PyBuffer_IsContiguous(view: *const Py_buffer, fort: c_char) -> c_int;\n    pub fn PyBuffer_FillContiguousStrides(\n        ndims: c_int,\n        shape: *mut Py_ssize_t,\n        strides: *mut Py_ssize_t,\n        itemsize: c_int,\n        fort: c_char,\n    );\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_FillInfo\")]\n    pub fn PyBuffer_FillInfo(\n        view: *mut Py_buffer,\n        o: *mut PyObject,\n        buf: *mut std::ffi::c_void,\n        len: Py_ssize_t,\n        readonly: c_int,\n        flags: c_int,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_Release\")]\n    pub fn PyBuffer_Release(view: *mut Py_buffer);\n}\n\n// PyIter_Check defined in ffi/abstract_.rs\n// PyIndex_Check defined in ffi/abstract_.rs\n// Not defined here because this file is not compiled under the\n// limited API, but the macros need to be defined for 3.6, 3.7 which\n// predate the limited API changes.\n\n// skipped PySequence_ITEM\n\npub const PY_ITERSEARCH_COUNT: c_int = 1;\npub const PY_ITERSEARCH_INDEX: c_int = 2;\npub const PY_ITERSEARCH_CONTAINS: c_int = 3;\n\nextern_libpython! {\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn _PySequence_IterSearch(\n        seq: *mut PyObject,\n        obj: *mut PyObject,\n        operation: c_int,\n    ) -> Py_ssize_t;\n}\n\n// skipped _PyObject_RealIsInstance\n// skipped _PyObject_RealIsSubclass\n\n// skipped _PySequence_BytesToCharpArray\n\n// skipped _Py_FreeCharPArray\n\n// skipped _Py_add_one_to_index_F\n// skipped _Py_add_one_to_index_C\n\n// skipped _Py_convert_optional_to_ssize_t\n\n// skipped _PyNumber_Index(*mut PyObject o)\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/bytesobject.rs",
    "content": "use crate::object::*;\nuse crate::Py_ssize_t;\n#[cfg(not(Py_LIMITED_API))]\nuse std::ffi::c_char;\nuse std::ffi::c_int;\n#[cfg(Py_3_15)]\nuse std::ffi::c_void;\n\n#[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))]\n#[repr(C)]\npub struct PyBytesObject {\n    pub ob_base: PyVarObject,\n    #[cfg_attr(\n        Py_3_11,\n        deprecated(note = \"Deprecated in Python 3.11 and will be removed in a future version.\")\n    )]\n    pub ob_shash: crate::Py_hash_t,\n    pub ob_sval: [c_char; 1],\n}\n\n#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))]\nopaque_struct!(pub PyBytesObject);\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"_PyPyBytes_Resize\")]\n    pub fn _PyBytes_Resize(bytes: *mut *mut PyObject, newsize: Py_ssize_t) -> c_int;\n}\n\n#[cfg(not(Py_LIMITED_API))]\n#[inline]\npub unsafe fn PyBytes_AS_STRING(op: *mut PyObject) -> *const c_char {\n    #[cfg(not(any(PyPy, GraalPy)))]\n    return &(*op.cast::<PyBytesObject>()).ob_sval as *const c_char;\n    #[cfg(any(PyPy, GraalPy))]\n    return crate::PyBytes_AsString(op);\n}\n\n#[cfg(Py_3_15)]\nopaque_struct!(pub PyBytesWriter);\n\n#[cfg(Py_3_15)]\nextern_libpython! {\n\n    pub fn PyBytesWriter_Create(size: Py_ssize_t) -> *mut PyBytesWriter;\n\n    pub fn PyBytesWriter_Discard(writer: *mut PyBytesWriter);\n\n    pub fn PyBytesWriter_Finish(writer: *mut PyBytesWriter) -> *mut PyObject;\n\n    pub fn PyBytesWriter_FinishWithSize(\n        writer: *mut PyBytesWriter,\n        size: Py_ssize_t,\n    ) -> *mut PyObject;\n\n    pub fn PyBytesWriter_GetData(writer: *mut PyBytesWriter) -> *mut c_void;\n\n    pub fn PyBytesWriter_GetSize(writer: *mut PyBytesWriter) -> Py_ssize_t;\n\n    pub fn PyBytesWriter_Resize(writer: *mut PyBytesWriter, size: Py_ssize_t) -> c_int;\n\n    pub fn PyBytesWriter_Grow(writer: *mut PyBytesWriter, size: Py_ssize_t) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/ceval.rs",
    "content": "use crate::cpython::pystate::Py_tracefunc;\nuse crate::object::{freefunc, PyObject};\nuse std::ffi::c_int;\n\nextern_libpython! {\n    // skipped non-limited _PyEval_CallTracing\n\n    #[cfg(not(Py_3_11))]\n    pub fn _PyEval_EvalFrameDefault(arg1: *mut crate::PyFrameObject, exc: c_int) -> *mut PyObject;\n\n    #[cfg(Py_3_11)]\n    pub fn _PyEval_EvalFrameDefault(\n        tstate: *mut crate::PyThreadState,\n        frame: *mut crate::_PyInterpreterFrame,\n        exc: c_int,\n    ) -> *mut crate::PyObject;\n\n    pub fn _PyEval_RequestCodeExtraIndex(func: freefunc) -> c_int;\n    pub fn PyEval_SetProfile(trace_func: Option<Py_tracefunc>, arg1: *mut PyObject);\n    pub fn PyEval_SetTrace(trace_func: Option<Py_tracefunc>, arg1: *mut PyObject);\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/code.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\n\n#[cfg(not(GraalPy))]\nuse crate::PyCodeObject;\n#[cfg(not(GraalPy))]\nuse std::ffi::c_char;\nuse std::ffi::{c_int, c_void};\n\n// skipped private _PY_MONITORING_LOCAL_EVENTS\n// skipped private _PY_MONITORING_UNGROUPED_EVENTS\n// skipped private _PY_MONITORING_EVENTS\n\n// skipped private _PyLocalMonitors\n// skipped private _Py_GlobalMonitors\n\n// skipped private _Py_CODEUNIT\n\n// skipped private _Py_OPCODE\n// skipped private _Py_OPARG\n\n// skipped private _py_make_codeunit\n\n// skipped private _py_set_opcode\n\n// skipped private _Py_MAKE_CODEUNIT\n// skipped private _Py_SET_OPCODE\n\n// skipped private _PyCoCached\n// skipped private _PyCoLineInstrumentationData\n// skipped private _PyCoMonitoringData\n\n// skipped private _PyExecutorArray\n\n/* Masks for co_flags */\npub const CO_OPTIMIZED: c_int = 0x0001;\npub const CO_NEWLOCALS: c_int = 0x0002;\npub const CO_VARARGS: c_int = 0x0004;\npub const CO_VARKEYWORDS: c_int = 0x0008;\npub const CO_NESTED: c_int = 0x0010;\npub const CO_GENERATOR: c_int = 0x0020;\n/* The CO_NOFREE flag is set if there are no free or cell variables.\n   This information is redundant, but it allows a single flag test\n   to determine whether there is any extra work to be done when the\n   call frame it setup.\n*/\npub const CO_NOFREE: c_int = 0x0040;\n/* The CO_COROUTINE flag is set for coroutine functions (defined with\n``async def`` keywords) */\npub const CO_COROUTINE: c_int = 0x0080;\npub const CO_ITERABLE_COROUTINE: c_int = 0x0100;\npub const CO_ASYNC_GENERATOR: c_int = 0x0200;\n\npub const CO_FUTURE_DIVISION: c_int = 0x2000;\npub const CO_FUTURE_ABSOLUTE_IMPORT: c_int = 0x4000; /* do absolute imports by default */\npub const CO_FUTURE_WITH_STATEMENT: c_int = 0x8000;\npub const CO_FUTURE_PRINT_FUNCTION: c_int = 0x1_0000;\npub const CO_FUTURE_UNICODE_LITERALS: c_int = 0x2_0000;\n\npub const CO_FUTURE_BARRY_AS_BDFL: c_int = 0x4_0000;\npub const CO_FUTURE_GENERATOR_STOP: c_int = 0x8_0000;\n// skipped CO_FUTURE_ANNOTATIONS\n// skipped CO_CELL_NOT_AN_ARG\n\npub const CO_MAXBLOCKS: usize = 20;\n\n#[cfg(not(PyPy))]\nextern_libpython! {\n    pub static mut PyCode_Type: PyTypeObject;\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyCode_Check(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyCode_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyCode_Check\"]\n    pub fn PyCode_Check(op: *mut PyObject) -> c_int;\n}\n\n// skipped PyCode_GetNumFree (requires knowledge of code object layout)\n\nextern_libpython! {\n    #[cfg(not(GraalPy))]\n    #[cfg_attr(PyPy, link_name = \"PyPyCode_New\")]\n    pub fn PyCode_New(\n        argcount: c_int,\n        kwonlyargcount: c_int,\n        nlocals: c_int,\n        stacksize: c_int,\n        flags: c_int,\n        code: *mut PyObject,\n        consts: *mut PyObject,\n        names: *mut PyObject,\n        varnames: *mut PyObject,\n        freevars: *mut PyObject,\n        cellvars: *mut PyObject,\n        filename: *mut PyObject,\n        name: *mut PyObject,\n        firstlineno: c_int,\n        lnotab: *mut PyObject,\n    ) -> *mut PyCodeObject;\n    #[cfg(not(GraalPy))]\n    #[cfg(Py_3_8)]\n    pub fn PyCode_NewWithPosOnlyArgs(\n        argcount: c_int,\n        posonlyargcount: c_int,\n        kwonlyargcount: c_int,\n        nlocals: c_int,\n        stacksize: c_int,\n        flags: c_int,\n        code: *mut PyObject,\n        consts: *mut PyObject,\n        names: *mut PyObject,\n        varnames: *mut PyObject,\n        freevars: *mut PyObject,\n        cellvars: *mut PyObject,\n        filename: *mut PyObject,\n        name: *mut PyObject,\n        firstlineno: c_int,\n        lnotab: *mut PyObject,\n    ) -> *mut PyCodeObject;\n    #[cfg(not(GraalPy))]\n    #[cfg_attr(PyPy, link_name = \"PyPyCode_NewEmpty\")]\n    pub fn PyCode_NewEmpty(\n        filename: *const c_char,\n        funcname: *const c_char,\n        firstlineno: c_int,\n    ) -> *mut PyCodeObject;\n    #[cfg(not(GraalPy))]\n    pub fn PyCode_Addr2Line(arg1: *mut PyCodeObject, arg2: c_int) -> c_int;\n    // skipped PyCodeAddressRange \"for internal use only\"\n    // skipped _PyCode_CheckLineNumber\n    // skipped _PyCode_ConstantKey\n    pub fn PyCode_Optimize(\n        code: *mut PyObject,\n        consts: *mut PyObject,\n        names: *mut PyObject,\n        lnotab: *mut PyObject,\n    ) -> *mut PyObject;\n    pub fn _PyCode_GetExtra(\n        code: *mut PyObject,\n        index: Py_ssize_t,\n        extra: *const *mut c_void,\n    ) -> c_int;\n    pub fn _PyCode_SetExtra(code: *mut PyObject, index: Py_ssize_t, extra: *mut c_void) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/compile.rs",
    "content": "#[cfg(not(any(PyPy, Py_3_10)))]\nuse crate::object::PyObject;\n#[cfg(not(any(PyPy, Py_3_10)))]\nuse crate::pyarena::*;\n#[cfg(not(any(PyPy, Py_3_10)))]\nuse crate::pythonrun::*;\n#[cfg(not(any(PyPy, Py_3_10)))]\nuse crate::PyCodeObject;\nuse crate::INT_MAX;\n#[cfg(not(any(PyPy, Py_3_10)))]\nuse std::ffi::c_char;\nuse std::ffi::c_int;\n\n// skipped PyCF_MASK\n// skipped PyCF_MASK_OBSOLETE\n// skipped PyCF_SOURCE_IS_UTF8\n// skipped PyCF_DONT_IMPLY_DEDENT\n// skipped PyCF_ONLY_AST\n// skipped PyCF_IGNORE_COOKIE\n// skipped PyCF_TYPE_COMMENTS\n// skipped PyCF_ALLOW_TOP_LEVEL_AWAIT\n// skipped PyCF_OPTIMIZED_AST\n// skipped PyCF_COMPILE_MASK\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyCompilerFlags {\n    pub cf_flags: c_int,\n    #[cfg(Py_3_8)]\n    pub cf_feature_version: c_int,\n}\n\n// skipped _PyCompilerFlags_INIT\n\n// NB this type technically existed in the header until 3.13, when it was\n// moved to the internal CPython headers.\n//\n// We choose not to expose it in the public API past 3.10, as it is\n// not used in the public API past that point.\n#[cfg(not(any(PyPy, GraalPy, Py_3_10)))]\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyFutureFeatures {\n    pub ff_features: c_int,\n    pub ff_lineno: c_int,\n}\n\n// FIXME: these constants should probably be &CStr, if they are used at all\n\npub const FUTURE_NESTED_SCOPES: &str = \"nested_scopes\";\npub const FUTURE_GENERATORS: &str = \"generators\";\npub const FUTURE_DIVISION: &str = \"division\";\npub const FUTURE_ABSOLUTE_IMPORT: &str = \"absolute_import\";\npub const FUTURE_WITH_STATEMENT: &str = \"with_statement\";\npub const FUTURE_PRINT_FUNCTION: &str = \"print_function\";\npub const FUTURE_UNICODE_LITERALS: &str = \"unicode_literals\";\npub const FUTURE_BARRY_AS_BDFL: &str = \"barry_as_FLUFL\";\npub const FUTURE_GENERATOR_STOP: &str = \"generator_stop\";\npub const FUTURE_ANNOTATIONS: &str = \"annotations\";\n\n#[cfg(not(any(PyPy, GraalPy, Py_3_10)))]\nextern_libpython! {\n    pub fn PyNode_Compile(arg1: *mut _node, arg2: *const c_char) -> *mut PyCodeObject;\n\n    pub fn PyAST_CompileEx(\n        _mod: *mut _mod,\n        filename: *const c_char,\n        flags: *mut PyCompilerFlags,\n        optimize: c_int,\n        arena: *mut PyArena,\n    ) -> *mut PyCodeObject;\n\n    pub fn PyAST_CompileObject(\n        _mod: *mut _mod,\n        filename: *mut PyObject,\n        flags: *mut PyCompilerFlags,\n        optimize: c_int,\n        arena: *mut PyArena,\n    ) -> *mut PyCodeObject;\n\n    pub fn PyFuture_FromAST(_mod: *mut _mod, filename: *const c_char) -> *mut PyFutureFeatures;\n\n    pub fn PyFuture_FromASTObject(\n        _mod: *mut _mod,\n        filename: *mut PyObject,\n    ) -> *mut PyFutureFeatures;\n}\n\npub const PY_INVALID_STACK_EFFECT: c_int = INT_MAX;\n\nextern_libpython! {\n\n    pub fn PyCompile_OpcodeStackEffect(opcode: c_int, oparg: c_int) -> c_int;\n\n    #[cfg(Py_3_8)]\n    pub fn PyCompile_OpcodeStackEffectWithJump(opcode: c_int, oparg: c_int, jump: c_int) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/complexobject.rs",
    "content": "use crate::PyObject;\nuse std::ffi::c_double;\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct Py_complex {\n    pub real: c_double,\n    pub imag: c_double,\n}\n\n// skipped private function _Py_c_sum\n// skipped private function _Py_c_diff\n// skipped private function _Py_c_neg\n// skipped private function _Py_c_prod\n// skipped private function _Py_c_quot\n// skipped private function _Py_c_pow\n// skipped private function _Py_c_abs\n\n#[repr(C)]\npub struct PyComplexObject {\n    pub ob_base: PyObject,\n    pub cval: Py_complex,\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyComplex_FromCComplex\")]\n    pub fn PyComplex_FromCComplex(v: Py_complex) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyComplex_AsCComplex\")]\n    pub fn PyComplex_AsCComplex(op: *mut PyObject) -> Py_complex;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/critical_section.rs",
    "content": "#[cfg(any(Py_3_14, Py_GIL_DISABLED))]\nuse crate::PyMutex;\nuse crate::PyObject;\n\n#[repr(C)]\n#[cfg(Py_GIL_DISABLED)]\npub struct PyCriticalSection {\n    _cs_prev: usize,\n    _cs_mutex: *mut PyMutex,\n}\n\n#[repr(C)]\n#[cfg(Py_GIL_DISABLED)]\npub struct PyCriticalSection2 {\n    _cs_base: PyCriticalSection,\n    _cs_mutex2: *mut PyMutex,\n}\n\n#[cfg(not(Py_GIL_DISABLED))]\nopaque_struct!(pub PyCriticalSection);\n\n#[cfg(not(Py_GIL_DISABLED))]\nopaque_struct!(pub PyCriticalSection2);\n\nextern_libpython! {\n    pub fn PyCriticalSection_Begin(c: *mut PyCriticalSection, op: *mut PyObject);\n    #[cfg(Py_3_14)]\n    pub fn PyCriticalSection_BeginMutex(c: *mut PyCriticalSection, m: *mut PyMutex);\n    pub fn PyCriticalSection_End(c: *mut PyCriticalSection);\n    pub fn PyCriticalSection2_Begin(c: *mut PyCriticalSection2, a: *mut PyObject, b: *mut PyObject);\n    #[cfg(Py_3_14)]\n    pub fn PyCriticalSection2_BeginMutex(\n        c: *mut PyCriticalSection2,\n        m1: *mut PyMutex,\n        m2: *mut PyMutex,\n    );\n    pub fn PyCriticalSection2_End(c: *mut PyCriticalSection2);\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/descrobject.rs",
    "content": "use crate::{PyGetSetDef, PyMethodDef, PyObject, PyTypeObject};\nuse std::ffi::{c_char, c_int, c_void};\n\n#[cfg(Py_3_11)]\nuse crate::PyMemberDef;\n\npub type wrapperfunc = Option<\n    unsafe extern \"C\" fn(\n        slf: *mut PyObject,\n        args: *mut PyObject,\n        wrapped: *mut c_void,\n    ) -> *mut PyObject,\n>;\n\npub type wrapperfunc_kwds = Option<\n    unsafe extern \"C\" fn(\n        slf: *mut PyObject,\n        args: *mut PyObject,\n        wrapped: *mut c_void,\n        kwds: *mut PyObject,\n    ) -> *mut PyObject,\n>;\n\n#[repr(C)]\npub struct wrapperbase {\n    pub name: *const c_char,\n    pub offset: c_int,\n    pub function: *mut c_void,\n    pub wrapper: wrapperfunc,\n    pub doc: *const c_char,\n    pub flags: c_int,\n    pub name_strobj: *mut PyObject,\n}\n\npub const PyWrapperFlag_KEYWORDS: c_int = 1;\n\n#[repr(C)]\npub struct PyDescrObject {\n    pub ob_base: PyObject,\n    pub d_type: *mut PyTypeObject,\n    pub d_name: *mut PyObject,\n    pub d_qualname: *mut PyObject,\n}\n\n// skipped non-limited PyDescr_TYPE\n// skipped non-limited PyDescr_NAME\n\n#[repr(C)]\npub struct PyMethodDescrObject {\n    pub d_common: PyDescrObject,\n    pub d_method: *mut PyMethodDef,\n    #[cfg(all(not(PyPy), Py_3_8))]\n    pub vectorcall: Option<crate::vectorcallfunc>,\n}\n\n#[repr(C)]\npub struct PyMemberDescrObject {\n    pub d_common: PyDescrObject,\n    #[cfg(not(Py_3_11))]\n    pub d_member: *mut PyGetSetDef,\n    #[cfg(Py_3_11)]\n    pub d_member: *mut PyMemberDef,\n}\n\n#[repr(C)]\npub struct PyGetSetDescrObject {\n    pub d_common: PyDescrObject,\n    pub d_getset: *mut PyGetSetDef,\n}\n\n#[repr(C)]\npub struct PyWrapperDescrObject {\n    pub d_common: PyDescrObject,\n    pub d_base: *mut wrapperbase,\n    pub d_wrapped: *mut c_void,\n}\n\n// skipped _PyMethodWrapper_Type\n\n// skipped non-limited PyDescr_NewWrapper\n// skipped non-limited PyDescr_IsData\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/dictobject.rs",
    "content": "#[cfg(not(GraalPy))]\nuse crate::object::*;\n#[cfg(not(any(PyPy, GraalPy)))]\nuse crate::pyport::Py_ssize_t;\n\n#[cfg(not(PyPy))]\nopaque_struct!(pub PyDictKeysObject);\n\n#[cfg(Py_3_11)]\n#[cfg(not(PyPy))]\nopaque_struct!(pub PyDictValues);\n\n#[cfg(not(any(GraalPy, PyPy)))]\n#[repr(C)]\n#[derive(Debug)]\npub struct PyDictObject {\n    pub ob_base: PyObject,\n    pub ma_used: Py_ssize_t,\n    #[cfg_attr(\n        Py_3_12,\n        deprecated(note = \"Deprecated in Python 3.12 and will be removed in the future.\")\n    )]\n    #[cfg(not(Py_3_14))]\n    pub ma_version_tag: u64,\n    #[cfg(Py_3_14)]\n    _ma_watcher_tag: u64,\n    pub ma_keys: *mut PyDictKeysObject,\n    #[cfg(not(Py_3_11))]\n    pub ma_values: *mut *mut PyObject,\n    #[cfg(Py_3_11)]\n    pub ma_values: *mut PyDictValues,\n}\n\n#[cfg(PyPy)]\n#[repr(C)]\n#[derive(Debug)]\npub struct PyDictObject {\n    pub ob_base: PyObject,\n    _tmpkeys: *mut PyObject,\n}\n\n// skipped private _PyDict_GetItem_KnownHash\n// skipped private _PyDict_GetItemStringWithError\n\n// skipped PyDict_SetDefault\n// skipped PyDict_SetDefaultRef\n\n// skipped PyDict_GET_SIZE\n// skipped PyDict_ContainsString\n\n// skipped private _PyDict_NewPresized\n\n// skipped PyDict_Pop\n// skipped PyDict_PopString\n\n// skipped private _PyDict_Pop\n\n// skipped PY_FOREACH_DICT_EVENT\n// skipped PyDict_WatchEvent\n\n// skipped PyDict_WatchCallback\n\n// skipped PyDict_AddWatcher\n// skipped PyDict_ClearWatcher\n\n// skipped PyDict_Watch\n// skipped PyDict_Unwatch\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/floatobject.rs",
    "content": "#[cfg(GraalPy)]\nuse crate::PyFloat_AsDouble;\nuse crate::{PyFloat_Check, PyObject};\nuse std::ffi::c_double;\n\n#[repr(C)]\npub struct PyFloatObject {\n    pub ob_base: PyObject,\n    pub ob_fval: c_double,\n}\n\n#[inline]\npub unsafe fn _PyFloat_CAST(op: *mut PyObject) -> *mut PyFloatObject {\n    debug_assert_eq!(PyFloat_Check(op), 1);\n    op.cast()\n}\n\n#[inline]\npub unsafe fn PyFloat_AS_DOUBLE(op: *mut PyObject) -> c_double {\n    #[cfg(not(GraalPy))]\n    return (*_PyFloat_CAST(op)).ob_fval;\n    #[cfg(GraalPy)]\n    return PyFloat_AsDouble(op);\n}\n\n// skipped PyFloat_Pack2\n// skipped PyFloat_Pack4\n// skipped PyFloat_Pack8\n\n// skipped PyFloat_Unpack2\n// skipped PyFloat_Unpack4\n// skipped PyFloat_Unpack8\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/frameobject.rs",
    "content": "#[cfg(not(GraalPy))]\nuse crate::object::*;\n#[cfg(not(GraalPy))]\nuse crate::PyCodeObject;\nuse crate::PyFrameObject;\n#[cfg(not(GraalPy))]\nuse crate::PyThreadState;\n#[cfg(not(any(PyPy, GraalPy, Py_3_11)))]\nuse std::ffi::c_char;\nuse std::ffi::c_int;\n\n#[cfg(not(any(PyPy, GraalPy, Py_3_11)))]\npub type PyFrameState = c_char;\n\n#[repr(C)]\n#[derive(Copy, Clone)]\n#[cfg(not(any(PyPy, GraalPy, Py_3_11)))]\npub struct PyTryBlock {\n    pub b_type: c_int,\n    pub b_handler: c_int,\n    pub b_level: c_int,\n}\n\n// skipped _PyFrame_IsRunnable\n// skipped _PyFrame_IsExecuting\n// skipped _PyFrameHasCompleted\n\nextern_libpython! {\n    #[cfg(not(GraalPy))]\n    #[cfg_attr(PyPy, link_name = \"PyPyFrame_New\")]\n    pub fn PyFrame_New(\n        tstate: *mut PyThreadState,\n        code: *mut PyCodeObject,\n        globals: *mut PyObject,\n        locals: *mut PyObject,\n    ) -> *mut PyFrameObject;\n    // skipped _PyFrame_New_NoTrack\n\n    pub fn PyFrame_BlockSetup(f: *mut PyFrameObject, _type: c_int, handler: c_int, level: c_int);\n    #[cfg(not(any(PyPy, GraalPy, Py_3_11)))]\n    pub fn PyFrame_BlockPop(f: *mut PyFrameObject) -> *mut PyTryBlock;\n\n    pub fn PyFrame_LocalsToFast(f: *mut PyFrameObject, clear: c_int);\n    pub fn PyFrame_FastToLocalsWithError(f: *mut PyFrameObject) -> c_int;\n    pub fn PyFrame_FastToLocals(f: *mut PyFrameObject);\n\n    // skipped _PyFrame_DebugMallocStats\n\n    #[cfg(not(Py_3_9))]\n    pub fn PyFrame_ClearFreeList() -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/funcobject.rs",
    "content": "use crate::PyObject;\nuse std::ffi::c_int;\n\n#[cfg(all(not(any(PyPy, GraalPy)), not(Py_3_10)))]\n#[repr(C)]\npub struct PyFunctionObject {\n    pub ob_base: PyObject,\n    pub func_code: *mut PyObject,\n    pub func_globals: *mut PyObject,\n    pub func_defaults: *mut PyObject,\n    pub func_kwdefaults: *mut PyObject,\n    pub func_closure: *mut PyObject,\n    pub func_doc: *mut PyObject,\n    pub func_name: *mut PyObject,\n    pub func_dict: *mut PyObject,\n    pub func_weakreflist: *mut PyObject,\n    pub func_module: *mut PyObject,\n    pub func_annotations: *mut PyObject,\n    pub func_qualname: *mut PyObject,\n    #[cfg(Py_3_8)]\n    pub vectorcall: Option<crate::vectorcallfunc>,\n}\n\n#[cfg(all(not(any(PyPy, GraalPy)), Py_3_10))]\n#[repr(C)]\npub struct PyFunctionObject {\n    pub ob_base: PyObject,\n    pub func_globals: *mut PyObject,\n    pub func_builtins: *mut PyObject,\n    pub func_name: *mut PyObject,\n    pub func_qualname: *mut PyObject,\n    pub func_code: *mut PyObject,\n    pub func_defaults: *mut PyObject,\n    pub func_kwdefaults: *mut PyObject,\n    pub func_closure: *mut PyObject,\n    pub func_doc: *mut PyObject,\n    pub func_dict: *mut PyObject,\n    pub func_weakreflist: *mut PyObject,\n    pub func_module: *mut PyObject,\n    pub func_annotations: *mut PyObject,\n    #[cfg(Py_3_14)]\n    pub func_annotate: *mut PyObject,\n    #[cfg(Py_3_12)]\n    pub func_typeparams: *mut PyObject,\n    pub vectorcall: Option<crate::vectorcallfunc>,\n    #[cfg(Py_3_11)]\n    pub func_version: u32,\n}\n\n#[cfg(PyPy)]\n#[repr(C)]\npub struct PyFunctionObject {\n    pub ob_base: PyObject,\n    pub func_name: *mut PyObject,\n}\n\n#[cfg(GraalPy)]\npub struct PyFunctionObject {\n    pub ob_base: PyObject,\n}\n\nextern_libpython! {\n    #[cfg(not(all(PyPy, not(Py_3_8))))]\n    #[cfg_attr(PyPy, link_name = \"PyPyFunction_Type\")]\n    pub static mut PyFunction_Type: crate::PyTypeObject;\n}\n\n#[cfg(not(all(PyPy, not(Py_3_8))))]\n#[inline]\npub unsafe fn PyFunction_Check(op: *mut PyObject) -> c_int {\n    (crate::Py_TYPE(op) == &raw mut PyFunction_Type) as c_int\n}\n\nextern_libpython! {\n    pub fn PyFunction_New(code: *mut PyObject, globals: *mut PyObject) -> *mut PyObject;\n    pub fn PyFunction_NewWithQualName(\n        code: *mut PyObject,\n        globals: *mut PyObject,\n        qualname: *mut PyObject,\n    ) -> *mut PyObject;\n    pub fn PyFunction_GetCode(op: *mut PyObject) -> *mut PyObject;\n    pub fn PyFunction_GetGlobals(op: *mut PyObject) -> *mut PyObject;\n    pub fn PyFunction_GetModule(op: *mut PyObject) -> *mut PyObject;\n    pub fn PyFunction_GetDefaults(op: *mut PyObject) -> *mut PyObject;\n    pub fn PyFunction_SetDefaults(op: *mut PyObject, defaults: *mut PyObject) -> c_int;\n    pub fn PyFunction_GetKwDefaults(op: *mut PyObject) -> *mut PyObject;\n    pub fn PyFunction_SetKwDefaults(op: *mut PyObject, defaults: *mut PyObject) -> c_int;\n    pub fn PyFunction_GetClosure(op: *mut PyObject) -> *mut PyObject;\n    pub fn PyFunction_SetClosure(op: *mut PyObject, closure: *mut PyObject) -> c_int;\n    pub fn PyFunction_GetAnnotations(op: *mut PyObject) -> *mut PyObject;\n    pub fn PyFunction_SetAnnotations(op: *mut PyObject, annotations: *mut PyObject) -> c_int;\n}\n\n// skipped _PyFunction_Vectorcall\n// skipped PyFunction_GET_CODE\n// skipped PyFunction_GET_GLOBALS\n// skipped PyFunction_GET_MODULE\n// skipped PyFunction_GET_DEFAULTS\n// skipped PyFunction_GET_KW_DEFAULTS\n// skipped PyFunction_GET_CLOSURE\n// skipped PyFunction_GET_ANNOTATIONS\n\n// skipped PyClassMethod_Type\n// skipped PyStaticMethod_Type\n// skipped PyClassMethod_New\n// skipped PyStaticMethod_New\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/genobject.rs",
    "content": "use crate::object::*;\nuse crate::PyFrameObject;\n#[cfg(all(Py_3_11, not(any(PyPy, GraalPy, Py_3_14))))]\nuse std::ffi::c_char;\nuse std::ffi::c_int;\n\n#[cfg(not(any(PyPy, GraalPy, Py_3_14)))]\n#[repr(C)]\npub struct PyGenObject {\n    pub ob_base: PyObject,\n    #[cfg(not(Py_3_11))]\n    pub gi_frame: *mut PyFrameObject,\n    #[cfg(not(Py_3_10))]\n    pub gi_running: c_int,\n    #[cfg(not(Py_3_12))]\n    pub gi_code: *mut PyObject,\n    pub gi_weakreflist: *mut PyObject,\n    pub gi_name: *mut PyObject,\n    pub gi_qualname: *mut PyObject,\n    #[allow(\n        private_interfaces,\n        reason = \"PyGenObject layout was public until 3.14\"\n    )]\n    pub gi_exc_state: crate::cpython::pystate::_PyErr_StackItem,\n    #[cfg(Py_3_11)]\n    pub gi_origin_or_finalizer: *mut PyObject,\n    #[cfg(Py_3_11)]\n    pub gi_hooks_inited: c_char,\n    #[cfg(Py_3_11)]\n    pub gi_closed: c_char,\n    #[cfg(Py_3_11)]\n    pub gi_running_async: c_char,\n    #[cfg(Py_3_11)]\n    pub gi_frame_state: i8,\n    #[cfg(Py_3_11)]\n    pub gi_iframe: [*mut PyObject; 1],\n}\n\n#[cfg(all(Py_3_14, not(any(PyPy, GraalPy))))]\nopaque_struct!(pub PyGenObject);\n\nextern_libpython! {\n    pub static mut PyGen_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyGen_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyGen_Type)\n}\n\n#[inline]\npub unsafe fn PyGen_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyGen_Type) as c_int\n}\n\nextern_libpython! {\n    pub fn PyGen_New(frame: *mut PyFrameObject) -> *mut PyObject;\n    // skipped PyGen_NewWithQualName\n    // skipped _PyGen_SetStopIterationValue\n    // skipped _PyGen_FetchStopIterationValue\n    // skipped _PyGen_yf\n    // skipped _PyGen_Finalize\n    #[cfg(not(any(Py_3_9, PyPy)))]\n    #[deprecated(note = \"This function was never documented in the Python API.\")]\n    pub fn PyGen_NeedsFinalizing(op: *mut PyGenObject) -> c_int;\n}\n\n// skipped PyCoroObject\n\nextern_libpython! {\n    pub static mut PyCoro_Type: PyTypeObject;\n}\n\n// skipped _PyCoroWrapper_Type\n\n#[inline]\npub unsafe fn PyCoro_CheckExact(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyCoro_Type)\n}\n\n// skipped _PyCoro_GetAwaitableIter\n// skipped PyCoro_New\n\n// skipped PyAsyncGenObject\n\nextern_libpython! {\n    pub static mut PyAsyncGen_Type: PyTypeObject;\n    // skipped _PyAsyncGenASend_Type\n    // skipped _PyAsyncGenWrappedValue_Type\n    // skipped _PyAsyncGenAThrow_Type\n}\n\n// skipped PyAsyncGen_New\n\n#[inline]\npub unsafe fn PyAsyncGen_CheckExact(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyAsyncGen_Type)\n}\n\n// skipped _PyAsyncGenValueWrapperNew\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/import.rs",
    "content": "#[cfg(any(not(PyPy), Py_3_14))]\nuse crate::PyObject;\n#[cfg(any(not(PyPy), Py_3_14))]\nuse std::ffi::c_char;\n#[cfg(not(PyPy))]\nuse std::ffi::{c_int, c_uchar};\n\n#[cfg(not(PyPy))]\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct _inittab {\n    pub name: *const c_char,\n    pub initfunc: Option<unsafe extern \"C\" fn() -> *mut PyObject>,\n}\n\nextern_libpython! {\n    #[cfg(not(PyPy))]\n    pub static mut PyImport_Inittab: *mut _inittab;\n\n    #[cfg(not(PyPy))]\n    pub fn PyImport_ExtendInittab(newtab: *mut _inittab) -> c_int;\n}\n\n#[cfg(not(PyPy))]\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct _frozen {\n    pub name: *const c_char,\n    pub code: *const c_uchar,\n    pub size: c_int,\n    #[cfg(Py_3_11)]\n    pub is_package: c_int,\n    #[cfg(all(Py_3_11, not(Py_3_13)))]\n    pub get_code: Option<unsafe extern \"C\" fn() -> *mut PyObject>,\n}\n\nextern_libpython! {\n    #[cfg(not(PyPy))]\n    pub static mut PyImport_FrozenModules: *const _frozen;\n\n    #[cfg(Py_3_14)]\n    pub fn PyImport_ImportModuleAttr(\n        mod_name: *mut PyObject,\n        attr_name: *mut PyObject,\n    ) -> *mut PyObject;\n    #[cfg(Py_3_14)]\n    pub fn PyImport_ImportModuleAttrString(\n        mod_name: *const c_char,\n        attr_name: *const c_char,\n    ) -> *mut PyObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/initconfig.rs",
    "content": "/* --- PyStatus ----------------------------------------------- */\n\nuse crate::Py_ssize_t;\nuse libc::wchar_t;\nuse std::ffi::{c_char, c_int, c_ulong};\n\n#[repr(C)]\n#[derive(Copy, Clone, Debug, PartialEq, Eq)]\npub enum _PyStatus_TYPE {\n    _PyStatus_TYPE_OK = 0,\n    _PyStatus_TYPE_ERROR = 1,\n    _PyStatus_TYPE_EXIT = 2,\n}\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyStatus {\n    pub _type: _PyStatus_TYPE,\n    pub func: *const c_char,\n    pub err_msg: *const c_char,\n    pub exitcode: c_int,\n}\n\nextern_libpython! {\n    pub fn PyStatus_Ok() -> PyStatus;\n    pub fn PyStatus_Error(err_msg: *const c_char) -> PyStatus;\n    pub fn PyStatus_NoMemory() -> PyStatus;\n    pub fn PyStatus_Exit(exitcode: c_int) -> PyStatus;\n    pub fn PyStatus_IsError(err: PyStatus) -> c_int;\n    pub fn PyStatus_IsExit(err: PyStatus) -> c_int;\n    pub fn PyStatus_Exception(err: PyStatus) -> c_int;\n}\n\n/* --- PyWideStringList ------------------------------------------------ */\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyWideStringList {\n    pub length: Py_ssize_t,\n    pub items: *mut *mut wchar_t,\n}\n\nextern_libpython! {\n    pub fn PyWideStringList_Append(list: *mut PyWideStringList, item: *const wchar_t) -> PyStatus;\n    pub fn PyWideStringList_Insert(\n        list: *mut PyWideStringList,\n        index: Py_ssize_t,\n        item: *const wchar_t,\n    ) -> PyStatus;\n}\n\n/* --- PyPreConfig ----------------------------------------------- */\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyPreConfig {\n    pub _config_init: c_int,\n    pub parse_argv: c_int,\n    pub isolated: c_int,\n    pub use_environment: c_int,\n    pub configure_locale: c_int,\n    pub coerce_c_locale: c_int,\n    pub coerce_c_locale_warn: c_int,\n\n    #[cfg(windows)]\n    pub legacy_windows_fs_encoding: c_int,\n\n    pub utf8_mode: c_int,\n    pub dev_mode: c_int,\n    pub allocator: c_int,\n}\n\nextern_libpython! {\n    pub fn PyPreConfig_InitPythonConfig(config: *mut PyPreConfig);\n    pub fn PyPreConfig_InitIsolatedConfig(config: *mut PyPreConfig);\n}\n\n/* --- PyConfig ---------------------------------------------- */\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyConfig {\n    pub _config_init: c_int,\n    pub isolated: c_int,\n    pub use_environment: c_int,\n    pub dev_mode: c_int,\n    pub install_signal_handlers: c_int,\n    pub use_hash_seed: c_int,\n    pub hash_seed: c_ulong,\n    pub faulthandler: c_int,\n    #[cfg(all(Py_3_9, not(Py_3_10)))]\n    pub _use_peg_parser: c_int,\n    pub tracemalloc: c_int,\n    #[cfg(Py_3_12)]\n    pub perf_profiling: c_int,\n    #[cfg(Py_3_14)]\n    pub remote_debug: c_int,\n    pub import_time: c_int,\n    #[cfg(Py_3_11)]\n    pub code_debug_ranges: c_int,\n    pub show_ref_count: c_int,\n    #[cfg(not(Py_3_9))]\n    pub show_alloc_count: c_int,\n    pub dump_refs: c_int,\n    #[cfg(Py_3_11)]\n    pub dump_refs_file: *mut wchar_t,\n    pub malloc_stats: c_int,\n    pub filesystem_encoding: *mut wchar_t,\n    pub filesystem_errors: *mut wchar_t,\n    pub pycache_prefix: *mut wchar_t,\n    pub parse_argv: c_int,\n    #[cfg(Py_3_10)]\n    pub orig_argv: PyWideStringList,\n    pub argv: PyWideStringList,\n    #[cfg(not(Py_3_10))]\n    pub program_name: *mut wchar_t,\n    pub xoptions: PyWideStringList,\n    pub warnoptions: PyWideStringList,\n    pub site_import: c_int,\n    pub bytes_warning: c_int,\n    #[cfg(Py_3_10)]\n    pub warn_default_encoding: c_int,\n    pub inspect: c_int,\n    pub interactive: c_int,\n    pub optimization_level: c_int,\n    pub parser_debug: c_int,\n    pub write_bytecode: c_int,\n    pub verbose: c_int,\n    pub quiet: c_int,\n    pub user_site_directory: c_int,\n    pub configure_c_stdio: c_int,\n    pub buffered_stdio: c_int,\n    pub stdio_encoding: *mut wchar_t,\n    pub stdio_errors: *mut wchar_t,\n\n    #[cfg(windows)]\n    pub legacy_windows_stdio: c_int,\n\n    pub check_hash_pycs_mode: *mut wchar_t,\n    #[cfg(Py_3_11)]\n    pub use_frozen_modules: c_int,\n    #[cfg(Py_3_11)]\n    pub safe_path: c_int,\n    #[cfg(Py_3_12)]\n    pub int_max_str_digits: c_int,\n    #[cfg(Py_3_14)]\n    pub thread_inherit_context: c_int,\n    #[cfg(Py_3_14)]\n    pub context_aware_warnings: c_int,\n    #[cfg(all(Py_3_14, target_os = \"macos\"))]\n    pub use_system_logger: c_int,\n    #[cfg(Py_3_13)]\n    pub cpu_count: c_int,\n    #[cfg(Py_GIL_DISABLED)]\n    pub enable_gil: c_int,\n    #[cfg(all(Py_3_14, Py_GIL_DISABLED))]\n    pub tlbc_enabled: c_int,\n    #[cfg(Py_3_15)]\n    pub lazy_imports: c_int,\n    pub pathconfig_warnings: c_int,\n    #[cfg(Py_3_10)]\n    pub program_name: *mut wchar_t,\n    pub pythonpath_env: *mut wchar_t,\n    pub home: *mut wchar_t,\n    #[cfg(Py_3_10)]\n    pub platlibdir: *mut wchar_t,\n\n    pub module_search_paths_set: c_int,\n    pub module_search_paths: PyWideStringList,\n    #[cfg(Py_3_11)]\n    pub stdlib_dir: *mut wchar_t,\n    pub executable: *mut wchar_t,\n    pub base_executable: *mut wchar_t,\n    pub prefix: *mut wchar_t,\n    pub base_prefix: *mut wchar_t,\n    pub exec_prefix: *mut wchar_t,\n    pub base_exec_prefix: *mut wchar_t,\n    #[cfg(all(Py_3_9, not(Py_3_10)))]\n    pub platlibdir: *mut wchar_t,\n    pub skip_source_first_line: c_int,\n    pub run_command: *mut wchar_t,\n    pub run_module: *mut wchar_t,\n    pub run_filename: *mut wchar_t,\n    #[cfg(Py_3_13)]\n    pub sys_path_0: *mut wchar_t,\n    pub _install_importlib: c_int,\n    pub _init_main: c_int,\n    #[cfg(all(Py_3_9, not(Py_3_12)))]\n    pub _isolated_interpreter: c_int,\n    #[cfg(Py_3_11)]\n    pub _is_python_build: c_int,\n    #[cfg(all(Py_3_9, not(Py_3_10)))]\n    pub _orig_argv: PyWideStringList,\n    #[cfg(all(Py_3_13, py_sys_config = \"Py_DEBUG\"))]\n    pub run_presite: *mut wchar_t,\n}\n\nextern_libpython! {\n    pub fn PyConfig_InitPythonConfig(config: *mut PyConfig);\n    pub fn PyConfig_InitIsolatedConfig(config: *mut PyConfig);\n    pub fn PyConfig_Clear(config: *mut PyConfig);\n    pub fn PyConfig_SetString(\n        config: *mut PyConfig,\n        config_str: *mut *mut wchar_t,\n        str: *const wchar_t,\n    ) -> PyStatus;\n    pub fn PyConfig_SetBytesString(\n        config: *mut PyConfig,\n        config_str: *mut *mut wchar_t,\n        str: *const c_char,\n    ) -> PyStatus;\n    pub fn PyConfig_Read(config: *mut PyConfig) -> PyStatus;\n    pub fn PyConfig_SetBytesArgv(\n        config: *mut PyConfig,\n        argc: Py_ssize_t,\n        argv: *mut *const c_char,\n    ) -> PyStatus;\n    pub fn PyConfig_SetArgv(\n        config: *mut PyConfig,\n        argc: Py_ssize_t,\n        argv: *mut *const wchar_t,\n    ) -> PyStatus;\n    pub fn PyConfig_SetWideStringList(\n        config: *mut PyConfig,\n        list: *mut PyWideStringList,\n        length: Py_ssize_t,\n        items: *mut *mut wchar_t,\n    ) -> PyStatus;\n}\n\n/* --- Helper functions --------------------------------------- */\n\nextern_libpython! {\n    pub fn Py_GetArgcArgv(argc: *mut c_int, argv: *mut *mut *mut wchar_t);\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/listobject.rs",
    "content": "use crate::object::*;\n#[cfg(not(PyPy))]\nuse crate::pyport::Py_ssize_t;\n\n#[cfg(not(PyPy))]\n#[repr(C)]\npub struct PyListObject {\n    pub ob_base: PyVarObject,\n    pub ob_item: *mut *mut PyObject,\n    pub allocated: Py_ssize_t,\n}\n\n#[cfg(PyPy)]\npub struct PyListObject {\n    pub ob_base: PyObject,\n}\n\n// skipped _PyList_Extend\n// skipped _PyList_DebugMallocStats\n// skipped _PyList_CAST (used inline below)\n\n/// Macro, trading safety for speed\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\npub unsafe fn PyList_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject {\n    *(*(op as *mut PyListObject)).ob_item.offset(i)\n}\n\n/// Macro, *only* to be used to fill in brand new lists\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\npub unsafe fn PyList_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) {\n    *(*(op as *mut PyListObject)).ob_item.offset(i) = v;\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyList_GET_SIZE(op: *mut PyObject) -> Py_ssize_t {\n    Py_SIZE(op)\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/lock.rs",
    "content": "#[cfg(Py_3_14)]\nuse std::os::raw::c_int;\nuse std::sync::atomic::AtomicU8;\n\n#[repr(transparent)]\n#[derive(Debug)]\npub struct PyMutex {\n    pub(crate) _bits: AtomicU8,\n}\n\n// we don't impl Default because PyO3's safe wrappers don't need it\n#[allow(clippy::new_without_default)]\nimpl PyMutex {\n    pub const fn new() -> PyMutex {\n        PyMutex {\n            _bits: AtomicU8::new(0),\n        }\n    }\n}\n\nextern_libpython! {\n    pub fn PyMutex_Lock(m: *mut PyMutex);\n    pub fn PyMutex_Unlock(m: *mut PyMutex);\n    #[cfg(Py_3_14)]\n    pub fn PyMutex_IsLocked(m: *mut PyMutex) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/longobject.rs",
    "content": "use crate::longobject::*;\nuse crate::object::*;\n#[cfg(Py_3_13)]\nuse crate::pyport::Py_ssize_t;\nuse libc::size_t;\n#[cfg(Py_3_13)]\nuse std::ffi::c_void;\nuse std::ffi::{c_int, c_uchar};\n\n#[cfg(Py_3_13)]\nextern_libpython! {\n    pub fn PyLong_FromUnicodeObject(u: *mut PyObject, base: c_int) -> *mut PyObject;\n}\n\n#[cfg(Py_3_13)]\npub const Py_ASNATIVEBYTES_DEFAULTS: c_int = -1;\n#[cfg(Py_3_13)]\npub const Py_ASNATIVEBYTES_BIG_ENDIAN: c_int = 0;\n#[cfg(Py_3_13)]\npub const Py_ASNATIVEBYTES_LITTLE_ENDIAN: c_int = 1;\n#[cfg(Py_3_13)]\npub const Py_ASNATIVEBYTES_NATIVE_ENDIAN: c_int = 3;\n#[cfg(Py_3_13)]\npub const Py_ASNATIVEBYTES_UNSIGNED_BUFFER: c_int = 4;\n#[cfg(Py_3_13)]\npub const Py_ASNATIVEBYTES_REJECT_NEGATIVE: c_int = 8;\n\nextern_libpython! {\n    // skipped _PyLong_Sign\n\n    #[cfg(Py_3_13)]\n    pub fn PyLong_AsNativeBytes(\n        v: *mut PyObject,\n        buffer: *mut c_void,\n        n_bytes: Py_ssize_t,\n        flags: c_int,\n    ) -> Py_ssize_t;\n\n    #[cfg(Py_3_13)]\n    pub fn PyLong_FromNativeBytes(\n        buffer: *const c_void,\n        n_bytes: size_t,\n        flags: c_int,\n    ) -> *mut PyObject;\n\n    #[cfg(Py_3_13)]\n    pub fn PyLong_FromUnsignedNativeBytes(\n        buffer: *const c_void,\n        n_bytes: size_t,\n        flags: c_int,\n    ) -> *mut PyObject;\n\n    // skipped PyUnstable_Long_IsCompact\n    // skipped PyUnstable_Long_CompactValue\n\n    #[cfg_attr(PyPy, link_name = \"_PyPyLong_FromByteArray\")]\n    pub fn _PyLong_FromByteArray(\n        bytes: *const c_uchar,\n        n: size_t,\n        little_endian: c_int,\n        is_signed: c_int,\n    ) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"_PyPyLong_AsByteArrayO\")]\n    pub fn _PyLong_AsByteArray(\n        v: *mut PyLongObject,\n        bytes: *mut c_uchar,\n        n: size_t,\n        little_endian: c_int,\n        is_signed: c_int,\n    ) -> c_int;\n\n    // skipped _PyLong_GCD\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/methodobject.rs",
    "content": "use crate::object::*;\n#[cfg(not(GraalPy))]\nuse crate::{PyCFunctionObject, PyMethodDefPointer, METH_METHOD, METH_STATIC};\nuse std::ffi::c_int;\n\n#[cfg(not(GraalPy))]\npub struct PyCMethodObject {\n    pub func: PyCFunctionObject,\n    pub mm_class: *mut PyTypeObject,\n}\n\nextern_libpython! {\n    pub static mut PyCMethod_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyCMethod_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyCMethod_Type) as c_int\n}\n\n#[inline]\npub unsafe fn PyCMethod_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyCMethod_Type)\n}\n\n#[cfg(not(GraalPy))]\n#[inline]\npub unsafe fn PyCFunction_GET_FUNCTION(func: *mut PyObject) -> PyMethodDefPointer {\n    debug_assert_eq!(PyCMethod_Check(func), 1);\n\n    let func = func.cast::<PyCFunctionObject>();\n    (*(*func).m_ml).ml_meth\n}\n\n#[cfg(not(GraalPy))]\n#[inline]\npub unsafe fn PyCFunction_GET_SELF(func: *mut PyObject) -> *mut PyObject {\n    debug_assert_eq!(PyCMethod_Check(func), 1);\n\n    let func = func.cast::<PyCFunctionObject>();\n    if (*(*func).m_ml).ml_flags & METH_STATIC != 0 {\n        std::ptr::null_mut()\n    } else {\n        (*func).m_self\n    }\n}\n\n#[cfg(not(GraalPy))]\n#[inline]\npub unsafe fn PyCFunction_GET_FLAGS(func: *mut PyObject) -> c_int {\n    debug_assert_eq!(PyCMethod_Check(func), 1);\n\n    let func = func.cast::<PyCFunctionObject>();\n    (*(*func).m_ml).ml_flags\n}\n\n#[cfg(not(GraalPy))]\n#[inline]\npub unsafe fn PyCFunction_GET_CLASS(func: *mut PyObject) -> *mut PyTypeObject {\n    debug_assert_eq!(PyCMethod_Check(func), 1);\n\n    let func = func.cast::<PyCFunctionObject>();\n    if (*(*func).m_ml).ml_flags & METH_METHOD != 0 {\n        let func = func.cast::<PyCMethodObject>();\n        (*func).mm_class\n    } else {\n        std::ptr::null_mut()\n    }\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/mod.rs",
    "content": "pub(crate) mod abstract_;\n// skipped bytearrayobject.h\npub(crate) mod bytesobject;\n#[cfg(not(PyPy))]\npub(crate) mod ceval;\npub(crate) mod code;\npub(crate) mod compile;\npub(crate) mod complexobject;\n#[cfg(Py_3_13)]\npub(crate) mod critical_section;\npub(crate) mod descrobject;\npub(crate) mod dictobject;\n// skipped fileobject.h\n// skipped fileutils.h\npub(crate) mod frameobject;\npub(crate) mod funcobject;\npub(crate) mod genobject;\n#[cfg(any(not(PyPy), Py_3_14))]\npub(crate) mod import;\n#[cfg(all(Py_3_8, not(PyPy)))]\npub(crate) mod initconfig;\n// skipped interpreteridobject.h\npub(crate) mod listobject;\n#[cfg(Py_3_13)]\npub(crate) mod lock;\npub(crate) mod longobject;\n#[cfg(all(Py_3_9, not(PyPy)))]\npub(crate) mod methodobject;\npub(crate) mod object;\npub(crate) mod objimpl;\npub(crate) mod pydebug;\npub(crate) mod pyerrors;\n#[cfg(all(Py_3_8, not(PyPy)))]\npub(crate) mod pylifecycle;\npub(crate) mod pymem;\npub(crate) mod pystate;\npub(crate) mod pythonrun;\n// skipped sysmodule.h\npub(crate) mod floatobject;\npub(crate) mod pyframe;\npub(crate) mod pyhash;\npub(crate) mod tupleobject;\npub(crate) mod unicodeobject;\npub(crate) mod weakrefobject;\n\npub use self::abstract_::*;\npub use self::bytesobject::*;\n#[cfg(not(PyPy))]\npub use self::ceval::*;\npub use self::code::*;\npub use self::compile::*;\npub use self::complexobject::*;\n#[cfg(Py_3_13)]\npub use self::critical_section::*;\npub use self::descrobject::*;\npub use self::dictobject::*;\npub use self::floatobject::*;\npub use self::frameobject::*;\npub use self::funcobject::*;\npub use self::genobject::*;\n#[cfg(any(not(PyPy), Py_3_14))]\npub use self::import::*;\n#[cfg(all(Py_3_8, not(PyPy)))]\npub use self::initconfig::*;\npub use self::listobject::*;\n#[cfg(Py_3_13)]\npub use self::lock::*;\npub use self::longobject::*;\n#[cfg(all(Py_3_9, not(PyPy)))]\npub use self::methodobject::*;\npub use self::object::*;\npub use self::objimpl::*;\npub use self::pydebug::*;\npub use self::pyerrors::*;\npub use self::pyframe::*;\n#[cfg(any(not(PyPy), Py_3_13))]\npub use self::pyhash::*;\n#[cfg(all(Py_3_8, not(PyPy)))]\npub use self::pylifecycle::*;\npub use self::pymem::*;\npub use self::pystate::*;\npub use self::pythonrun::*;\npub use self::tupleobject::*;\npub use self::unicodeobject::*;\n#[cfg(not(any(PyPy, GraalPy)))]\npub use self::weakrefobject::*;\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/object.rs",
    "content": "#[cfg(Py_3_8)]\nuse crate::vectorcallfunc;\nuse crate::{object, PyGetSetDef, PyMemberDef, PyMethodDef, PyObject, Py_ssize_t};\nuse std::ffi::{c_char, c_int, c_uint, c_void};\nuse std::mem;\n\n// skipped private _Py_NewReference\n// skipped private _Py_NewReferenceNoTotal\n// skipped private _Py_ResurrectReference\n\n// skipped private _Py_GetGlobalRefTotal\n// skipped private _Py_GetRefTotal\n// skipped private _Py_GetLegacyRefTotal\n// skipped private _PyInterpreterState_GetRefTotal\n\n// skipped private _Py_Identifier\n\n// skipped private _Py_static_string_init\n// skipped private _Py_static_string\n// skipped private _Py_IDENTIFIER\n\n#[cfg(not(Py_3_11))] // moved to src/buffer.rs from Python\nmod bufferinfo {\n    use crate::Py_ssize_t;\n    use std::ffi::{c_char, c_int, c_void};\n    use std::ptr;\n\n    #[repr(C)]\n    #[derive(Copy, Clone)]\n    pub struct Py_buffer {\n        pub buf: *mut c_void,\n        /// Owned reference\n        pub obj: *mut crate::PyObject,\n        pub len: Py_ssize_t,\n        pub itemsize: Py_ssize_t,\n        pub readonly: c_int,\n        pub ndim: c_int,\n        pub format: *mut c_char,\n        pub shape: *mut Py_ssize_t,\n        pub strides: *mut Py_ssize_t,\n        pub suboffsets: *mut Py_ssize_t,\n        pub internal: *mut c_void,\n        #[cfg(PyPy)]\n        pub flags: c_int,\n        #[cfg(PyPy)]\n        pub _strides: [Py_ssize_t; PyBUF_MAX_NDIM as usize],\n        #[cfg(PyPy)]\n        pub _shape: [Py_ssize_t; PyBUF_MAX_NDIM as usize],\n    }\n\n    impl Py_buffer {\n        #[allow(clippy::new_without_default)]\n        pub const fn new() -> Self {\n            Py_buffer {\n                buf: ptr::null_mut(),\n                obj: ptr::null_mut(),\n                len: 0,\n                itemsize: 0,\n                readonly: 0,\n                ndim: 0,\n                format: ptr::null_mut(),\n                shape: ptr::null_mut(),\n                strides: ptr::null_mut(),\n                suboffsets: ptr::null_mut(),\n                internal: ptr::null_mut(),\n                #[cfg(PyPy)]\n                flags: 0,\n                #[cfg(PyPy)]\n                _strides: [0; PyBUF_MAX_NDIM as usize],\n                #[cfg(PyPy)]\n                _shape: [0; PyBUF_MAX_NDIM as usize],\n            }\n        }\n    }\n\n    pub type getbufferproc = unsafe extern \"C\" fn(\n        arg1: *mut crate::PyObject,\n        arg2: *mut Py_buffer,\n        arg3: c_int,\n    ) -> c_int;\n    pub type releasebufferproc =\n        unsafe extern \"C\" fn(arg1: *mut crate::PyObject, arg2: *mut Py_buffer);\n\n    /// Maximum number of dimensions\n    pub const PyBUF_MAX_NDIM: c_int = if cfg!(PyPy) { 36 } else { 64 };\n\n    /* Flags for getting buffers */\n    pub const PyBUF_SIMPLE: c_int = 0;\n    pub const PyBUF_WRITABLE: c_int = 0x0001;\n    /* we used to include an E, backwards compatible alias */\n    pub const PyBUF_WRITEABLE: c_int = PyBUF_WRITABLE;\n    pub const PyBUF_FORMAT: c_int = 0x0004;\n    pub const PyBUF_ND: c_int = 0x0008;\n    pub const PyBUF_STRIDES: c_int = 0x0010 | PyBUF_ND;\n    pub const PyBUF_C_CONTIGUOUS: c_int = 0x0020 | PyBUF_STRIDES;\n    pub const PyBUF_F_CONTIGUOUS: c_int = 0x0040 | PyBUF_STRIDES;\n    pub const PyBUF_ANY_CONTIGUOUS: c_int = 0x0080 | PyBUF_STRIDES;\n    pub const PyBUF_INDIRECT: c_int = 0x0100 | PyBUF_STRIDES;\n\n    pub const PyBUF_CONTIG: c_int = PyBUF_ND | PyBUF_WRITABLE;\n    pub const PyBUF_CONTIG_RO: c_int = PyBUF_ND;\n\n    pub const PyBUF_STRIDED: c_int = PyBUF_STRIDES | PyBUF_WRITABLE;\n    pub const PyBUF_STRIDED_RO: c_int = PyBUF_STRIDES;\n\n    pub const PyBUF_RECORDS: c_int = PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT;\n    pub const PyBUF_RECORDS_RO: c_int = PyBUF_STRIDES | PyBUF_FORMAT;\n\n    pub const PyBUF_FULL: c_int = PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT;\n    pub const PyBUF_FULL_RO: c_int = PyBUF_INDIRECT | PyBUF_FORMAT;\n\n    pub const PyBUF_READ: c_int = 0x100;\n    pub const PyBUF_WRITE: c_int = 0x200;\n}\n\n#[cfg(not(Py_3_11))]\npub use self::bufferinfo::*;\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyNumberMethods {\n    pub nb_add: Option<object::binaryfunc>,\n    pub nb_subtract: Option<object::binaryfunc>,\n    pub nb_multiply: Option<object::binaryfunc>,\n    pub nb_remainder: Option<object::binaryfunc>,\n    pub nb_divmod: Option<object::binaryfunc>,\n    pub nb_power: Option<object::ternaryfunc>,\n    pub nb_negative: Option<object::unaryfunc>,\n    pub nb_positive: Option<object::unaryfunc>,\n    pub nb_absolute: Option<object::unaryfunc>,\n    pub nb_bool: Option<object::inquiry>,\n    pub nb_invert: Option<object::unaryfunc>,\n    pub nb_lshift: Option<object::binaryfunc>,\n    pub nb_rshift: Option<object::binaryfunc>,\n    pub nb_and: Option<object::binaryfunc>,\n    pub nb_xor: Option<object::binaryfunc>,\n    pub nb_or: Option<object::binaryfunc>,\n    pub nb_int: Option<object::unaryfunc>,\n    pub nb_reserved: *mut c_void,\n    pub nb_float: Option<object::unaryfunc>,\n    pub nb_inplace_add: Option<object::binaryfunc>,\n    pub nb_inplace_subtract: Option<object::binaryfunc>,\n    pub nb_inplace_multiply: Option<object::binaryfunc>,\n    pub nb_inplace_remainder: Option<object::binaryfunc>,\n    pub nb_inplace_power: Option<object::ternaryfunc>,\n    pub nb_inplace_lshift: Option<object::binaryfunc>,\n    pub nb_inplace_rshift: Option<object::binaryfunc>,\n    pub nb_inplace_and: Option<object::binaryfunc>,\n    pub nb_inplace_xor: Option<object::binaryfunc>,\n    pub nb_inplace_or: Option<object::binaryfunc>,\n    pub nb_floor_divide: Option<object::binaryfunc>,\n    pub nb_true_divide: Option<object::binaryfunc>,\n    pub nb_inplace_floor_divide: Option<object::binaryfunc>,\n    pub nb_inplace_true_divide: Option<object::binaryfunc>,\n    pub nb_index: Option<object::unaryfunc>,\n    pub nb_matrix_multiply: Option<object::binaryfunc>,\n    pub nb_inplace_matrix_multiply: Option<object::binaryfunc>,\n}\n\n#[repr(C)]\n#[derive(Clone)]\npub struct PySequenceMethods {\n    pub sq_length: Option<object::lenfunc>,\n    pub sq_concat: Option<object::binaryfunc>,\n    pub sq_repeat: Option<object::ssizeargfunc>,\n    pub sq_item: Option<object::ssizeargfunc>,\n    pub was_sq_slice: *mut c_void,\n    pub sq_ass_item: Option<object::ssizeobjargproc>,\n    pub was_sq_ass_slice: *mut c_void,\n    pub sq_contains: Option<object::objobjproc>,\n    pub sq_inplace_concat: Option<object::binaryfunc>,\n    pub sq_inplace_repeat: Option<object::ssizeargfunc>,\n}\n\n#[repr(C)]\n#[derive(Clone, Default)]\npub struct PyMappingMethods {\n    pub mp_length: Option<object::lenfunc>,\n    pub mp_subscript: Option<object::binaryfunc>,\n    pub mp_ass_subscript: Option<object::objobjargproc>,\n}\n\n#[cfg(Py_3_10)]\npub type sendfunc = unsafe extern \"C\" fn(\n    iter: *mut PyObject,\n    value: *mut PyObject,\n    result: *mut *mut PyObject,\n) -> object::PySendResult;\n\n#[repr(C)]\n#[derive(Clone, Default)]\npub struct PyAsyncMethods {\n    pub am_await: Option<object::unaryfunc>,\n    pub am_aiter: Option<object::unaryfunc>,\n    pub am_anext: Option<object::unaryfunc>,\n    #[cfg(Py_3_10)]\n    pub am_send: Option<sendfunc>,\n}\n\n#[repr(C)]\n#[derive(Clone, Default)]\npub struct PyBufferProcs {\n    pub bf_getbuffer: Option<crate::getbufferproc>,\n    pub bf_releasebuffer: Option<crate::releasebufferproc>,\n}\n\npub type printfunc =\n    unsafe extern \"C\" fn(arg1: *mut PyObject, arg2: *mut ::libc::FILE, arg3: c_int) -> c_int;\n\n#[repr(C)]\n#[derive(Debug)]\npub struct PyTypeObject {\n    pub ob_base: object::PyVarObject,\n    pub tp_name: *const c_char,\n    pub tp_basicsize: Py_ssize_t,\n    pub tp_itemsize: Py_ssize_t,\n    pub tp_dealloc: Option<object::destructor>,\n    #[cfg(not(Py_3_8))]\n    pub tp_print: Option<printfunc>,\n    #[cfg(Py_3_8)]\n    pub tp_vectorcall_offset: Py_ssize_t,\n    pub tp_getattr: Option<object::getattrfunc>,\n    pub tp_setattr: Option<object::setattrfunc>,\n    pub tp_as_async: *mut PyAsyncMethods,\n    pub tp_repr: Option<object::reprfunc>,\n    pub tp_as_number: *mut PyNumberMethods,\n    pub tp_as_sequence: *mut PySequenceMethods,\n    pub tp_as_mapping: *mut PyMappingMethods,\n    pub tp_hash: Option<object::hashfunc>,\n    pub tp_call: Option<object::ternaryfunc>,\n    pub tp_str: Option<object::reprfunc>,\n    pub tp_getattro: Option<object::getattrofunc>,\n    pub tp_setattro: Option<object::setattrofunc>,\n    pub tp_as_buffer: *mut PyBufferProcs,\n    #[cfg(not(Py_GIL_DISABLED))]\n    pub tp_flags: std::ffi::c_ulong,\n    #[cfg(Py_GIL_DISABLED)]\n    pub tp_flags: crate::impl_::AtomicCULong,\n    pub tp_doc: *const c_char,\n    pub tp_traverse: Option<object::traverseproc>,\n    pub tp_clear: Option<object::inquiry>,\n    pub tp_richcompare: Option<object::richcmpfunc>,\n    pub tp_weaklistoffset: Py_ssize_t,\n    pub tp_iter: Option<object::getiterfunc>,\n    pub tp_iternext: Option<object::iternextfunc>,\n    pub tp_methods: *mut PyMethodDef,\n    pub tp_members: *mut PyMemberDef,\n    pub tp_getset: *mut PyGetSetDef,\n    pub tp_base: *mut PyTypeObject,\n    pub tp_dict: *mut object::PyObject,\n    pub tp_descr_get: Option<object::descrgetfunc>,\n    pub tp_descr_set: Option<object::descrsetfunc>,\n    pub tp_dictoffset: Py_ssize_t,\n    pub tp_init: Option<object::initproc>,\n    pub tp_alloc: Option<object::allocfunc>,\n    pub tp_new: Option<object::newfunc>,\n    pub tp_free: Option<object::freefunc>,\n    pub tp_is_gc: Option<object::inquiry>,\n    pub tp_bases: *mut object::PyObject,\n    pub tp_mro: *mut object::PyObject,\n    pub tp_cache: *mut object::PyObject,\n    pub tp_subclasses: *mut object::PyObject,\n    pub tp_weaklist: *mut object::PyObject,\n    pub tp_del: Option<object::destructor>,\n    pub tp_version_tag: c_uint,\n    pub tp_finalize: Option<object::destructor>,\n    #[cfg(Py_3_8)]\n    pub tp_vectorcall: Option<vectorcallfunc>,\n    #[cfg(Py_3_12)]\n    pub tp_watched: c_char,\n    #[cfg(all(not(PyPy), Py_3_8, not(Py_3_9)))]\n    pub tp_print: Option<printfunc>,\n    #[cfg(py_sys_config = \"COUNT_ALLOCS\")]\n    pub tp_allocs: Py_ssize_t,\n    #[cfg(py_sys_config = \"COUNT_ALLOCS\")]\n    pub tp_frees: Py_ssize_t,\n    #[cfg(py_sys_config = \"COUNT_ALLOCS\")]\n    pub tp_maxalloc: Py_ssize_t,\n    #[cfg(py_sys_config = \"COUNT_ALLOCS\")]\n    pub tp_prev: *mut PyTypeObject,\n    #[cfg(py_sys_config = \"COUNT_ALLOCS\")]\n    pub tp_next: *mut PyTypeObject,\n}\n\n#[cfg(Py_3_11)]\n#[repr(C)]\n#[derive(Clone)]\nstruct _specialization_cache {\n    getitem: *mut PyObject,\n    #[cfg(Py_3_12)]\n    getitem_version: u32,\n    #[cfg(Py_3_13)]\n    init: *mut PyObject,\n}\n\n#[repr(C)]\npub struct PyHeapTypeObject {\n    pub ht_type: PyTypeObject,\n    pub as_async: PyAsyncMethods,\n    pub as_number: PyNumberMethods,\n    pub as_mapping: PyMappingMethods,\n    pub as_sequence: PySequenceMethods,\n    pub as_buffer: PyBufferProcs,\n    pub ht_name: *mut object::PyObject,\n    pub ht_slots: *mut object::PyObject,\n    pub ht_qualname: *mut object::PyObject,\n    #[cfg(not(PyPy))]\n    pub ht_cached_keys: *mut c_void,\n    #[cfg(Py_3_9)]\n    pub ht_module: *mut object::PyObject,\n    #[cfg(all(Py_3_11, not(PyPy)))]\n    _ht_tpname: *mut c_char,\n    #[cfg(Py_3_14)]\n    pub ht_token: *mut c_void,\n    #[cfg(all(Py_3_11, not(PyPy)))]\n    _spec_cache: _specialization_cache,\n    #[cfg(all(Py_GIL_DISABLED, Py_3_14))]\n    pub unique_id: Py_ssize_t,\n}\n\nimpl Default for PyHeapTypeObject {\n    #[inline]\n    fn default() -> Self {\n        unsafe { mem::zeroed() }\n    }\n}\n\n#[inline]\n#[cfg(not(Py_3_11))]\npub unsafe fn PyHeapType_GET_MEMBERS(etype: *mut PyHeapTypeObject) -> *mut PyMemberDef {\n    let py_type = object::Py_TYPE(etype as *mut object::PyObject);\n    let ptr = etype.offset((*py_type).tp_basicsize);\n    ptr as *mut PyMemberDef\n}\n\n// skipped private _PyType_Name\n// skipped private _PyType_Lookup\n// skipped private _PyType_LookupRef\n\nextern_libpython! {\n    #[cfg(Py_3_12)]\n    pub fn PyType_GetDict(o: *mut PyTypeObject) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Print\")]\n    pub fn PyObject_Print(o: *mut PyObject, fp: *mut ::libc::FILE, flags: c_int) -> c_int;\n\n    // skipped private _Py_BreakPoint\n    // skipped private _PyObject_Dump\n\n    // skipped _PyObject_GetAttrId\n\n    // skipped private _PyObject_GetDictPtr\n    pub fn PyObject_CallFinalizer(arg1: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_CallFinalizerFromDealloc\")]\n    pub fn PyObject_CallFinalizerFromDealloc(arg1: *mut PyObject) -> c_int;\n\n    // skipped private _PyObject_GenericGetAttrWithDict\n    // skipped private _PyObject_GenericSetAttrWithDict\n    // skipped private _PyObject_FunctionStr\n}\n\n// skipped Py_SETREF\n// skipped Py_XSETREF\n\n// skipped private _PyObject_ASSERT_FROM\n// skipped private _PyObject_ASSERT_WITH_MSG\n// skipped private _PyObject_ASSERT\n// skipped private _PyObject_ASSERT_FAILED_MSG\n// skipped private _PyObject_AssertFailed\n\n// skipped private _PyTrash_begin\n// skipped private _PyTrash_end\n\n// skipped _PyTrash_thread_deposit_object\n// skipped _PyTrash_thread_destroy_chain\n\n// skipped Py_TRASHCAN_BEGIN\n// skipped Py_TRASHCAN_END\n\n// skipped PyObject_GetItemData\n\n// skipped PyObject_VisitManagedDict\n// skipped _PyObject_SetManagedDict\n// skipped PyObject_ClearManagedDict\n\n// skipped TYPE_MAX_WATCHERS\n\n// skipped PyType_WatchCallback\n// skipped PyType_AddWatcher\n// skipped PyType_ClearWatcher\n// skipped PyType_Watch\n// skipped PyType_Unwatch\n\n// skipped PyUnstable_Type_AssignVersionTag\n\n// skipped PyRefTracerEvent\n\n// skipped PyRefTracer\n// skipped PyRefTracer_SetTracer\n// skipped PyRefTracer_GetTracer\n\n#[cfg(Py_3_14)]\nextern_libpython! {\n    // skipped PyUnstable_Object_EnableDeferredRefcount\n\n    pub fn PyUnstable_Object_IsUniqueReferencedTemporary(obj: *mut PyObject) -> c_int;\n\n    // skipped PyUnstable_IsImmortal\n\n    pub fn PyUnstable_TryIncRef(obj: *mut PyObject) -> c_int;\n\n    pub fn PyUnstable_EnableTryIncRef(obj: *mut PyObject) -> c_void;\n\n    pub fn PyUnstable_Object_IsUniquelyReferenced(op: *mut PyObject) -> c_int;\n}\n\n#[cfg(Py_3_15)]\nextern_libpython! {\n    pub fn PyUnstable_SetImmortal(op: *mut PyObject) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/objimpl.rs",
    "content": "#[cfg(not(all(Py_3_11, any(PyPy, GraalPy))))]\nuse libc::size_t;\nuse std::ffi::c_int;\n\n#[cfg(not(any(PyPy, GraalPy)))]\nuse std::ffi::c_void;\n\nuse crate::object::*;\n\n// skipped _PyObject_SIZE\n// skipped _PyObject_VAR_SIZE\n\n#[cfg(not(Py_3_11))]\nextern_libpython! {\n    pub fn _Py_GetAllocatedBlocks() -> crate::Py_ssize_t;\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyObjectArenaAllocator {\n    pub ctx: *mut c_void,\n    pub alloc: Option<extern \"C\" fn(ctx: *mut c_void, size: size_t) -> *mut c_void>,\n    pub free: Option<extern \"C\" fn(ctx: *mut c_void, ptr: *mut c_void, size: size_t)>,\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\nimpl Default for PyObjectArenaAllocator {\n    #[inline]\n    fn default() -> Self {\n        unsafe { std::mem::zeroed() }\n    }\n}\n\nextern_libpython! {\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator);\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator);\n\n    #[cfg(Py_3_9)]\n    pub fn PyObject_IS_GC(o: *mut PyObject) -> c_int;\n}\n\n#[inline]\n#[cfg(not(Py_3_9))]\npub unsafe fn PyObject_IS_GC(o: *mut PyObject) -> c_int {\n    (crate::PyType_IS_GC(Py_TYPE(o)) != 0\n        && match (*Py_TYPE(o)).tp_is_gc {\n            Some(tp_is_gc) => tp_is_gc(o) != 0,\n            None => true,\n        }) as c_int\n}\n\n#[cfg(not(Py_3_11))]\nextern_libpython! {\n    pub fn _PyObject_GC_Malloc(size: size_t) -> *mut PyObject;\n    pub fn _PyObject_GC_Calloc(size: size_t) -> *mut PyObject;\n}\n\n#[inline]\npub unsafe fn PyType_SUPPORTS_WEAKREFS(t: *mut PyTypeObject) -> c_int {\n    ((*t).tp_weaklistoffset > 0) as c_int\n}\n\n#[inline]\npub unsafe fn PyObject_GET_WEAKREFS_LISTPTR(o: *mut PyObject) -> *mut *mut PyObject {\n    let weaklistoffset = (*Py_TYPE(o)).tp_weaklistoffset;\n    o.offset(weaklistoffset) as *mut *mut PyObject\n}\n\n// skipped PyUnstable_Object_GC_NewWithExtraData\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/pydebug.rs",
    "content": "use std::ffi::{c_char, c_int};\n\n#[cfg(not(Py_LIMITED_API))]\nextern_libpython! {\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_DebugFlag\")]\n    pub static mut Py_DebugFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_VerboseFlag\")]\n    pub static mut Py_VerboseFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    pub static mut Py_QuietFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_InteractiveFlag\")]\n    pub static mut Py_InteractiveFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_InspectFlag\")]\n    pub static mut Py_InspectFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_OptimizeFlag\")]\n    pub static mut Py_OptimizeFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_NoSiteFlag\")]\n    pub static mut Py_NoSiteFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_BytesWarningFlag\")]\n    pub static mut Py_BytesWarningFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_UseClassExceptionsFlag\")]\n    pub static mut Py_UseClassExceptionsFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_FrozenFlag\")]\n    pub static mut Py_FrozenFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_IgnoreEnvironmentFlag\")]\n    pub static mut Py_IgnoreEnvironmentFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_DontWriteBytecodeFlag\")]\n    pub static mut Py_DontWriteBytecodeFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPy_NoUserSiteDirectory\")]\n    pub static mut Py_NoUserSiteDirectory: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    pub static mut Py_UnbufferedStdioFlag: c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPy_HashRandomizationFlag\")]\n    pub static mut Py_HashRandomizationFlag: c_int;\n    #[deprecated(note = \"Python 3.12\")]\n    pub static mut Py_IsolatedFlag: c_int;\n    #[cfg(windows)]\n    #[deprecated(note = \"Python 3.12\")]\n    pub static mut Py_LegacyWindowsFSEncodingFlag: c_int;\n    #[cfg(windows)]\n    #[deprecated(note = \"Python 3.12\")]\n    pub static mut Py_LegacyWindowsStdioFlag: c_int;\n}\n\nextern_libpython! {\n    #[cfg(Py_3_11)]\n    pub fn Py_GETENV(name: *const c_char) -> *mut c_char;\n}\n\n#[cfg(not(Py_3_11))]\n#[inline(always)]\npub unsafe fn Py_GETENV(name: *const c_char) -> *mut c_char {\n    #[allow(deprecated)]\n    if Py_IgnoreEnvironmentFlag != 0 {\n        std::ptr::null_mut()\n    } else {\n        libc::getenv(name)\n    }\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/pyerrors.rs",
    "content": "use crate::PyObject;\n#[cfg(not(any(PyPy, GraalPy)))]\nuse crate::Py_ssize_t;\n\n#[repr(C)]\n#[derive(Debug)]\npub struct PyBaseExceptionObject {\n    pub ob_base: PyObject,\n    #[cfg(not(PyPy))]\n    pub dict: *mut PyObject,\n    #[cfg(not(PyPy))]\n    pub args: *mut PyObject,\n    #[cfg(all(Py_3_11, not(PyPy)))]\n    pub notes: *mut PyObject,\n    #[cfg(not(PyPy))]\n    pub traceback: *mut PyObject,\n    #[cfg(not(PyPy))]\n    pub context: *mut PyObject,\n    #[cfg(not(PyPy))]\n    pub cause: *mut PyObject,\n    #[cfg(not(PyPy))]\n    pub suppress_context: char,\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(C)]\n#[derive(Debug)]\npub struct PySyntaxErrorObject {\n    pub ob_base: PyObject,\n    pub dict: *mut PyObject,\n    pub args: *mut PyObject,\n    #[cfg(Py_3_11)]\n    pub notes: *mut PyObject,\n    pub traceback: *mut PyObject,\n    pub context: *mut PyObject,\n    pub cause: *mut PyObject,\n    pub suppress_context: char,\n\n    pub msg: *mut PyObject,\n    pub filename: *mut PyObject,\n    pub lineno: *mut PyObject,\n    pub offset: *mut PyObject,\n    #[cfg(Py_3_10)]\n    pub end_lineno: *mut PyObject,\n    #[cfg(Py_3_10)]\n    pub end_offset: *mut PyObject,\n    pub text: *mut PyObject,\n    pub print_file_and_line: *mut PyObject,\n    #[cfg(Py_3_14)]\n    pub metadata: *mut PyObject,\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(C)]\n#[derive(Debug)]\npub struct PyImportErrorObject {\n    pub ob_base: PyObject,\n    pub dict: *mut PyObject,\n    pub args: *mut PyObject,\n    #[cfg(Py_3_11)]\n    pub notes: *mut PyObject,\n    pub traceback: *mut PyObject,\n    pub context: *mut PyObject,\n    pub cause: *mut PyObject,\n    pub suppress_context: char,\n\n    pub msg: *mut PyObject,\n    pub name: *mut PyObject,\n    pub path: *mut PyObject,\n    #[cfg(Py_3_12)]\n    pub name_from: *mut PyObject,\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(C)]\n#[derive(Debug)]\npub struct PyUnicodeErrorObject {\n    pub ob_base: PyObject,\n    pub dict: *mut PyObject,\n    pub args: *mut PyObject,\n    #[cfg(Py_3_11)]\n    pub notes: *mut PyObject,\n    pub traceback: *mut PyObject,\n    pub context: *mut PyObject,\n    pub cause: *mut PyObject,\n    pub suppress_context: char,\n\n    pub encoding: *mut PyObject,\n    pub object: *mut PyObject,\n    pub start: Py_ssize_t,\n    pub end: Py_ssize_t,\n    pub reason: *mut PyObject,\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(C)]\n#[derive(Debug)]\npub struct PySystemExitObject {\n    pub ob_base: PyObject,\n    pub dict: *mut PyObject,\n    pub args: *mut PyObject,\n    #[cfg(Py_3_11)]\n    pub notes: *mut PyObject,\n    pub traceback: *mut PyObject,\n    pub context: *mut PyObject,\n    pub cause: *mut PyObject,\n    pub suppress_context: char,\n\n    pub code: *mut PyObject,\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(C)]\n#[derive(Debug)]\npub struct PyOSErrorObject {\n    pub ob_base: PyObject,\n    pub dict: *mut PyObject,\n    pub args: *mut PyObject,\n    #[cfg(Py_3_11)]\n    pub notes: *mut PyObject,\n    pub traceback: *mut PyObject,\n    pub context: *mut PyObject,\n    pub cause: *mut PyObject,\n    pub suppress_context: char,\n\n    pub myerrno: *mut PyObject,\n    pub strerror: *mut PyObject,\n    pub filename: *mut PyObject,\n    pub filename2: *mut PyObject,\n    #[cfg(windows)]\n    pub winerror: *mut PyObject,\n    pub written: Py_ssize_t,\n}\n\n#[repr(C)]\n#[derive(Debug)]\npub struct PyStopIterationObject {\n    pub ob_base: PyObject,\n    #[cfg(not(PyPy))]\n    pub dict: *mut PyObject,\n    #[cfg(not(PyPy))]\n    pub args: *mut PyObject,\n    #[cfg(all(Py_3_11, not(PyPy)))]\n    pub notes: *mut PyObject,\n    #[cfg(not(PyPy))]\n    pub traceback: *mut PyObject,\n    #[cfg(not(PyPy))]\n    pub context: *mut PyObject,\n    #[cfg(not(PyPy))]\n    pub cause: *mut PyObject,\n    #[cfg(not(PyPy))]\n    pub suppress_context: char,\n\n    pub value: *mut PyObject,\n}\n\n// skipped _PyErr_ChainExceptions\n\n// skipped PyNameErrorObject\n// skipped PyAttributeErrorObject\n\n// skipped PyEnvironmentErrorObject\n// skipped PyWindowsErrorObject\n\n// skipped _PyErr_SetKeyError\n// skipped _PyErr_GetTopmostException\n// skipped _PyErr_GetExcInfo\n\n// skipped PyErr_SetFromErrnoWithUnicodeFilename\n\n// skipped _PyErr_FormatFromCause\n\n// skipped PyErr_SetFromWindowsErrWithUnicodeFilename\n// skipped PyErr_SetExcFromWindowsErrWithUnicodeFilename\n\n// skipped _PyErr_TrySetFromCause\n\n// skipped PySignal_SetWakeupFd\n// skipped _PyErr_CheckSignals\n\n// skipped PyErr_SyntaxLocationObject\n// skipped PyErr_RangedSyntaxLocationObject\n// skipped PyErr_ProgramTextObject\n\n// skipped _PyErr_ProgramDecodedTextObject\n// skipped _PyUnicodeTranslateError_Create\n// skipped _PyErr_WriteUnraisableMsg\n// skipped _Py_FatalErrorFunc\n// skipped _Py_FatalErrorFormat\n// skipped Py_FatalError\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/pyframe.rs",
    "content": "#[cfg(any(Py_3_11, all(Py_3_9, not(PyPy))))]\nuse crate::PyFrameObject;\nuse crate::{PyObject, PyTypeObject, Py_TYPE};\n#[cfg(Py_3_12)]\nuse std::ffi::c_char;\nuse std::ffi::c_int;\n\n// NB used in `_PyEval_EvalFrameDefault`, maybe we remove this too.\n#[cfg(all(Py_3_11, not(PyPy)))]\nopaque_struct!(pub _PyInterpreterFrame);\n\nextern_libpython! {\n    pub static mut PyFrame_Type: PyTypeObject;\n\n    #[cfg(Py_3_13)]\n    pub static mut PyFrameLocalsProxy_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyFrame_Check(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyFrame_Type) as c_int\n}\n\n#[cfg(Py_3_13)]\n#[inline]\npub unsafe fn PyFrameLocalsProxy_Check(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyFrameLocalsProxy_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg(all(Py_3_9, not(PyPy)))]\n    pub fn PyFrame_GetBack(frame: *mut PyFrameObject) -> *mut PyFrameObject;\n\n    #[cfg(Py_3_11)]\n    pub fn PyFrame_GetLocals(frame: *mut PyFrameObject) -> *mut PyObject;\n\n    #[cfg(Py_3_11)]\n    pub fn PyFrame_GetGlobals(frame: *mut PyFrameObject) -> *mut PyObject;\n\n    #[cfg(Py_3_11)]\n    pub fn PyFrame_GetBuiltins(frame: *mut PyFrameObject) -> *mut PyObject;\n\n    #[cfg(Py_3_11)]\n    pub fn PyFrame_GetGenerator(frame: *mut PyFrameObject) -> *mut PyObject;\n\n    #[cfg(Py_3_11)]\n    pub fn PyFrame_GetLasti(frame: *mut PyFrameObject) -> c_int;\n\n    #[cfg(Py_3_12)]\n    pub fn PyFrame_GetVar(frame: *mut PyFrameObject, name: *mut PyObject) -> *mut PyObject;\n\n    #[cfg(Py_3_12)]\n    pub fn PyFrame_GetVarString(frame: *mut PyFrameObject, name: *mut c_char) -> *mut PyObject;\n\n    // skipped PyUnstable_InterpreterFrame_GetCode\n    // skipped PyUnstable_InterpreterFrame_GetLasti\n    // skipped PyUnstable_InterpreterFrame_GetLine\n    // skipped PyUnstable_ExecutableKinds\n\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/pyhash.rs",
    "content": "#[cfg(Py_3_14)]\nuse crate::Py_ssize_t;\n#[cfg(Py_3_13)]\nuse crate::{PyObject, Py_hash_t};\n#[cfg(any(Py_3_13, not(PyPy)))]\nuse std::ffi::c_void;\n#[cfg(not(PyPy))]\nuse std::ffi::{c_char, c_int};\n\n#[cfg(not(PyPy))]\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyHash_FuncDef {\n    pub hash:\n        Option<extern \"C\" fn(arg1: *const c_void, arg2: crate::Py_ssize_t) -> crate::Py_hash_t>,\n    pub name: *const c_char,\n    pub hash_bits: c_int,\n    pub seed_bits: c_int,\n}\n\n#[cfg(not(PyPy))]\nimpl Default for PyHash_FuncDef {\n    #[inline]\n    fn default() -> Self {\n        unsafe { std::mem::zeroed() }\n    }\n}\n\nextern_libpython! {\n    #[cfg(not(PyPy))]\n    pub fn PyHash_GetFuncDef() -> *mut PyHash_FuncDef;\n    #[cfg(Py_3_13)]\n    pub fn Py_HashPointer(ptr: *const c_void) -> Py_hash_t;\n    #[cfg(Py_3_13)]\n    pub fn PyObject_GenericHash(obj: *mut PyObject) -> Py_hash_t;\n    #[cfg(Py_3_14)]\n    pub fn Py_HashBuffer(ptr: *const c_void, len: Py_ssize_t) -> Py_hash_t;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/pylifecycle.rs",
    "content": "use crate::{PyConfig, PyPreConfig, PyStatus, Py_ssize_t};\nuse libc::wchar_t;\nuse std::ffi::{c_char, c_int};\n\nextern_libpython! {\n\n    // skipped Py_FrozenMain\n\n    pub fn Py_PreInitialize(src_config: *const PyPreConfig) -> PyStatus;\n    pub fn Py_PreInitializeFromBytesArgs(\n        src_config: *const PyPreConfig,\n        argc: Py_ssize_t,\n        argv: *mut *mut c_char,\n    ) -> PyStatus;\n    pub fn Py_PreInitializeFromArgs(\n        src_config: *const PyPreConfig,\n        argc: Py_ssize_t,\n        argv: *mut *mut wchar_t,\n    ) -> PyStatus;\n\n    pub fn Py_InitializeFromConfig(config: *const PyConfig) -> PyStatus;\n\n    pub fn Py_RunMain() -> c_int;\n\n    pub fn Py_ExitStatusException(status: PyStatus) -> !;\n\n    // skipped Py_FdIsInteractive\n}\n\n#[cfg(Py_3_12)]\npub const PyInterpreterConfig_DEFAULT_GIL: c_int = 0;\n#[cfg(Py_3_12)]\npub const PyInterpreterConfig_SHARED_GIL: c_int = 1;\n#[cfg(Py_3_12)]\npub const PyInterpreterConfig_OWN_GIL: c_int = 2;\n\n#[cfg(Py_3_12)]\n#[repr(C)]\npub struct PyInterpreterConfig {\n    pub use_main_obmalloc: c_int,\n    pub allow_fork: c_int,\n    pub allow_exec: c_int,\n    pub allow_threads: c_int,\n    pub allow_daemon_threads: c_int,\n    pub check_multi_interp_extensions: c_int,\n    pub gil: c_int,\n}\n\n#[cfg(Py_3_12)]\npub const _PyInterpreterConfig_INIT: PyInterpreterConfig = PyInterpreterConfig {\n    use_main_obmalloc: 0,\n    allow_fork: 0,\n    allow_exec: 0,\n    allow_threads: 1,\n    allow_daemon_threads: 0,\n    check_multi_interp_extensions: 1,\n    gil: PyInterpreterConfig_OWN_GIL,\n};\n\n// https://github.com/python/cpython/blob/902de283a8303177eb95bf5bc252d2421fcbd758/Include/cpython/pylifecycle.h#L63-L65\n#[cfg(Py_3_12)]\nconst _PyInterpreterConfig_LEGACY_CHECK_MULTI_INTERP_EXTENSIONS: c_int =\n    if cfg!(Py_GIL_DISABLED) { 1 } else { 0 };\n\n#[cfg(Py_3_12)]\npub const _PyInterpreterConfig_LEGACY_INIT: PyInterpreterConfig = PyInterpreterConfig {\n    use_main_obmalloc: 1,\n    allow_fork: 1,\n    allow_exec: 1,\n    allow_threads: 1,\n    allow_daemon_threads: 1,\n    check_multi_interp_extensions: _PyInterpreterConfig_LEGACY_CHECK_MULTI_INTERP_EXTENSIONS,\n    gil: PyInterpreterConfig_SHARED_GIL,\n};\n\nextern_libpython! {\n    #[cfg(Py_3_12)]\n    pub fn Py_NewInterpreterFromConfig(\n        tstate_p: *mut *mut crate::PyThreadState,\n        config: *const PyInterpreterConfig,\n    ) -> PyStatus;\n}\n\n// skipped atexit_datacallbackfunc\n// skipped PyUnstable_AtExit\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/pymem.rs",
    "content": "use libc::size_t;\nuse std::ffi::c_void;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyMem_RawMalloc\")]\n    pub fn PyMem_RawMalloc(size: size_t) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyMem_RawCalloc\")]\n    pub fn PyMem_RawCalloc(nelem: size_t, elsize: size_t) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyMem_RawRealloc\")]\n    pub fn PyMem_RawRealloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyMem_RawFree\")]\n    pub fn PyMem_RawFree(ptr: *mut c_void);\n\n    // skipped _PyMem_GetCurrentAllocatorName\n    // skipped _PyMem_RawStrdup\n    // skipped _PyMem_Strdup\n    // skipped _PyMem_RawWcsdup\n}\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub enum PyMemAllocatorDomain {\n    PYMEM_DOMAIN_RAW,\n    PYMEM_DOMAIN_MEM,\n    PYMEM_DOMAIN_OBJ,\n}\n\n// skipped PyMemAllocatorName\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyMemAllocatorEx {\n    pub ctx: *mut c_void,\n    pub malloc: Option<extern \"C\" fn(ctx: *mut c_void, size: size_t) -> *mut c_void>,\n    pub calloc:\n        Option<extern \"C\" fn(ctx: *mut c_void, nelem: size_t, elsize: size_t) -> *mut c_void>,\n    pub realloc:\n        Option<extern \"C\" fn(ctx: *mut c_void, ptr: *mut c_void, new_size: size_t) -> *mut c_void>,\n    pub free: Option<extern \"C\" fn(ctx: *mut c_void, ptr: *mut c_void)>,\n}\n\nextern_libpython! {\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyMem_GetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx);\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyMem_SetAllocator(domain: PyMemAllocatorDomain, allocator: *mut PyMemAllocatorEx);\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyMem_SetupDebugHooks();\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/pystate.rs",
    "content": "use crate::PyThreadState;\nuse crate::{PyFrameObject, PyInterpreterState, PyObject};\nuse std::ffi::c_int;\n\n// skipped private _PyInterpreterState_RequiresIDRef\n// skipped private _PyInterpreterState_RequireIDRef\n\npub type Py_tracefunc = unsafe extern \"C\" fn(\n    obj: *mut PyObject,\n    frame: *mut PyFrameObject,\n    what: c_int,\n    arg: *mut PyObject,\n) -> c_int;\n\npub const PyTrace_CALL: c_int = 0;\npub const PyTrace_EXCEPTION: c_int = 1;\npub const PyTrace_LINE: c_int = 2;\npub const PyTrace_RETURN: c_int = 3;\npub const PyTrace_C_CALL: c_int = 4;\npub const PyTrace_C_EXCEPTION: c_int = 5;\npub const PyTrace_C_RETURN: c_int = 6;\npub const PyTrace_OPCODE: c_int = 7;\n\n// skipped private _Py_MAX_SCRIPT_PATH_SIZE\n// skipped private _PyRemoteDebuggerSupport\n\n/// Private structure used inline in `PyGenObject`\n///\n/// `PyGenObject` was made opaque in Python 3.14, so we don't bother defining this\n/// structure for that version and later.\n#[cfg(not(any(PyPy, Py_3_14)))]\n#[repr(C)]\n#[derive(Clone, Copy)]\npub(crate) struct _PyErr_StackItem {\n    #[cfg(not(Py_3_11))]\n    exc_type: *mut PyObject,\n    exc_value: *mut PyObject,\n    #[cfg(not(Py_3_11))]\n    exc_traceback: *mut PyObject,\n    previous_item: *mut _PyErr_StackItem,\n}\n\n// skipped private _PyStackChunk\n\n// skipped private _PY_DATA_STACK_CHUNK_SIZE\n// skipped private _ts (aka PyThreadState)\n\nextern_libpython! {\n    #[cfg(Py_3_13)]\n    pub fn PyThreadState_GetUnchecked() -> *mut PyThreadState;\n\n    #[cfg(not(Py_3_13))]\n    pub(crate) fn _PyThreadState_UncheckedGet() -> *mut PyThreadState;\n\n    #[cfg(Py_3_11)]\n    pub fn PyThreadState_EnterTracing(state: *mut PyThreadState);\n    #[cfg(Py_3_11)]\n    pub fn PyThreadState_LeaveTracing(state: *mut PyThreadState);\n\n    #[cfg_attr(PyPy, link_name = \"PyPyGILState_Check\")]\n    pub fn PyGILState_Check() -> c_int;\n\n    // skipped private _PyThread_CurrentFrames\n\n    // skipped PyUnstable_ThreadState_SetStackProtection\n    // skipped PyUnstable_ThreadState_ResetStackProtection\n\n    #[cfg(not(PyPy))]\n    pub fn PyInterpreterState_Main() -> *mut PyInterpreterState;\n    #[cfg_attr(PyPy, link_name = \"PyPyInterpreterState_Head\")]\n    pub fn PyInterpreterState_Head() -> *mut PyInterpreterState;\n    #[cfg_attr(PyPy, link_name = \"PyPyInterpreterState_Next\")]\n    pub fn PyInterpreterState_Next(interp: *mut PyInterpreterState) -> *mut PyInterpreterState;\n    #[cfg(not(PyPy))]\n    pub fn PyInterpreterState_ThreadHead(interp: *mut PyInterpreterState) -> *mut PyThreadState;\n    #[cfg(not(PyPy))]\n    pub fn PyThreadState_Next(tstate: *mut PyThreadState) -> *mut PyThreadState;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyThreadState_DeleteCurrent\")]\n    pub fn PyThreadState_DeleteCurrent();\n}\n\n// skipped private _PyFrameEvalFunction\n// skipped private _PyInterpreterState_GetEvalFrameFunc\n// skipped private _PyInterpreterState_SetEvalFrameFunc\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/pythonrun.rs",
    "content": "use crate::object::*;\n#[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API, Py_3_10)))]\nuse crate::pyarena::PyArena;\nuse crate::PyCompilerFlags;\n#[cfg(not(any(PyPy, GraalPy, Py_3_10)))]\nuse crate::{_mod, _node};\nuse libc::FILE;\nuse std::ffi::{c_char, c_int};\n\nextern_libpython! {\n    pub fn PyRun_SimpleStringFlags(arg1: *const c_char, arg2: *mut PyCompilerFlags) -> c_int;\n    pub fn _PyRun_SimpleFileObject(\n        fp: *mut FILE,\n        filename: *mut PyObject,\n        closeit: c_int,\n        flags: *mut PyCompilerFlags,\n    ) -> c_int;\n    pub fn PyRun_AnyFileExFlags(\n        fp: *mut FILE,\n        filename: *const c_char,\n        closeit: c_int,\n        flags: *mut PyCompilerFlags,\n    ) -> c_int;\n    pub fn _PyRun_AnyFileObject(\n        fp: *mut FILE,\n        filename: *mut PyObject,\n        closeit: c_int,\n        flags: *mut PyCompilerFlags,\n    ) -> c_int;\n    pub fn PyRun_SimpleFileExFlags(\n        fp: *mut FILE,\n        filename: *const c_char,\n        closeit: c_int,\n        flags: *mut PyCompilerFlags,\n    ) -> c_int;\n    pub fn PyRun_InteractiveOneFlags(\n        fp: *mut FILE,\n        filename: *const c_char,\n        flags: *mut PyCompilerFlags,\n    ) -> c_int;\n    pub fn PyRun_InteractiveOneObject(\n        fp: *mut FILE,\n        filename: *mut PyObject,\n        flags: *mut PyCompilerFlags,\n    ) -> c_int;\n    pub fn PyRun_InteractiveLoopFlags(\n        fp: *mut FILE,\n        filename: *const c_char,\n        flags: *mut PyCompilerFlags,\n    ) -> c_int;\n    pub fn _PyRun_InteractiveLoopObject(\n        fp: *mut FILE,\n        filename: *mut PyObject,\n        flags: *mut PyCompilerFlags,\n    ) -> c_int;\n\n    #[cfg(not(any(PyPy, GraalPy, Py_3_10)))]\n    pub fn PyParser_ASTFromString(\n        s: *const c_char,\n        filename: *const c_char,\n        start: c_int,\n        flags: *mut PyCompilerFlags,\n        arena: *mut PyArena,\n    ) -> *mut _mod;\n    #[cfg(not(any(PyPy, GraalPy, Py_3_10)))]\n    pub fn PyParser_ASTFromStringObject(\n        s: *const c_char,\n        filename: *mut PyObject,\n        start: c_int,\n        flags: *mut PyCompilerFlags,\n        arena: *mut PyArena,\n    ) -> *mut _mod;\n    #[cfg(not(any(PyPy, GraalPy, Py_3_10)))]\n    pub fn PyParser_ASTFromFile(\n        fp: *mut FILE,\n        filename: *const c_char,\n        enc: *const c_char,\n        start: c_int,\n        ps1: *const c_char,\n        ps2: *const c_char,\n        flags: *mut PyCompilerFlags,\n        errcode: *mut c_int,\n        arena: *mut PyArena,\n    ) -> *mut _mod;\n    #[cfg(not(any(PyPy, GraalPy, Py_3_10)))]\n    pub fn PyParser_ASTFromFileObject(\n        fp: *mut FILE,\n        filename: *mut PyObject,\n        enc: *const c_char,\n        start: c_int,\n        ps1: *const c_char,\n        ps2: *const c_char,\n        flags: *mut PyCompilerFlags,\n        errcode: *mut c_int,\n        arena: *mut PyArena,\n    ) -> *mut _mod;\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyRun_StringFlags\")]\n    pub fn PyRun_StringFlags(\n        arg1: *const c_char,\n        arg2: c_int,\n        arg3: *mut PyObject,\n        arg4: *mut PyObject,\n        arg5: *mut PyCompilerFlags,\n    ) -> *mut PyObject;\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyRun_FileExFlags(\n        fp: *mut FILE,\n        filename: *const c_char,\n        start: c_int,\n        globals: *mut PyObject,\n        locals: *mut PyObject,\n        closeit: c_int,\n        flags: *mut PyCompilerFlags,\n    ) -> *mut PyObject;\n\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn Py_CompileStringExFlags(\n        str: *const c_char,\n        filename: *const c_char,\n        start: c_int,\n        flags: *mut PyCompilerFlags,\n        optimize: c_int,\n    ) -> *mut PyObject;\n    #[cfg(not(Py_LIMITED_API))]\n    pub fn Py_CompileStringObject(\n        str: *const c_char,\n        filename: *mut PyObject,\n        start: c_int,\n        flags: *mut PyCompilerFlags,\n        optimize: c_int,\n    ) -> *mut PyObject;\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\npub unsafe fn Py_CompileString(string: *const c_char, p: *const c_char, s: c_int) -> *mut PyObject {\n    Py_CompileStringExFlags(string, p, s, std::ptr::null_mut(), -1)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\npub unsafe fn Py_CompileStringFlags(\n    string: *const c_char,\n    p: *const c_char,\n    s: c_int,\n    f: *mut PyCompilerFlags,\n) -> *mut PyObject {\n    Py_CompileStringExFlags(string, p, s, f, -1)\n}\n\n// skipped _Py_SourceAsString\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyRun_String\")]\n    pub fn PyRun_String(\n        string: *const c_char,\n        s: c_int,\n        g: *mut PyObject,\n        l: *mut PyObject,\n    ) -> *mut PyObject;\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyRun_AnyFile(fp: *mut FILE, name: *const c_char) -> c_int;\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyRun_AnyFileEx(fp: *mut FILE, name: *const c_char, closeit: c_int) -> c_int;\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyRun_AnyFileFlags(\n        arg1: *mut FILE,\n        arg2: *const c_char,\n        arg3: *mut PyCompilerFlags,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyRun_SimpleString\")]\n    pub fn PyRun_SimpleString(s: *const c_char) -> c_int;\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyRun_SimpleFile(f: *mut FILE, p: *const c_char) -> c_int;\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyRun_SimpleFileEx(f: *mut FILE, p: *const c_char, c: c_int) -> c_int;\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyRun_InteractiveOne(f: *mut FILE, p: *const c_char) -> c_int;\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyRun_InteractiveLoop(f: *mut FILE, p: *const c_char) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyRun_File\")]\n    pub fn PyRun_File(\n        fp: *mut FILE,\n        p: *const c_char,\n        s: c_int,\n        g: *mut PyObject,\n        l: *mut PyObject,\n    ) -> *mut PyObject;\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyRun_FileEx(\n        fp: *mut FILE,\n        p: *const c_char,\n        s: c_int,\n        g: *mut PyObject,\n        l: *mut PyObject,\n        c: c_int,\n    ) -> *mut PyObject;\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn PyRun_FileFlags(\n        fp: *mut FILE,\n        p: *const c_char,\n        s: c_int,\n        g: *mut PyObject,\n        l: *mut PyObject,\n        flags: *mut PyCompilerFlags,\n    ) -> *mut PyObject;\n}\n\n// skipped macro PyRun_String\n// skipped macro PyRun_AnyFile\n// skipped macro PyRun_AnyFileEx\n// skipped macro PyRun_AnyFileFlags\n\nextern_libpython! {\n    #[cfg(not(any(PyPy, GraalPy, Py_3_10)))]\n    #[cfg_attr(Py_3_9, deprecated(note = \"Python 3.9\"))]\n    pub fn PyParser_SimpleParseStringFlags(\n        arg1: *const c_char,\n        arg2: c_int,\n        arg3: c_int,\n    ) -> *mut _node;\n    #[cfg(not(any(PyPy, GraalPy, Py_3_10)))]\n    #[cfg_attr(Py_3_9, deprecated(note = \"Python 3.9\"))]\n    pub fn PyParser_SimpleParseStringFlagsFilename(\n        arg1: *const c_char,\n        arg2: *const c_char,\n        arg3: c_int,\n        arg4: c_int,\n    ) -> *mut _node;\n    #[cfg(not(any(PyPy, GraalPy, Py_3_10)))]\n    #[cfg_attr(Py_3_9, deprecated(note = \"Python 3.9\"))]\n    pub fn PyParser_SimpleParseFileFlags(\n        arg1: *mut FILE,\n        arg2: *const c_char,\n        arg3: c_int,\n        arg4: c_int,\n    ) -> *mut _node;\n\n    #[cfg(PyPy)]\n    #[cfg_attr(PyPy, link_name = \"PyPy_CompileStringFlags\")]\n    pub fn Py_CompileStringFlags(\n        string: *const c_char,\n        p: *const c_char,\n        s: c_int,\n        f: *mut PyCompilerFlags,\n    ) -> *mut PyObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/tupleobject.rs",
    "content": "use crate::object::*;\n#[cfg(Py_3_14)]\nuse crate::pyport::Py_hash_t;\n#[cfg(not(PyPy))]\nuse crate::pyport::Py_ssize_t;\n\n#[repr(C)]\npub struct PyTupleObject {\n    pub ob_base: PyVarObject,\n    #[cfg(Py_3_14)]\n    pub ob_hash: Py_hash_t,\n    pub ob_item: [*mut PyObject; 1],\n}\n\n// skipped _PyTuple_Resize\n// skipped _PyTuple_MaybeUntrack\n\n// skipped _PyTuple_CAST\n\n/// Macro, trading safety for speed\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyTuple_GET_SIZE(op: *mut PyObject) -> Py_ssize_t {\n    Py_SIZE(op)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\npub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject {\n    *(*(op as *mut PyTupleObject)).ob_item.as_ptr().offset(i)\n}\n\n/// Macro, *only* to be used to fill in brand new tuples\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\npub unsafe fn PyTuple_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) {\n    *(*(op as *mut PyTupleObject)).ob_item.as_mut_ptr().offset(i) = v;\n}\n\n// skipped _PyTuple_DebugMallocStats\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/unicodeobject.rs",
    "content": "#[cfg(any(Py_3_11, not(PyPy)))]\nuse crate::Py_hash_t;\nuse crate::{PyObject, Py_UCS1, Py_UCS2, Py_UCS4, Py_ssize_t};\nuse libc::wchar_t;\nuse std::ffi::{c_char, c_int, c_uint, c_void};\n\n// skipped Py_UNICODE_ISSPACE()\n// skipped Py_UNICODE_ISLOWER()\n// skipped Py_UNICODE_ISUPPER()\n// skipped Py_UNICODE_ISTITLE()\n// skipped Py_UNICODE_ISLINEBREAK\n// skipped Py_UNICODE_TOLOWER\n// skipped Py_UNICODE_TOUPPER\n// skipped Py_UNICODE_TOTITLE\n// skipped Py_UNICODE_ISDECIMAL\n// skipped Py_UNICODE_ISDIGIT\n// skipped Py_UNICODE_ISNUMERIC\n// skipped Py_UNICODE_ISPRINTABLE\n// skipped Py_UNICODE_TODECIMAL\n// skipped Py_UNICODE_TODIGIT\n// skipped Py_UNICODE_TONUMERIC\n// skipped Py_UNICODE_ISALPHA\n// skipped Py_UNICODE_ISALNUM\n// skipped Py_UNICODE_COPY\n// skipped Py_UNICODE_FILL\n// skipped Py_UNICODE_IS_SURROGATE\n// skipped Py_UNICODE_IS_HIGH_SURROGATE\n// skipped Py_UNICODE_IS_LOW_SURROGATE\n// skipped Py_UNICODE_JOIN_SURROGATES\n// skipped Py_UNICODE_HIGH_SURROGATE\n// skipped Py_UNICODE_LOW_SURROGATE\n\n// generated by bindgen v0.63.0 (with small adaptations)\n#[cfg(not(Py_3_14))]\n#[repr(C)]\nstruct BitfieldUnit<Storage> {\n    storage: Storage,\n}\n\n#[cfg(not(Py_3_14))]\nimpl<Storage> BitfieldUnit<Storage> {\n    #[inline]\n    pub const fn new(storage: Storage) -> Self {\n        Self { storage }\n    }\n}\n\n#[cfg(not(any(GraalPy, Py_3_14)))]\nimpl<Storage> BitfieldUnit<Storage>\nwhere\n    Storage: AsRef<[u8]> + AsMut<[u8]>,\n{\n    #[inline]\n    fn get_bit(&self, index: usize) -> bool {\n        debug_assert!(index / 8 < self.storage.as_ref().len());\n        let byte_index = index / 8;\n        let byte = self.storage.as_ref()[byte_index];\n        let bit_index = if cfg!(target_endian = \"big\") {\n            7 - (index % 8)\n        } else {\n            index % 8\n        };\n        let mask = 1 << bit_index;\n        byte & mask == mask\n    }\n\n    #[inline]\n    fn set_bit(&mut self, index: usize, val: bool) {\n        debug_assert!(index / 8 < self.storage.as_ref().len());\n        let byte_index = index / 8;\n        let byte = &mut self.storage.as_mut()[byte_index];\n        let bit_index = if cfg!(target_endian = \"big\") {\n            7 - (index % 8)\n        } else {\n            index % 8\n        };\n        let mask = 1 << bit_index;\n        if val {\n            *byte |= mask;\n        } else {\n            *byte &= !mask;\n        }\n    }\n\n    #[inline]\n    fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {\n        debug_assert!(bit_width <= 64);\n        debug_assert!(bit_offset / 8 < self.storage.as_ref().len());\n        debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());\n        let mut val = 0;\n        for i in 0..(bit_width as usize) {\n            if self.get_bit(i + bit_offset) {\n                let index = if cfg!(target_endian = \"big\") {\n                    bit_width as usize - 1 - i\n                } else {\n                    i\n                };\n                val |= 1 << index;\n            }\n        }\n        val\n    }\n\n    #[inline]\n    fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {\n        debug_assert!(bit_width <= 64);\n        debug_assert!(bit_offset / 8 < self.storage.as_ref().len());\n        debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());\n        for i in 0..(bit_width as usize) {\n            let mask = 1 << i;\n            let val_bit_is_set = val & mask == mask;\n            let index = if cfg!(target_endian = \"big\") {\n                bit_width as usize - 1 - i\n            } else {\n                i\n            };\n            self.set_bit(index + bit_offset, val_bit_is_set);\n        }\n    }\n}\n\n#[cfg(not(any(GraalPy, Py_3_14)))]\nconst STATE_INTERNED_INDEX: usize = 0;\n#[cfg(not(any(GraalPy, Py_3_14)))]\nconst STATE_INTERNED_WIDTH: u8 = 2;\n\n#[cfg(not(any(GraalPy, Py_3_14)))]\nconst STATE_KIND_INDEX: usize = STATE_INTERNED_WIDTH as usize;\n#[cfg(not(any(GraalPy, Py_3_14)))]\nconst STATE_KIND_WIDTH: u8 = 3;\n\n#[cfg(not(any(GraalPy, Py_3_14)))]\nconst STATE_COMPACT_INDEX: usize = (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH) as usize;\n#[cfg(not(any(GraalPy, Py_3_14)))]\nconst STATE_COMPACT_WIDTH: u8 = 1;\n\n#[cfg(not(any(GraalPy, Py_3_14)))]\nconst STATE_ASCII_INDEX: usize =\n    (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH) as usize;\n#[cfg(not(any(GraalPy, Py_3_14)))]\nconst STATE_ASCII_WIDTH: u8 = 1;\n\n#[cfg(all(not(any(GraalPy, Py_3_14)), Py_3_12))]\nconst STATE_STATICALLY_ALLOCATED_INDEX: usize =\n    (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH + STATE_ASCII_WIDTH) as usize;\n#[cfg(all(not(any(GraalPy, Py_3_14)), Py_3_12))]\nconst STATE_STATICALLY_ALLOCATED_WIDTH: u8 = 1;\n\n#[cfg(not(any(Py_3_12, GraalPy)))]\nconst STATE_READY_INDEX: usize =\n    (STATE_INTERNED_WIDTH + STATE_KIND_WIDTH + STATE_COMPACT_WIDTH + STATE_ASCII_WIDTH) as usize;\n#[cfg(not(any(Py_3_12, GraalPy)))]\nconst STATE_READY_WIDTH: u8 = 1;\n\n// generated by bindgen v0.63.0 (with small adaptations)\n// The same code is generated for Python 3.7, 3.8, 3.9, 3.10, and 3.11, but the \"ready\" field\n// has been removed from Python 3.12.\n\n/// Wrapper around the `PyASCIIObject.state` bitfield with getters and setters that work\n/// on most little- and big-endian architectures.\n///\n/// Memory layout of C bitfields is implementation defined, so these functions are still\n/// unsafe. Users must verify that they work as expected on the architectures they target.\n#[cfg(not(Py_3_14))]\n#[repr(C)]\nstruct PyASCIIObjectState {\n    bitfield_align: [u8; 0],\n    bitfield: BitfieldUnit<[u8; 4usize]>,\n}\n\n// c_uint and u32 are not necessarily the same type on all targets / architectures\n#[cfg(not(any(GraalPy, Py_3_14)))]\n#[allow(clippy::useless_transmute)]\nimpl PyASCIIObjectState {\n    #[inline]\n    unsafe fn interned(&self) -> c_uint {\n        std::mem::transmute(\n            self.bitfield\n                .get(STATE_INTERNED_INDEX, STATE_INTERNED_WIDTH) as u32,\n        )\n    }\n\n    #[inline]\n    unsafe fn set_interned(&mut self, val: c_uint) {\n        let val: u32 = std::mem::transmute(val);\n        self.bitfield\n            .set(STATE_INTERNED_INDEX, STATE_INTERNED_WIDTH, val as u64)\n    }\n\n    #[inline]\n    unsafe fn kind(&self) -> c_uint {\n        std::mem::transmute(self.bitfield.get(STATE_KIND_INDEX, STATE_KIND_WIDTH) as u32)\n    }\n\n    #[inline]\n    unsafe fn set_kind(&mut self, val: c_uint) {\n        let val: u32 = std::mem::transmute(val);\n        self.bitfield\n            .set(STATE_KIND_INDEX, STATE_KIND_WIDTH, val as u64)\n    }\n\n    #[inline]\n    unsafe fn compact(&self) -> c_uint {\n        std::mem::transmute(self.bitfield.get(STATE_COMPACT_INDEX, STATE_COMPACT_WIDTH) as u32)\n    }\n\n    #[inline]\n    unsafe fn set_compact(&mut self, val: c_uint) {\n        let val: u32 = std::mem::transmute(val);\n        self.bitfield\n            .set(STATE_COMPACT_INDEX, STATE_COMPACT_WIDTH, val as u64)\n    }\n\n    #[inline]\n    unsafe fn ascii(&self) -> c_uint {\n        std::mem::transmute(self.bitfield.get(STATE_ASCII_INDEX, STATE_ASCII_WIDTH) as u32)\n    }\n\n    #[inline]\n    unsafe fn set_ascii(&mut self, val: c_uint) {\n        let val: u32 = std::mem::transmute(val);\n        self.bitfield\n            .set(STATE_ASCII_INDEX, STATE_ASCII_WIDTH, val as u64)\n    }\n\n    #[cfg(Py_3_12)]\n    #[inline]\n    unsafe fn statically_allocated(&self) -> c_uint {\n        std::mem::transmute(self.bitfield.get(\n            STATE_STATICALLY_ALLOCATED_INDEX,\n            STATE_STATICALLY_ALLOCATED_WIDTH,\n        ) as u32)\n    }\n\n    #[cfg(Py_3_12)]\n    #[inline]\n    unsafe fn set_statically_allocated(&mut self, val: c_uint) {\n        let val: u32 = std::mem::transmute(val);\n        self.bitfield.set(\n            STATE_STATICALLY_ALLOCATED_INDEX,\n            STATE_STATICALLY_ALLOCATED_WIDTH,\n            val as u64,\n        )\n    }\n\n    #[cfg(not(Py_3_12))]\n    #[inline]\n    unsafe fn ready(&self) -> c_uint {\n        std::mem::transmute(self.bitfield.get(STATE_READY_INDEX, STATE_READY_WIDTH) as u32)\n    }\n\n    #[cfg(not(Py_3_12))]\n    #[inline]\n    unsafe fn set_ready(&mut self, val: c_uint) {\n        let val: u32 = std::mem::transmute(val);\n        self.bitfield\n            .set(STATE_READY_INDEX, STATE_READY_WIDTH, val as u64)\n    }\n}\n\n#[cfg(not(Py_3_14))]\nimpl From<u32> for PyASCIIObjectState {\n    #[inline]\n    fn from(value: u32) -> Self {\n        PyASCIIObjectState {\n            bitfield_align: [],\n            bitfield: BitfieldUnit::new(value.to_ne_bytes()),\n        }\n    }\n}\n\n#[cfg(not(Py_3_14))]\nimpl From<PyASCIIObjectState> for u32 {\n    #[inline]\n    fn from(value: PyASCIIObjectState) -> Self {\n        u32::from_ne_bytes(value.bitfield.storage)\n    }\n}\n\n#[repr(C)]\npub struct PyASCIIObject {\n    pub ob_base: PyObject,\n    pub length: Py_ssize_t,\n    #[cfg(any(Py_3_11, not(PyPy)))]\n    pub hash: Py_hash_t,\n    /// A bit field with various properties.\n    ///\n    /// Rust doesn't expose bitfields. So we have accessor functions for\n    /// retrieving values.\n    ///\n    /// Before 3.12:\n    /// unsigned int interned:2; // SSTATE_* constants.\n    /// unsigned int kind:3;     // PyUnicode_*_KIND constants.\n    /// unsigned int compact:1;\n    /// unsigned int ascii:1;\n    /// unsigned int ready:1;\n    /// unsigned int :24;\n    ///\n    /// 3.12, and 3.13\n    /// unsigned int interned:2; // SSTATE_* constants.\n    /// unsigned int kind:3;     // PyUnicode_*_KIND constants.\n    /// unsigned int compact:1;\n    /// unsigned int ascii:1;\n    /// unsigned int statically_allocated:1;\n    /// unsigned int :24;\n    /// on 3.14 and higher PyO3 doesn't access the internal state\n    pub state: u32,\n    #[cfg(not(Py_3_12))]\n    pub wstr: *mut wchar_t,\n}\n\n/// Interacting with the bitfield is not actually well-defined, so we mark these APIs unsafe.\n#[cfg(not(any(GraalPy, Py_3_14)))]\nimpl PyASCIIObject {\n    #[cfg_attr(not(Py_3_12), allow(rustdoc::broken_intra_doc_links))] // SSTATE_INTERNED_IMMORTAL_STATIC requires 3.12\n    /// Get the `interned` field of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Returns one of: [`SSTATE_NOT_INTERNED`], [`SSTATE_INTERNED_MORTAL`],\n    /// [`SSTATE_INTERNED_IMMORTAL`], or [`SSTATE_INTERNED_IMMORTAL_STATIC`].\n    #[inline]\n    pub unsafe fn interned(&self) -> c_uint {\n        PyASCIIObjectState::from(self.state).interned()\n    }\n\n    #[cfg_attr(not(Py_3_12), allow(rustdoc::broken_intra_doc_links))] // SSTATE_INTERNED_IMMORTAL_STATIC requires 3.12\n    /// Set the `interned` field of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Calling this function with an argument that is not [`SSTATE_NOT_INTERNED`],\n    /// [`SSTATE_INTERNED_MORTAL`], [`SSTATE_INTERNED_IMMORTAL`], or\n    /// [`SSTATE_INTERNED_IMMORTAL_STATIC`] is invalid.\n    #[inline]\n    pub unsafe fn set_interned(&mut self, val: c_uint) {\n        let mut state = PyASCIIObjectState::from(self.state);\n        state.set_interned(val);\n        self.state = u32::from(state);\n    }\n\n    /// Get the `kind` field of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Returns one of:\n    #[cfg_attr(not(Py_3_12), doc = \"[`PyUnicode_WCHAR_KIND`], \")]\n    /// [`PyUnicode_1BYTE_KIND`], [`PyUnicode_2BYTE_KIND`], or [`PyUnicode_4BYTE_KIND`].\n    #[inline]\n    pub unsafe fn kind(&self) -> c_uint {\n        PyASCIIObjectState::from(self.state).kind()\n    }\n\n    /// Set the `kind` field of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Calling this function with an argument that is not\n    #[cfg_attr(not(Py_3_12), doc = \"[`PyUnicode_WCHAR_KIND`], \")]\n    /// [`PyUnicode_1BYTE_KIND`], [`PyUnicode_2BYTE_KIND`], or [`PyUnicode_4BYTE_KIND`] is invalid.\n    #[inline]\n    pub unsafe fn set_kind(&mut self, val: c_uint) {\n        let mut state = PyASCIIObjectState::from(self.state);\n        state.set_kind(val);\n        self.state = u32::from(state);\n    }\n\n    /// Get the `compact` field of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Returns either `0` or `1`.\n    #[inline]\n    pub unsafe fn compact(&self) -> c_uint {\n        PyASCIIObjectState::from(self.state).compact()\n    }\n\n    /// Set the `compact` flag of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Calling this function with an argument that is neither `0` nor `1` is invalid.\n    #[inline]\n    pub unsafe fn set_compact(&mut self, val: c_uint) {\n        let mut state = PyASCIIObjectState::from(self.state);\n        state.set_compact(val);\n        self.state = u32::from(state);\n    }\n\n    /// Get the `ascii` field of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Returns either `0` or `1`.\n    #[inline]\n    pub unsafe fn ascii(&self) -> c_uint {\n        PyASCIIObjectState::from(self.state).ascii()\n    }\n\n    /// Set the `ascii` flag of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Calling this function with an argument that is neither `0` nor `1` is invalid.\n    #[inline]\n    #[cfg(not(all(Py_3_14, Py_GIL_DISABLED)))]\n    pub unsafe fn set_ascii(&mut self, val: c_uint) {\n        let mut state = PyASCIIObjectState::from(self.state);\n        state.set_ascii(val);\n        self.state = u32::from(state);\n    }\n\n    /// Get the `ready` field of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Returns either `0` or `1`.\n    #[cfg(not(Py_3_12))]\n    #[inline]\n    pub unsafe fn ready(&self) -> c_uint {\n        PyASCIIObjectState::from(self.state).ready()\n    }\n\n    /// Set the `ready` flag of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Calling this function with an argument that is neither `0` nor `1` is invalid.\n    #[cfg(not(Py_3_12))]\n    #[inline]\n    pub unsafe fn set_ready(&mut self, val: c_uint) {\n        let mut state = PyASCIIObjectState::from(self.state);\n        state.set_ready(val);\n        self.state = u32::from(state);\n    }\n\n    /// Get the `statically_allocated` field of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Returns either `0` or `1`.\n    #[inline]\n    #[cfg(Py_3_12)]\n    pub unsafe fn statically_allocated(&self) -> c_uint {\n        PyASCIIObjectState::from(self.state).statically_allocated()\n    }\n\n    /// Set the `statically_allocated` flag of the [`PyASCIIObject`] state bitfield.\n    ///\n    /// Calling this function with an argument that is neither `0` nor `1` is invalid.\n    #[inline]\n    #[cfg(Py_3_12)]\n    pub unsafe fn set_statically_allocated(&mut self, val: c_uint) {\n        let mut state = PyASCIIObjectState::from(self.state);\n        state.set_statically_allocated(val);\n        self.state = u32::from(state);\n    }\n}\n\n#[repr(C)]\npub struct PyCompactUnicodeObject {\n    pub _base: PyASCIIObject,\n    pub utf8_length: Py_ssize_t,\n    pub utf8: *mut c_char,\n    #[cfg(not(Py_3_12))]\n    pub wstr_length: Py_ssize_t,\n}\n\n#[repr(C)]\npub union PyUnicodeObjectData {\n    pub any: *mut c_void,\n    pub latin1: *mut Py_UCS1,\n    pub ucs2: *mut Py_UCS2,\n    pub ucs4: *mut Py_UCS4,\n}\n\n#[repr(C)]\npub struct PyUnicodeObject {\n    pub _base: PyCompactUnicodeObject,\n    pub data: PyUnicodeObjectData,\n}\n\nextern_libpython! {\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn _PyUnicode_CheckConsistency(op: *mut PyObject, check_content: c_int) -> c_int;\n}\n\n// skipped PyUnicode_GET_SIZE\n// skipped PyUnicode_GET_DATA_SIZE\n// skipped PyUnicode_AS_UNICODE\n// skipped PyUnicode_AS_DATA\n\npub const SSTATE_NOT_INTERNED: c_uint = 0;\npub const SSTATE_INTERNED_MORTAL: c_uint = 1;\npub const SSTATE_INTERNED_IMMORTAL: c_uint = 2;\n#[cfg(Py_3_12)]\npub const SSTATE_INTERNED_IMMORTAL_STATIC: c_uint = 3;\n\n#[cfg(not(any(GraalPy, Py_3_14)))]\n#[inline]\npub unsafe fn PyUnicode_IS_ASCII(op: *mut PyObject) -> c_uint {\n    debug_assert!(crate::PyUnicode_Check(op) != 0);\n    #[cfg(not(Py_3_12))]\n    debug_assert!(PyUnicode_IS_READY(op) != 0);\n\n    (*(op as *mut PyASCIIObject)).ascii()\n}\n\n#[cfg(not(any(GraalPy, Py_3_14)))]\n#[inline]\npub unsafe fn PyUnicode_IS_COMPACT(op: *mut PyObject) -> c_uint {\n    (*(op as *mut PyASCIIObject)).compact()\n}\n\n#[cfg(not(any(GraalPy, Py_3_14)))]\n#[inline]\npub unsafe fn PyUnicode_IS_COMPACT_ASCII(op: *mut PyObject) -> c_uint {\n    ((*(op as *mut PyASCIIObject)).ascii() != 0 && PyUnicode_IS_COMPACT(op) != 0).into()\n}\n\n#[cfg(not(Py_3_12))]\n#[deprecated(note = \"Removed in Python 3.12\")]\npub const PyUnicode_WCHAR_KIND: c_uint = 0;\n\npub const PyUnicode_1BYTE_KIND: c_uint = 1;\npub const PyUnicode_2BYTE_KIND: c_uint = 2;\npub const PyUnicode_4BYTE_KIND: c_uint = 4;\n\n#[cfg(not(any(GraalPy, PyPy)))]\n#[inline]\npub unsafe fn PyUnicode_1BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS1 {\n    PyUnicode_DATA(op) as *mut Py_UCS1\n}\n\n#[cfg(not(any(GraalPy, PyPy)))]\n#[inline]\npub unsafe fn PyUnicode_2BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS2 {\n    PyUnicode_DATA(op) as *mut Py_UCS2\n}\n\n#[cfg(not(any(GraalPy, PyPy)))]\n#[inline]\npub unsafe fn PyUnicode_4BYTE_DATA(op: *mut PyObject) -> *mut Py_UCS4 {\n    PyUnicode_DATA(op) as *mut Py_UCS4\n}\n\n#[cfg(all(not(GraalPy), Py_3_14))]\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_KIND\")]\n    pub fn PyUnicode_KIND(op: *mut PyObject) -> c_uint;\n}\n\n#[cfg(all(not(GraalPy), not(Py_3_14)))]\n#[inline]\npub unsafe fn PyUnicode_KIND(op: *mut PyObject) -> c_uint {\n    debug_assert!(crate::PyUnicode_Check(op) != 0);\n    #[cfg(not(Py_3_12))]\n    debug_assert!(PyUnicode_IS_READY(op) != 0);\n\n    (*(op as *mut PyASCIIObject)).kind()\n}\n\n#[cfg(not(any(GraalPy, Py_3_14)))]\n#[inline]\npub unsafe fn _PyUnicode_COMPACT_DATA(op: *mut PyObject) -> *mut c_void {\n    if PyUnicode_IS_ASCII(op) != 0 {\n        (op as *mut PyASCIIObject).offset(1) as *mut c_void\n    } else {\n        (op as *mut PyCompactUnicodeObject).offset(1) as *mut c_void\n    }\n}\n\n#[cfg(not(any(GraalPy, PyPy)))]\n#[inline]\npub unsafe fn _PyUnicode_NONCOMPACT_DATA(op: *mut PyObject) -> *mut c_void {\n    debug_assert!(!(*(op as *mut PyUnicodeObject)).data.any.is_null());\n\n    (*(op as *mut PyUnicodeObject)).data.any\n}\n\n#[cfg(not(any(GraalPy, PyPy, Py_3_14)))]\n#[inline]\npub unsafe fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void {\n    debug_assert!(crate::PyUnicode_Check(op) != 0);\n\n    if PyUnicode_IS_COMPACT(op) != 0 {\n        _PyUnicode_COMPACT_DATA(op)\n    } else {\n        _PyUnicode_NONCOMPACT_DATA(op)\n    }\n}\n\n#[cfg(Py_3_14)]\n#[cfg(all(not(GraalPy), Py_3_14))]\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_DATA\")]\n    pub fn PyUnicode_DATA(op: *mut PyObject) -> *mut c_void;\n}\n\n// skipped PyUnicode_WRITE\n// skipped PyUnicode_READ\n// skipped PyUnicode_READ_CHAR\n\n#[cfg(not(GraalPy))]\n#[inline]\npub unsafe fn PyUnicode_GET_LENGTH(op: *mut PyObject) -> Py_ssize_t {\n    debug_assert!(crate::PyUnicode_Check(op) != 0);\n    #[cfg(not(Py_3_12))]\n    debug_assert!(PyUnicode_IS_READY(op) != 0);\n\n    (*(op as *mut PyASCIIObject)).length\n}\n\n#[cfg(any(Py_3_12, GraalPy))]\n#[inline]\npub unsafe fn PyUnicode_IS_READY(_op: *mut PyObject) -> c_uint {\n    // kept in CPython for backwards compatibility\n    1\n}\n\n#[cfg(not(any(GraalPy, Py_3_12)))]\n#[inline]\npub unsafe fn PyUnicode_IS_READY(op: *mut PyObject) -> c_uint {\n    (*(op as *mut PyASCIIObject)).ready()\n}\n\n#[cfg(any(Py_3_12, GraalPy))]\n#[inline]\npub unsafe fn PyUnicode_READY(_op: *mut PyObject) -> c_int {\n    0\n}\n\n#[cfg(not(any(Py_3_12, GraalPy)))]\n#[inline]\npub unsafe fn PyUnicode_READY(op: *mut PyObject) -> c_int {\n    debug_assert!(crate::PyUnicode_Check(op) != 0);\n\n    if PyUnicode_IS_READY(op) != 0 {\n        0\n    } else {\n        _PyUnicode_Ready(op)\n    }\n}\n\n// skipped PyUnicode_MAX_CHAR_VALUE\n// skipped _PyUnicode_get_wstr_length\n// skipped PyUnicode_WSTR_LENGTH\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_New\")]\n    pub fn PyUnicode_New(size: Py_ssize_t, maxchar: Py_UCS4) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"_PyPyUnicode_Ready\")]\n    pub fn _PyUnicode_Ready(unicode: *mut PyObject) -> c_int;\n\n    // skipped _PyUnicode_Copy\n\n    #[cfg(not(PyPy))]\n    pub fn PyUnicode_CopyCharacters(\n        to: *mut PyObject,\n        to_start: Py_ssize_t,\n        from: *mut PyObject,\n        from_start: Py_ssize_t,\n        how_many: Py_ssize_t,\n    ) -> Py_ssize_t;\n\n    // skipped _PyUnicode_FastCopyCharacters\n\n    #[cfg(not(PyPy))]\n    pub fn PyUnicode_Fill(\n        unicode: *mut PyObject,\n        start: Py_ssize_t,\n        length: Py_ssize_t,\n        fill_char: Py_UCS4,\n    ) -> Py_ssize_t;\n\n    // skipped _PyUnicode_FastFill\n\n    #[cfg(not(Py_3_12))]\n    #[deprecated]\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_FromUnicode\")]\n    pub fn PyUnicode_FromUnicode(u: *const wchar_t, size: Py_ssize_t) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_FromKindAndData\")]\n    pub fn PyUnicode_FromKindAndData(\n        kind: c_int,\n        buffer: *const c_void,\n        size: Py_ssize_t,\n    ) -> *mut PyObject;\n\n    // skipped _PyUnicode_FromASCII\n    // skipped _PyUnicode_FindMaxChar\n\n    #[cfg(not(Py_3_12))]\n    #[deprecated]\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsUnicode\")]\n    pub fn PyUnicode_AsUnicode(unicode: *mut PyObject) -> *mut wchar_t;\n\n    // skipped _PyUnicode_AsUnicode\n\n    #[cfg(not(Py_3_12))]\n    #[deprecated]\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsUnicodeAndSize\")]\n    pub fn PyUnicode_AsUnicodeAndSize(\n        unicode: *mut PyObject,\n        size: *mut Py_ssize_t,\n    ) -> *mut wchar_t;\n\n    // skipped PyUnicode_GetMax\n}\n\n#[cfg(Py_3_14)]\nopaque_struct!(pub PyUnicodeWriter);\n\nextern_libpython! {\n    #[cfg(Py_3_14)]\n    pub fn PyUnicodeWriter_Create(length: Py_ssize_t) -> *mut PyUnicodeWriter;\n    #[cfg(Py_3_14)]\n    pub fn PyUnicodeWriter_Finish(writer: *mut PyUnicodeWriter) -> *mut PyObject;\n    #[cfg(Py_3_14)]\n    pub fn PyUnicodeWriter_Discard(writer: *mut PyUnicodeWriter);\n    #[cfg(Py_3_14)]\n    pub fn PyUnicodeWriter_WriteChar(writer: *mut PyUnicodeWriter, ch: Py_UCS4) -> c_int;\n    #[cfg(Py_3_14)]\n    pub fn PyUnicodeWriter_WriteUTF8(\n        writer: *mut PyUnicodeWriter,\n        str: *const c_char,\n        size: Py_ssize_t,\n    ) -> c_int;\n}\n\n// skipped _PyUnicodeWriter\n// skipped _PyUnicodeWriter_Init\n// skipped _PyUnicodeWriter_Prepare\n// skipped _PyUnicodeWriter_PrepareInternal\n// skipped _PyUnicodeWriter_PrepareKind\n// skipped _PyUnicodeWriter_PrepareKindInternal\n// skipped _PyUnicodeWriter_WriteChar\n// skipped _PyUnicodeWriter_WriteStr\n// skipped _PyUnicodeWriter_WriteSubstring\n// skipped _PyUnicodeWriter_WriteASCIIString\n// skipped _PyUnicodeWriter_WriteLatin1String\n// skipped _PyUnicodeWriter_Finish\n// skipped _PyUnicodeWriter_Dealloc\n// skipped _PyUnicode_FormatAdvancedWriter\n\nextern_libpython! {\n    // skipped _PyUnicode_AsStringAndSize\n\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsUTF8\")]\n    pub fn PyUnicode_AsUTF8(unicode: *mut PyObject) -> *const c_char;\n\n    // skipped _PyUnicode_AsString\n\n    pub fn PyUnicode_Encode(\n        s: *const wchar_t,\n        size: Py_ssize_t,\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n\n    pub fn PyUnicode_EncodeUTF7(\n        data: *const wchar_t,\n        length: Py_ssize_t,\n        base64SetO: c_int,\n        base64WhiteSpace: c_int,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n\n    // skipped _PyUnicode_EncodeUTF7\n    // skipped _PyUnicode_AsUTF8String\n\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_EncodeUTF8\")]\n    pub fn PyUnicode_EncodeUTF8(\n        data: *const wchar_t,\n        length: Py_ssize_t,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n\n    pub fn PyUnicode_EncodeUTF32(\n        data: *const wchar_t,\n        length: Py_ssize_t,\n        errors: *const c_char,\n        byteorder: c_int,\n    ) -> *mut PyObject;\n\n    // skipped _PyUnicode_EncodeUTF32\n\n    pub fn PyUnicode_EncodeUTF16(\n        data: *const wchar_t,\n        length: Py_ssize_t,\n        errors: *const c_char,\n        byteorder: c_int,\n    ) -> *mut PyObject;\n\n    // skipped _PyUnicode_EncodeUTF16\n    // skipped _PyUnicode_DecodeUnicodeEscape\n\n    pub fn PyUnicode_EncodeUnicodeEscape(data: *const wchar_t, length: Py_ssize_t)\n        -> *mut PyObject;\n\n    pub fn PyUnicode_EncodeRawUnicodeEscape(\n        data: *const wchar_t,\n        length: Py_ssize_t,\n    ) -> *mut PyObject;\n\n    // skipped _PyUnicode_AsLatin1String\n\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_EncodeLatin1\")]\n    pub fn PyUnicode_EncodeLatin1(\n        data: *const wchar_t,\n        length: Py_ssize_t,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n\n    // skipped _PyUnicode_AsASCIIString\n\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_EncodeASCII\")]\n    pub fn PyUnicode_EncodeASCII(\n        data: *const wchar_t,\n        length: Py_ssize_t,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n\n    pub fn PyUnicode_EncodeCharmap(\n        data: *const wchar_t,\n        length: Py_ssize_t,\n        mapping: *mut PyObject,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n\n    // skipped _PyUnicode_EncodeCharmap\n\n    pub fn PyUnicode_TranslateCharmap(\n        data: *const wchar_t,\n        length: Py_ssize_t,\n        table: *mut PyObject,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n\n    // skipped PyUnicode_EncodeMBCS\n\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_EncodeDecimal\")]\n    pub fn PyUnicode_EncodeDecimal(\n        s: *mut wchar_t,\n        length: Py_ssize_t,\n        output: *mut c_char,\n        errors: *const c_char,\n    ) -> c_int;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_TransformDecimalToASCII\")]\n    pub fn PyUnicode_TransformDecimalToASCII(s: *mut wchar_t, length: Py_ssize_t) -> *mut PyObject;\n\n    // skipped _PyUnicode_TransformDecimalAndSpaceToASCII\n}\n\n// skipped _PyUnicode_JoinArray\n// skipped _PyUnicode_EqualToASCIIId\n// skipped _PyUnicode_EqualToASCIIString\n// skipped _PyUnicode_XStrip\n// skipped _PyUnicode_InsertThousandsGrouping\n\n// skipped _Py_ascii_whitespace\n\n// skipped _PyUnicode_IsLowercase\n// skipped _PyUnicode_IsUppercase\n// skipped _PyUnicode_IsTitlecase\n// skipped _PyUnicode_IsXidStart\n// skipped _PyUnicode_IsXidContinue\n// skipped _PyUnicode_IsWhitespace\n// skipped _PyUnicode_IsLinebreak\n// skipped _PyUnicode_ToLowercase\n// skipped _PyUnicode_ToUppercase\n// skipped _PyUnicode_ToTitlecase\n// skipped _PyUnicode_ToLowerFull\n// skipped _PyUnicode_ToTitleFull\n// skipped _PyUnicode_ToUpperFull\n// skipped _PyUnicode_ToFoldedFull\n// skipped _PyUnicode_IsCaseIgnorable\n// skipped _PyUnicode_IsCased\n// skipped _PyUnicode_ToDecimalDigit\n// skipped _PyUnicode_ToDigit\n// skipped _PyUnicode_ToNumeric\n// skipped _PyUnicode_IsDecimalDigit\n// skipped _PyUnicode_IsDigit\n// skipped _PyUnicode_IsNumeric\n// skipped _PyUnicode_IsPrintable\n// skipped _PyUnicode_IsAlpha\n// skipped Py_UNICODE_strlen\n// skipped Py_UNICODE_strcpy\n// skipped Py_UNICODE_strcat\n// skipped Py_UNICODE_strncpy\n// skipped Py_UNICODE_strcmp\n// skipped Py_UNICODE_strncmp\n// skipped Py_UNICODE_strchr\n// skipped Py_UNICODE_strrchr\n// skipped _PyUnicode_FormatLong\n// skipped PyUnicode_AsUnicodeCopy\n// skipped _PyUnicode_FromId\n// skipped _PyUnicode_EQ\n// skipped _PyUnicode_ScanIdentifier\n"
  },
  {
    "path": "pyo3-ffi/src/cpython/weakrefobject.rs",
    "content": "// NB publicly re-exported in `src/weakrefobject.rs`\n#[cfg(not(any(PyPy, GraalPy)))]\npub struct _PyWeakReference {\n    pub ob_base: crate::PyObject,\n    pub wr_object: *mut crate::PyObject,\n    pub wr_callback: *mut crate::PyObject,\n    pub hash: crate::Py_hash_t,\n    pub wr_prev: *mut crate::PyWeakReference,\n    pub wr_next: *mut crate::PyWeakReference,\n    #[cfg(Py_3_11)]\n    pub vectorcall: Option<crate::vectorcallfunc>,\n    #[cfg(all(Py_3_13, Py_GIL_DISABLED))]\n    pub weakrefs_lock: *mut crate::PyMutex,\n}\n\n// skipped _PyWeakref_GetWeakrefCount\n// skipped _PyWeakref_ClearRef\n// skipped PyWeakRef_GET_OBJECT\n"
  },
  {
    "path": "pyo3-ffi/src/datetime.rs",
    "content": "//! FFI bindings to the functions and structs defined in `datetime.h`\n//!\n//! This is the unsafe thin  wrapper around the [CPython C API](https://docs.python.org/3/c-api/datetime.html),\n//! and covers the various date and time related objects in the Python `datetime`\n//! standard library module.\n\n#[cfg(not(PyPy))]\nuse crate::PyCapsule_Import;\n#[cfg(GraalPy)]\nuse crate::{PyLong_AsLong, PyLong_Check, PyObject_GetAttrString, Py_DecRef};\nuse crate::{PyObject, PyObject_TypeCheck, PyTypeObject, Py_TYPE};\nuse std::ffi::c_char;\nuse std::ffi::c_int;\nuse std::ptr;\nuse std::sync::Once;\nuse std::{cell::UnsafeCell, ffi::CStr};\n#[cfg(not(PyPy))]\nuse {crate::Py_hash_t, std::ffi::c_uchar};\n// Type struct wrappers\nconst _PyDateTime_DATE_DATASIZE: usize = 4;\nconst _PyDateTime_TIME_DATASIZE: usize = 6;\nconst _PyDateTime_DATETIME_DATASIZE: usize = 10;\n\n#[repr(C)]\n#[derive(Debug)]\n/// Structure representing a `datetime.timedelta`.\npub struct PyDateTime_Delta {\n    pub ob_base: PyObject,\n    #[cfg(not(PyPy))]\n    pub hashcode: Py_hash_t,\n    pub days: c_int,\n    pub seconds: c_int,\n    pub microseconds: c_int,\n}\n\n// skipped non-limited PyDateTime_TZInfo\n// skipped non-limited _PyDateTime_BaseTZInfo\n\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(C)]\n#[derive(Debug)]\n/// Structure representing a `datetime.time` without a `tzinfo` member.\npub struct _PyDateTime_BaseTime {\n    pub ob_base: PyObject,\n    pub hashcode: Py_hash_t,\n    pub hastzinfo: c_char,\n    pub data: [c_uchar; _PyDateTime_TIME_DATASIZE],\n}\n\n#[repr(C)]\n#[derive(Debug)]\n/// Structure representing a `datetime.time`.\npub struct PyDateTime_Time {\n    pub ob_base: PyObject,\n    #[cfg(not(PyPy))]\n    pub hashcode: Py_hash_t,\n    pub hastzinfo: c_char,\n    #[cfg(not(PyPy))]\n    pub data: [c_uchar; _PyDateTime_TIME_DATASIZE],\n    #[cfg(not(PyPy))]\n    pub fold: c_uchar,\n    /// # Safety\n    ///\n    /// Care should be taken when reading this field. If the time does not have a\n    /// tzinfo then CPython may allocate as a `_PyDateTime_BaseTime` without this field.\n    pub tzinfo: *mut PyObject,\n}\n\n#[repr(C)]\n#[derive(Debug)]\n/// Structure representing a `datetime.date`\npub struct PyDateTime_Date {\n    pub ob_base: PyObject,\n    #[cfg(not(PyPy))]\n    pub hashcode: Py_hash_t,\n    #[cfg(not(PyPy))]\n    pub hastzinfo: c_char,\n    #[cfg(not(PyPy))]\n    pub data: [c_uchar; _PyDateTime_DATE_DATASIZE],\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(C)]\n#[derive(Debug)]\n/// Structure representing a `datetime.datetime` without a `tzinfo` member.\npub struct _PyDateTime_BaseDateTime {\n    pub ob_base: PyObject,\n    pub hashcode: Py_hash_t,\n    pub hastzinfo: c_char,\n    pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE],\n}\n\n#[repr(C)]\n#[derive(Debug)]\n/// Structure representing a `datetime.datetime`.\npub struct PyDateTime_DateTime {\n    pub ob_base: PyObject,\n    #[cfg(not(PyPy))]\n    pub hashcode: Py_hash_t,\n    pub hastzinfo: c_char,\n    #[cfg(not(PyPy))]\n    pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE],\n    #[cfg(not(PyPy))]\n    pub fold: c_uchar,\n    /// # Safety\n    ///\n    /// Care should be taken when reading this field. If the time does not have a\n    /// tzinfo then CPython may allocate as a `_PyDateTime_BaseDateTime` without this field.\n    pub tzinfo: *mut PyObject,\n}\n\n// skipped non-limited _PyDateTime_HAS_TZINFO\n\n// Accessor functions for PyDateTime_Date and PyDateTime_DateTime\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the year component of a `PyDateTime_Date` or `PyDateTime_DateTime`.\n/// Returns a signed integer greater than 0.\npub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int {\n    // This should work for Date or DateTime\n    let data = (*(o as *mut PyDateTime_Date)).data;\n    (c_int::from(data[0]) << 8) | c_int::from(data[1])\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the month component of a `PyDateTime_Date` or `PyDateTime_DateTime`.\n/// Returns a signed integer in the range `[1, 12]`.\npub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int {\n    let data = (*(o as *mut PyDateTime_Date)).data;\n    c_int::from(data[2])\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the day component of a `PyDateTime_Date` or `PyDateTime_DateTime`.\n/// Returns a signed integer in the interval `[1, 31]`.\npub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int {\n    let data = (*(o as *mut PyDateTime_Date)).data;\n    c_int::from(data[3])\n}\n\n// Accessor macros for times\n#[cfg(not(any(PyPy, GraalPy)))]\nmacro_rules! _PyDateTime_GET_HOUR {\n    ($o: expr, $offset:expr) => {\n        c_int::from((*$o).data[$offset + 0])\n    };\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\nmacro_rules! _PyDateTime_GET_MINUTE {\n    ($o: expr, $offset:expr) => {\n        c_int::from((*$o).data[$offset + 1])\n    };\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\nmacro_rules! _PyDateTime_GET_SECOND {\n    ($o: expr, $offset:expr) => {\n        c_int::from((*$o).data[$offset + 2])\n    };\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\nmacro_rules! _PyDateTime_GET_MICROSECOND {\n    ($o: expr, $offset:expr) => {\n        (c_int::from((*$o).data[$offset + 3]) << 16)\n            | (c_int::from((*$o).data[$offset + 4]) << 8)\n            | (c_int::from((*$o).data[$offset + 5]))\n    };\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\nmacro_rules! _PyDateTime_GET_FOLD {\n    ($o: expr) => {\n        (*$o).fold\n    };\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\nmacro_rules! _PyDateTime_GET_TZINFO {\n    ($o: expr) => {\n        if (*$o).hastzinfo != 0 {\n            (*$o).tzinfo\n        } else {\n            $crate::Py_None()\n        }\n    };\n}\n\n// Accessor functions for DateTime\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the hour component of a `PyDateTime_DateTime`.\n/// Returns a signed integer in the interval `[0, 23]`\npub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int {\n    _PyDateTime_GET_HOUR!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the minute component of a `PyDateTime_DateTime`.\n/// Returns a signed integer in the interval `[0, 59]`\npub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int {\n    _PyDateTime_GET_MINUTE!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the second component of a `PyDateTime_DateTime`.\n/// Returns a signed integer in the interval `[0, 59]`\npub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int {\n    _PyDateTime_GET_SECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the microsecond component of a `PyDateTime_DateTime`.\n/// Returns a signed integer in the interval `[0, 999999]`\npub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int {\n    _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the fold component of a `PyDateTime_DateTime`.\n/// Returns a signed integer in the interval `[0, 1]`\npub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar {\n    _PyDateTime_GET_FOLD!(o as *mut PyDateTime_DateTime)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the tzinfo component of a `PyDateTime_DateTime`.\n/// Returns a pointer to a `PyObject` that should be either NULL or an instance\n/// of a `datetime.tzinfo` subclass.\npub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {\n    _PyDateTime_GET_TZINFO!(o as *mut PyDateTime_DateTime)\n}\n\n// Accessor functions for Time\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the hour component of a `PyDateTime_Time`.\n/// Returns a signed integer in the interval `[0, 23]`\npub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int {\n    _PyDateTime_GET_HOUR!((o as *mut PyDateTime_Time), 0)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the minute component of a `PyDateTime_Time`.\n/// Returns a signed integer in the interval `[0, 59]`\npub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int {\n    _PyDateTime_GET_MINUTE!((o as *mut PyDateTime_Time), 0)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the second component of a `PyDateTime_DateTime`.\n/// Returns a signed integer in the interval `[0, 59]`\npub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int {\n    _PyDateTime_GET_SECOND!((o as *mut PyDateTime_Time), 0)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the microsecond component of a `PyDateTime_DateTime`.\n/// Returns a signed integer in the interval `[0, 999999]`\npub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int {\n    _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_Time), 0)\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\n#[inline]\n/// Retrieve the fold component of a `PyDateTime_Time`.\n/// Returns a signed integer in the interval `[0, 1]`\npub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_uchar {\n    _PyDateTime_GET_FOLD!(o as *mut PyDateTime_Time)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the tzinfo component of a `PyDateTime_Time`.\n/// Returns a pointer to a `PyObject` that should be either NULL or an instance\n/// of a `datetime.tzinfo` subclass.\npub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {\n    _PyDateTime_GET_TZINFO!(o as *mut PyDateTime_Time)\n}\n\n// Accessor functions\n#[cfg(not(any(PyPy, GraalPy)))]\nmacro_rules! _access_field {\n    ($obj:expr, $type: ident, $field:ident) => {\n        (*($obj as *mut $type)).$field\n    };\n}\n\n// Accessor functions for PyDateTime_Delta\n#[cfg(not(any(PyPy, GraalPy)))]\nmacro_rules! _access_delta_field {\n    ($obj:expr, $field:ident) => {\n        _access_field!($obj, PyDateTime_Delta, $field)\n    };\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the days component of a `PyDateTime_Delta`.\n///\n/// Returns a signed integer in the interval [-999999999, 999999999].\n///\n/// Note: This retrieves a component from the underlying structure, it is *not*\n/// a representation of the total duration of the structure.\npub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int {\n    _access_delta_field!(o, days)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the seconds component of a `PyDateTime_Delta`.\n///\n/// Returns a signed integer in the interval [0, 86399].\n///\n/// Note: This retrieves a component from the underlying structure, it is *not*\n/// a representation of the total duration of the structure.\npub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int {\n    _access_delta_field!(o, seconds)\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\n/// Retrieve the seconds component of a `PyDateTime_Delta`.\n///\n/// Returns a signed integer in the interval [0, 999999].\n///\n/// Note: This retrieves a component from the underlying structure, it is *not*\n/// a representation of the total duration of the structure.\npub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int {\n    _access_delta_field!(o, microseconds)\n}\n\n// Accessor functions for GraalPy. The macros on GraalPy work differently,\n// but copying them seems suboptimal\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn _get_attr(obj: *mut PyObject, field: &std::ffi::CStr) -> c_int {\n    let result = PyObject_GetAttrString(obj, field.as_ptr());\n    Py_DecRef(result); // the original macros are borrowing\n    if PyLong_Check(result) == 1 {\n        PyLong_AsLong(result) as c_int\n    } else {\n        0\n    }\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"year\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"month\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"day\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"hour\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"minute\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"second\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"microsecond\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"fold\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {\n    let res = PyObject_GetAttrString(o, c\"tzinfo\".as_ptr().cast());\n    Py_DecRef(res); // the original macros are borrowing\n    res\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"hour\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"minute\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"second\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"microsecond\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"fold\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {\n    let res = PyObject_GetAttrString(o, c\"tzinfo\".as_ptr().cast());\n    Py_DecRef(res); // the original macros are borrowing\n    res\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"days\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"seconds\")\n}\n\n#[inline]\n#[cfg(GraalPy)]\npub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int {\n    _get_attr(o, c\"microseconds\")\n}\n\n#[cfg(PyPy)]\nextern_libpython! {\n    // skipped _PyDateTime_HAS_TZINFO (not in PyPy)\n    #[link_name = \"PyPyDateTime_GET_YEAR\"]\n    pub fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_GET_MONTH\"]\n    pub fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_GET_DAY\"]\n    pub fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int;\n\n    #[link_name = \"PyPyDateTime_DATE_GET_HOUR\"]\n    pub fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_DATE_GET_MINUTE\"]\n    pub fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_DATE_GET_SECOND\"]\n    pub fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_DATE_GET_MICROSECOND\"]\n    pub fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_GET_FOLD\"]\n    pub fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_DATE_GET_TZINFO\"]\n    #[cfg(Py_3_10)]\n    pub fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject;\n\n    #[link_name = \"PyPyDateTime_TIME_GET_HOUR\"]\n    pub fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_TIME_GET_MINUTE\"]\n    pub fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_TIME_GET_SECOND\"]\n    pub fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_TIME_GET_MICROSECOND\"]\n    pub fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_TIME_GET_FOLD\"]\n    pub fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_TIME_GET_TZINFO\"]\n    #[cfg(Py_3_10)]\n    pub fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject;\n\n    #[link_name = \"PyPyDateTime_DELTA_GET_DAYS\"]\n    pub fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_DELTA_GET_SECONDS\"]\n    pub fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int;\n    #[link_name = \"PyPyDateTime_DELTA_GET_MICROSECONDS\"]\n    pub fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int;\n}\n\n#[repr(C)]\n#[derive(Debug, Copy, Clone)]\npub struct PyDateTime_CAPI {\n    pub DateType: *mut PyTypeObject,\n    pub DateTimeType: *mut PyTypeObject,\n    pub TimeType: *mut PyTypeObject,\n    pub DeltaType: *mut PyTypeObject,\n    pub TZInfoType: *mut PyTypeObject,\n    pub TimeZone_UTC: *mut PyObject,\n    pub Date_FromDate: unsafe extern \"C\" fn(\n        year: c_int,\n        month: c_int,\n        day: c_int,\n        cls: *mut PyTypeObject,\n    ) -> *mut PyObject,\n    pub DateTime_FromDateAndTime: unsafe extern \"C\" fn(\n        year: c_int,\n        month: c_int,\n        day: c_int,\n        hour: c_int,\n        minute: c_int,\n        second: c_int,\n        microsecond: c_int,\n        tzinfo: *mut PyObject,\n        cls: *mut PyTypeObject,\n    ) -> *mut PyObject,\n    pub Time_FromTime: unsafe extern \"C\" fn(\n        hour: c_int,\n        minute: c_int,\n        second: c_int,\n        microsecond: c_int,\n        tzinfo: *mut PyObject,\n        cls: *mut PyTypeObject,\n    ) -> *mut PyObject,\n    pub Delta_FromDelta: unsafe extern \"C\" fn(\n        days: c_int,\n        seconds: c_int,\n        microseconds: c_int,\n        normalize: c_int,\n        cls: *mut PyTypeObject,\n    ) -> *mut PyObject,\n    pub TimeZone_FromTimeZone:\n        unsafe extern \"C\" fn(offset: *mut PyObject, name: *mut PyObject) -> *mut PyObject,\n\n    pub DateTime_FromTimestamp: unsafe extern \"C\" fn(\n        cls: *mut PyTypeObject,\n        args: *mut PyObject,\n        kwargs: *mut PyObject,\n    ) -> *mut PyObject,\n    pub Date_FromTimestamp:\n        unsafe extern \"C\" fn(cls: *mut PyTypeObject, args: *mut PyObject) -> *mut PyObject,\n    pub DateTime_FromDateAndTimeAndFold: unsafe extern \"C\" fn(\n        year: c_int,\n        month: c_int,\n        day: c_int,\n        hour: c_int,\n        minute: c_int,\n        second: c_int,\n        microsecond: c_int,\n        tzinfo: *mut PyObject,\n        fold: c_int,\n        cls: *mut PyTypeObject,\n    ) -> *mut PyObject,\n    pub Time_FromTimeAndFold: unsafe extern \"C\" fn(\n        hour: c_int,\n        minute: c_int,\n        second: c_int,\n        microsecond: c_int,\n        tzinfo: *mut PyObject,\n        fold: c_int,\n        cls: *mut PyTypeObject,\n    ) -> *mut PyObject,\n}\n\n// Python already shares this object between threads, so it's no more evil for us to do it too!\nunsafe impl Sync for PyDateTime_CAPI {}\n\npub const PyDateTime_CAPSULE_NAME: &CStr = c\"datetime.datetime_CAPI\";\n\n/// Returns a pointer to a `PyDateTime_CAPI` instance\n///\n/// # Note\n/// This function will return a null pointer until\n/// `PyDateTime_IMPORT` is called\n#[inline]\npub unsafe fn PyDateTimeAPI() -> *mut PyDateTime_CAPI {\n    *PyDateTimeAPI_impl.ptr.get()\n}\n\n/// Populates the `PyDateTimeAPI` object\npub unsafe fn PyDateTime_IMPORT() {\n    if !PyDateTimeAPI_impl.once.is_completed() {\n        // PyPy expects the C-API to be initialized via PyDateTime_Import, so trying to use\n        // `PyCapsule_Import` will behave unexpectedly in pypy.\n        #[cfg(PyPy)]\n        let py_datetime_c_api = PyDateTime_Import();\n\n        #[cfg(not(PyPy))]\n        let py_datetime_c_api =\n            PyCapsule_Import(PyDateTime_CAPSULE_NAME.as_ptr(), 1) as *mut PyDateTime_CAPI;\n\n        if py_datetime_c_api.is_null() {\n            return;\n        }\n\n        // Protect against race conditions when the datetime API is concurrently\n        // initialized in multiple threads. UnsafeCell.get() cannot panic so this\n        // won't panic either.\n        PyDateTimeAPI_impl.once.call_once(|| {\n            *PyDateTimeAPI_impl.ptr.get() = py_datetime_c_api;\n        });\n    }\n}\n\n#[inline]\npub unsafe fn PyDateTime_TimeZone_UTC() -> *mut PyObject {\n    (*PyDateTimeAPI()).TimeZone_UTC\n}\n\n/// Type Check macros\n///\n/// These are bindings around the C API typecheck macros, all of them return\n/// `1` if True and `0` if False. In all type check macros, the argument (`op`)\n/// must not be `NULL`.\n#[inline]\n/// Check if `op` is a `PyDateTimeAPI.DateType` or subtype.\npub unsafe fn PyDate_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, (*PyDateTimeAPI()).DateType) as c_int\n}\n\n#[inline]\n/// Check if `op`'s type is exactly `PyDateTimeAPI.DateType`.\npub unsafe fn PyDate_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == (*PyDateTimeAPI()).DateType) as c_int\n}\n\n#[inline]\n/// Check if `op` is a `PyDateTimeAPI.DateTimeType` or subtype.\npub unsafe fn PyDateTime_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, (*PyDateTimeAPI()).DateTimeType) as c_int\n}\n\n#[inline]\n/// Check if `op`'s type is exactly `PyDateTimeAPI.DateTimeType`.\npub unsafe fn PyDateTime_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == (*PyDateTimeAPI()).DateTimeType) as c_int\n}\n\n#[inline]\n/// Check if `op` is a `PyDateTimeAPI.TimeType` or subtype.\npub unsafe fn PyTime_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, (*PyDateTimeAPI()).TimeType) as c_int\n}\n\n#[inline]\n/// Check if `op`'s type is exactly `PyDateTimeAPI.TimeType`.\npub unsafe fn PyTime_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == (*PyDateTimeAPI()).TimeType) as c_int\n}\n\n#[inline]\n/// Check if `op` is a `PyDateTimeAPI.DetaType` or subtype.\npub unsafe fn PyDelta_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, (*PyDateTimeAPI()).DeltaType) as c_int\n}\n\n#[inline]\n/// Check if `op`'s type is exactly `PyDateTimeAPI.DeltaType`.\npub unsafe fn PyDelta_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == (*PyDateTimeAPI()).DeltaType) as c_int\n}\n\n#[inline]\n/// Check if `op` is a `PyDateTimeAPI.TZInfoType` or subtype.\npub unsafe fn PyTZInfo_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, (*PyDateTimeAPI()).TZInfoType) as c_int\n}\n\n#[inline]\n/// Check if `op`'s type is exactly `PyDateTimeAPI.TZInfoType`.\npub unsafe fn PyTZInfo_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == (*PyDateTimeAPI()).TZInfoType) as c_int\n}\n\n// skipped non-limited PyDate_FromDate\n// skipped non-limited PyDateTime_FromDateAndTime\n// skipped non-limited PyDateTime_FromDateAndTimeAndFold\n// skipped non-limited PyTime_FromTime\n// skipped non-limited PyTime_FromTimeAndFold\n// skipped non-limited PyDelta_FromDSU\n\npub unsafe fn PyTimeZone_FromOffset(offset: *mut PyObject) -> *mut PyObject {\n    ((*PyDateTimeAPI()).TimeZone_FromTimeZone)(offset, std::ptr::null_mut())\n}\n\npub unsafe fn PyTimeZone_FromOffsetAndName(\n    offset: *mut PyObject,\n    name: *mut PyObject,\n) -> *mut PyObject {\n    ((*PyDateTimeAPI()).TimeZone_FromTimeZone)(offset, name)\n}\n\n#[cfg(not(PyPy))]\npub unsafe fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject {\n    let f = (*PyDateTimeAPI()).DateTime_FromTimestamp;\n    f((*PyDateTimeAPI()).DateTimeType, args, std::ptr::null_mut())\n}\n\n#[cfg(not(PyPy))]\npub unsafe fn PyDate_FromTimestamp(args: *mut PyObject) -> *mut PyObject {\n    let f = (*PyDateTimeAPI()).Date_FromTimestamp;\n    f((*PyDateTimeAPI()).DateType, args)\n}\n\n#[cfg(PyPy)]\nextern_libpython! {\n    #[link_name = \"PyPyDate_FromTimestamp\"]\n    pub fn PyDate_FromTimestamp(args: *mut PyObject) -> *mut PyObject;\n    #[link_name = \"PyPyDateTime_FromTimestamp\"]\n    pub fn PyDateTime_FromTimestamp(args: *mut PyObject) -> *mut PyObject;\n}\n\n#[cfg(PyPy)]\nextern_libpython! {\n    #[link_name = \"_PyPyDateTime_Import\"]\n    pub fn PyDateTime_Import() -> *mut PyDateTime_CAPI;\n}\n\n// Rust specific implementation details\n\nstruct PyDateTimeAPISingleton {\n    once: Once,\n    ptr: UnsafeCell<*mut PyDateTime_CAPI>,\n}\nunsafe impl Sync for PyDateTimeAPISingleton {}\n\nstatic PyDateTimeAPI_impl: PyDateTimeAPISingleton = PyDateTimeAPISingleton {\n    once: Once::new(),\n    ptr: UnsafeCell::new(ptr::null_mut()),\n};\n"
  },
  {
    "path": "pyo3-ffi/src/descrobject.rs",
    "content": "use crate::methodobject::PyMethodDef;\nuse crate::object::{PyObject, PyTypeObject};\nuse crate::Py_ssize_t;\nuse std::ffi::{c_char, c_int, c_void};\nuse std::ptr;\n\npub type getter = unsafe extern \"C\" fn(slf: *mut PyObject, closure: *mut c_void) -> *mut PyObject;\npub type setter =\n    unsafe extern \"C\" fn(slf: *mut PyObject, value: *mut PyObject, closure: *mut c_void) -> c_int;\n\n/// Represents the [PyGetSetDef](https://docs.python.org/3/c-api/structures.html#c.PyGetSetDef)\n/// structure.\n///\n/// Note that CPython may leave fields uninitialized. You must ensure that\n/// `name` != NULL before dereferencing or reading other fields.\n#[repr(C)]\n#[derive(Copy, Clone, Debug)]\npub struct PyGetSetDef {\n    pub name: *const c_char,\n    pub get: Option<getter>,\n    pub set: Option<setter>,\n    pub doc: *const c_char,\n    pub closure: *mut c_void,\n}\n\nimpl Default for PyGetSetDef {\n    fn default() -> PyGetSetDef {\n        PyGetSetDef {\n            name: ptr::null(),\n            get: None,\n            set: None,\n            doc: ptr::null(),\n            closure: ptr::null_mut(),\n        }\n    }\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyClassMethodDescr_Type\")]\n    pub static mut PyClassMethodDescr_Type: PyTypeObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyGetSetDescr_Type\")]\n    pub static mut PyGetSetDescr_Type: PyTypeObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyMemberDescr_Type\")]\n    pub static mut PyMemberDescr_Type: PyTypeObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyMethodDescr_Type\")]\n    pub static mut PyMethodDescr_Type: PyTypeObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyWrapperDescr_Type\")]\n    pub static mut PyWrapperDescr_Type: PyTypeObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDictProxy_Type\")]\n    pub static mut PyDictProxy_Type: PyTypeObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyProperty_Type\")]\n    pub static mut PyProperty_Type: PyTypeObject;\n}\n\nextern_libpython! {\n    pub fn PyDescr_NewMethod(arg1: *mut PyTypeObject, arg2: *mut PyMethodDef) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDescr_NewClassMethod\")]\n    pub fn PyDescr_NewClassMethod(arg1: *mut PyTypeObject, arg2: *mut PyMethodDef)\n        -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDescr_NewMember\")]\n    pub fn PyDescr_NewMember(arg1: *mut PyTypeObject, arg2: *mut PyMemberDef) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDescr_NewGetSet\")]\n    pub fn PyDescr_NewGetSet(arg1: *mut PyTypeObject, arg2: *mut PyGetSetDef) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyDictProxy_New\")]\n    pub fn PyDictProxy_New(arg1: *mut PyObject) -> *mut PyObject;\n    pub fn PyWrapper_New(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;\n}\n\n/// Represents the [PyMemberDef](https://docs.python.org/3/c-api/structures.html#c.PyMemberDef)\n/// structure.\n///\n/// Note that CPython may leave fields uninitialized. You must always ensure that\n/// `name` != NULL before dereferencing or reading other fields.\n#[repr(C)]\n#[derive(Copy, Clone, Eq, PartialEq)]\npub struct PyMemberDef {\n    pub name: *const c_char,\n    pub type_code: c_int,\n    pub offset: Py_ssize_t,\n    pub flags: c_int,\n    pub doc: *const c_char,\n}\n\nimpl Default for PyMemberDef {\n    fn default() -> PyMemberDef {\n        PyMemberDef {\n            name: ptr::null_mut(),\n            type_code: 0,\n            offset: 0,\n            flags: 0,\n            doc: ptr::null_mut(),\n        }\n    }\n}\n\n/* Types */\npub const Py_T_SHORT: c_int = 0;\npub const Py_T_INT: c_int = 1;\npub const Py_T_LONG: c_int = 2;\npub const Py_T_FLOAT: c_int = 3;\npub const Py_T_DOUBLE: c_int = 4;\npub const Py_T_STRING: c_int = 5;\n#[deprecated(note = \"Use Py_T_OBJECT_EX instead\")]\npub const _Py_T_OBJECT: c_int = 6;\npub const Py_T_CHAR: c_int = 7;\npub const Py_T_BYTE: c_int = 8;\npub const Py_T_UBYTE: c_int = 9;\npub const Py_T_USHORT: c_int = 10;\npub const Py_T_UINT: c_int = 11;\npub const Py_T_ULONG: c_int = 12;\npub const Py_T_STRING_INPLACE: c_int = 13;\npub const Py_T_BOOL: c_int = 14;\npub const Py_T_OBJECT_EX: c_int = 16;\npub const Py_T_LONGLONG: c_int = 17;\npub const Py_T_ULONGLONG: c_int = 18;\npub const Py_T_PYSSIZET: c_int = 19;\n#[deprecated(note = \"Value is always none\")]\npub const _Py_T_NONE: c_int = 20;\n\n/* Flags */\npub const Py_READONLY: c_int = 1;\n#[cfg(Py_3_10)]\npub const Py_AUDIT_READ: c_int = 2; // Added in 3.10, harmless no-op before that\n#[deprecated]\npub const _Py_WRITE_RESTRICTED: c_int = 4; // Deprecated, no-op. Do not reuse the value.\npub const Py_RELATIVE_OFFSET: c_int = 8;\n\nextern_libpython! {\n    pub fn PyMember_GetOne(addr: *const c_char, l: *mut PyMemberDef) -> *mut PyObject;\n    pub fn PyMember_SetOne(addr: *mut c_char, l: *mut PyMemberDef, value: *mut PyObject) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/dictobject.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::{c_char, c_int};\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_Type\")]\n    pub static mut PyDict_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyDict_Check(op: *mut PyObject) -> c_int {\n    PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS)\n}\n\n#[inline]\npub unsafe fn PyDict_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyDict_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_New\")]\n    pub fn PyDict_New() -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_GetItem\")]\n    pub fn PyDict_GetItem(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_GetItemWithError\")]\n    pub fn PyDict_GetItemWithError(mp: *mut PyObject, key: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_SetItem\")]\n    pub fn PyDict_SetItem(mp: *mut PyObject, key: *mut PyObject, item: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_DelItem\")]\n    pub fn PyDict_DelItem(mp: *mut PyObject, key: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_Clear\")]\n    pub fn PyDict_Clear(mp: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_Next\")]\n    pub fn PyDict_Next(\n        mp: *mut PyObject,\n        pos: *mut Py_ssize_t,\n        key: *mut *mut PyObject,\n        value: *mut *mut PyObject,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_Keys\")]\n    pub fn PyDict_Keys(mp: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_Values\")]\n    pub fn PyDict_Values(mp: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_Items\")]\n    pub fn PyDict_Items(mp: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_Size\")]\n    pub fn PyDict_Size(mp: *mut PyObject) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_Copy\")]\n    pub fn PyDict_Copy(mp: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_Contains\")]\n    pub fn PyDict_Contains(mp: *mut PyObject, key: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_Update\")]\n    pub fn PyDict_Update(mp: *mut PyObject, other: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_Merge\")]\n    pub fn PyDict_Merge(mp: *mut PyObject, other: *mut PyObject, _override: c_int) -> c_int;\n    pub fn PyDict_MergeFromSeq2(d: *mut PyObject, seq2: *mut PyObject, _override: c_int) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_GetItemString\")]\n    pub fn PyDict_GetItemString(dp: *mut PyObject, key: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_SetItemString\")]\n    pub fn PyDict_SetItemString(\n        dp: *mut PyObject,\n        key: *const c_char,\n        item: *mut PyObject,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_DelItemString\")]\n    pub fn PyDict_DelItemString(dp: *mut PyObject, key: *const c_char) -> c_int;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_GetItemRef\")]\n    pub fn PyDict_GetItemRef(\n        dp: *mut PyObject,\n        key: *mut PyObject,\n        result: *mut *mut PyObject,\n    ) -> c_int;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyDict_GetItemStringRef\")]\n    pub fn PyDict_GetItemStringRef(\n        dp: *mut PyObject,\n        key: *const c_char,\n        result: *mut *mut PyObject,\n    ) -> c_int;\n    // skipped 3.10 / ex-non-limited PyObject_GenericGetDict\n}\n\nextern_libpython! {\n    pub static mut PyDictKeys_Type: PyTypeObject;\n    pub static mut PyDictValues_Type: PyTypeObject;\n    pub static mut PyDictItems_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyDictKeys_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyDictKeys_Type)\n}\n\n#[inline]\npub unsafe fn PyDictValues_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyDictValues_Type)\n}\n\n#[inline]\npub unsafe fn PyDictItems_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyDictItems_Type)\n}\n\n#[inline]\npub unsafe fn PyDictViewSet_Check(op: *mut PyObject) -> c_int {\n    (PyDictKeys_Check(op) != 0 || PyDictItems_Check(op) != 0) as c_int\n}\n\nextern_libpython! {\n    pub static mut PyDictIterKey_Type: PyTypeObject;\n    pub static mut PyDictIterValue_Type: PyTypeObject;\n    pub static mut PyDictIterItem_Type: PyTypeObject;\n    #[cfg(Py_3_8)]\n    pub static mut PyDictRevIterKey_Type: PyTypeObject;\n    #[cfg(Py_3_8)]\n    pub static mut PyDictRevIterValue_Type: PyTypeObject;\n    #[cfg(Py_3_8)]\n    pub static mut PyDictRevIterItem_Type: PyTypeObject;\n}\n\n#[cfg(any(GraalPy, Py_LIMITED_API))]\n// TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985)\nopaque_struct!(pub PyDictObject);\n"
  },
  {
    "path": "pyo3-ffi/src/enumobject.rs",
    "content": "use crate::object::PyTypeObject;\n\nextern_libpython! {\n    pub static mut PyEnum_Type: PyTypeObject;\n    pub static mut PyReversed_Type: PyTypeObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/fileobject.rs",
    "content": "use crate::object::PyObject;\nuse std::ffi::{c_char, c_int};\n\npub const PY_STDIOTEXTMODE: &str = \"b\";\n\nextern_libpython! {\n    pub fn PyFile_FromFd(\n        arg1: c_int,\n        arg2: *const c_char,\n        arg3: *const c_char,\n        arg4: c_int,\n        arg5: *const c_char,\n        arg6: *const c_char,\n        arg7: *const c_char,\n        arg8: c_int,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyFile_GetLine\")]\n    pub fn PyFile_GetLine(arg1: *mut PyObject, arg2: c_int) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyFile_WriteObject\")]\n    pub fn PyFile_WriteObject(arg1: *mut PyObject, arg2: *mut PyObject, arg3: c_int) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyFile_WriteString\")]\n    pub fn PyFile_WriteString(arg1: *const c_char, arg2: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyFile_AsFileDescriptor\")]\n    pub fn PyObject_AsFileDescriptor(arg1: *mut PyObject) -> c_int;\n}\n\nextern_libpython! {\n    #[deprecated(note = \"Python 3.12\")]\n    pub static mut Py_FileSystemDefaultEncoding: *const c_char;\n    #[deprecated(note = \"Python 3.12\")]\n    pub static mut Py_FileSystemDefaultEncodeErrors: *const c_char;\n    #[deprecated(note = \"Python 3.12\")]\n    pub static mut Py_HasFileSystemDefaultEncoding: c_int;\n    // skipped 3.12-deprecated Py_UTF8Mode\n}\n\n// skipped _PyIsSelectable_fd\n"
  },
  {
    "path": "pyo3-ffi/src/fileutils.rs",
    "content": "use crate::pyport::Py_ssize_t;\nuse libc::wchar_t;\nuse std::ffi::c_char;\n\nextern_libpython! {\n    pub fn Py_DecodeLocale(arg1: *const c_char, size: *mut Py_ssize_t) -> *mut wchar_t;\n\n    pub fn Py_EncodeLocale(text: *const wchar_t, error_pos: *mut Py_ssize_t) -> *mut c_char;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/floatobject.rs",
    "content": "use crate::object::*;\nuse std::ffi::{c_double, c_int};\n\n#[cfg(Py_LIMITED_API)]\n// TODO: remove (see https://github.com/PyO3/pyo3/pull/1341#issuecomment-751515985)\nopaque_struct!(pub PyFloatObject);\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyFloat_Type\")]\n    pub static mut PyFloat_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyFloat_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyFloat_Type)\n}\n\n#[inline]\npub unsafe fn PyFloat_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyFloat_Type) as c_int\n}\n\n// skipped Py_RETURN_NAN\n// skipped Py_RETURN_INF\n\nextern_libpython! {\n    pub fn PyFloat_GetMax() -> c_double;\n    pub fn PyFloat_GetMin() -> c_double;\n    pub fn PyFloat_GetInfo() -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyFloat_FromString\")]\n    pub fn PyFloat_FromString(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyFloat_FromDouble\")]\n    pub fn PyFloat_FromDouble(arg1: c_double) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyFloat_AsDouble\")]\n    pub fn PyFloat_AsDouble(arg1: *mut PyObject) -> c_double;\n}\n\n// skipped non-limited _PyFloat_Pack2\n// skipped non-limited _PyFloat_Pack4\n// skipped non-limited _PyFloat_Pack8\n// skipped non-limited _PyFloat_Unpack2\n// skipped non-limited _PyFloat_Unpack4\n// skipped non-limited _PyFloat_Unpack8\n// skipped non-limited _PyFloat_DebugMallocStats\n// skipped non-limited _PyFloat_FormatAdvancedWriter\n"
  },
  {
    "path": "pyo3-ffi/src/genericaliasobject.rs",
    "content": "#[cfg(Py_3_9)]\nuse crate::object::{PyObject, PyTypeObject};\n\nextern_libpython! {\n    #[cfg(Py_3_9)]\n    #[cfg_attr(PyPy, link_name = \"PyPy_GenericAlias\")]\n    pub fn Py_GenericAlias(origin: *mut PyObject, args: *mut PyObject) -> *mut PyObject;\n\n    #[cfg(Py_3_9)]\n    pub static mut Py_GenericAliasType: PyTypeObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/impl_/macros.rs",
    "content": "// On x86 Windows, `raw-dylib` with `import_name_type = \"undecorated\"` removes the\n// leading cdecl underscore from function names. This is expected behavior for\n// `import_name_type = \"undecorated\"` (not a rustc bug): it strips the cdecl `_`\n// prefix, which collides with symbols whose real names start with `_Py`.\n// See https://doc.rust-lang.org/reference/items/external-blocks.html#the-import_name_type-key\n//\n// That matches ordinary `Py_*` exports, but it breaks CPython's internal `_Py*`\n// function exports whose real DLL names already start with an underscore. For\n// those functions, ask rustc for one extra underscore so that x86 undecoration\n// lands back on CPython's export.\n//\n// Variables are intentionally excluded here: `import_name_type` does not affect\n// variable imports, so `_Py_*` statics continue to work without any rewriting.\n#[allow(unused_macros, reason = \"used indirectly by extern_libpython_item!\")]\nmacro_rules! extern_libpython_cpython_private_fn {\n    ($(#[$attrs:meta])* $vis:vis $name:ident($($args:tt)*) $(-> $ret:ty)?) => {\n        #[cfg_attr(\n            all(windows, target_arch = \"x86\", not(any(PyPy, GraalPy))),\n            link_name = concat!(\"_\", stringify!($name))\n        )]\n        $(#[$attrs])*\n        $vis fn $name($($args)*) $(-> $ret)?;\n    };\n}\n\n// Keep this list in sync with `_Py*` function imports declared through\n// `extern_libpython!`. The x86 workaround only needs to apply to functions:\n// statics keep their original names even when `import_name_type` is set. Match\n// by name only here so the function signature stays in a single generic arm.\n//\n// TODO: reduce the number of `_Py*` exports from pyo3-ffi over time — the fewer\n// CPython-private functions we expose, the smaller this workaround list becomes.\n#[allow(unused_macros, reason = \"used indirectly by extern_libpython_item!\")]\nmacro_rules! extern_libpython_maybe_private_fn {\n    (\n        [_PyObject_CallFunction_SizeT]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyObject_CallMethod_SizeT]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyObject_MakeTpCall]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PySequence_IterSearch]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyStack_AsDict]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_Py_CheckFunctionResult]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyBytes_Resize]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyEval_EvalFrameDefault]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyEval_RequestCodeExtraIndex]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyCode_GetExtra]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyCode_SetExtra]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyLong_AsByteArray]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyLong_FromByteArray]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyObject_GC_Calloc]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyObject_GC_Malloc]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_Py_GetAllocatedBlocks]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyRun_AnyFileObject]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyRun_InteractiveLoopObject]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyRun_SimpleFileObject]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyUnicode_CheckConsistency]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyUnicode_Ready]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyLong_NumBits]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyThreadState_UncheckedGet]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyObject_GC_New]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyObject_GC_NewVar]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyObject_GC_Resize]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyObject_New]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyObject_NewVar]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PyErr_BadInternalCall]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_Py_HashBytes]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_Py_DECREF_DecRefTotal]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_Py_Dealloc]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_Py_DecRef]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_Py_INCREF_IncRefTotal]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_Py_IncRef]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_Py_NegativeRefcount]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [_PySet_NextEntry]\n        $(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        extern_libpython_cpython_private_fn! { $(#[$attrs])* $vis $name($($args)*) $(-> $ret)? }\n    };\n    (\n        [$name:ident]\n        $(#[$attrs:meta])* $vis:vis fn $fn_name:ident($($args:tt)*) $(-> $ret:ty)?\n    ) => {\n        $(#[$attrs])*\n        $vis fn $fn_name($($args)*) $(-> $ret)?;\n    };\n}\n\nmacro_rules! extern_libpython_item {\n    ($(#[$attrs:meta])* $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?) => {\n        extern_libpython_maybe_private_fn! {\n            [$name]\n            $(#[$attrs])*\n            $vis fn $name($($args)*) $(-> $ret)?\n        }\n    };\n    ($(#[$attrs:meta])* $vis:vis static mut $name:ident: $ty:ty) => {\n        $(#[$attrs])*\n        $vis static mut $name: $ty;\n    };\n    ($(#[$attrs:meta])* $vis:vis static $name:ident: $ty:ty) => {\n        $(#[$attrs])*\n        $vis static $name: $ty;\n    };\n}\n\nmacro_rules! extern_libpython_items {\n    () => {};\n    (\n        $(#[$attrs:meta])*\n        $vis:vis fn $name:ident($($args:tt)*) $(-> $ret:ty)?;\n        $($rest:tt)*\n    ) => {\n        extern_libpython_item! {\n            $(#[$attrs])*\n            $vis fn $name($($args)*) $(-> $ret)?\n        }\n        extern_libpython_items! { $($rest)* }\n    };\n    (\n        $(#[$attrs:meta])*\n        $vis:vis static mut $name:ident: $ty:ty;\n        $($rest:tt)*\n    ) => {\n        extern_libpython_item! {\n            $(#[$attrs])*\n            $vis static mut $name: $ty\n        }\n        extern_libpython_items! { $($rest)* }\n    };\n    (\n        $(#[$attrs:meta])*\n        $vis:vis static $name:ident: $ty:ty;\n        $($rest:tt)*\n    ) => {\n        extern_libpython_item! {\n            $(#[$attrs])*\n            $vis static $name: $ty\n        }\n        extern_libpython_items! { $($rest)* }\n    };\n}\n\n/// Helper macro to declare `extern` blocks that link against libpython on Windows\n/// using `raw-dylib`, eliminating the need for import libraries.\n///\n/// The build script sets a `pyo3_dll` cfg value to the target DLL name (e.g. `python312`),\n/// and this macro expands to the appropriate `#[link(name = \"...\", kind = \"raw-dylib\")]`\n/// attribute for that DLL.\n///\n/// # Usage\n///\n/// ```rust,ignore\n/// // Default ABI \"C\" (most common):\n/// extern_libpython! {\n///     pub fn PyObject_Call(\n///         callable: *mut PyObject,\n///         args: *mut PyObject,\n///         kwargs: *mut PyObject,\n///     ) -> *mut PyObject;\n/// }\n///\n/// // Explicit ABI:\n/// extern_libpython! { \"C-unwind\" {\n///     pub fn PyGILState_Ensure() -> PyGILState_STATE;\n/// }}\n/// ```\nmacro_rules! extern_libpython {\n    // Explicit ABI\n    ($abi:literal { $($body:tt)* }) => {\n        extern_libpython!(@impl $abi { $($body)* }\n            // abi3\n            \"python3\", \"python3_d\",\n            // Python 3.7 - 3.15\n            \"python37\", \"python37_d\",\n            \"python38\", \"python38_d\",\n            \"python39\", \"python39_d\",\n            \"python310\", \"python310_d\",\n            \"python311\", \"python311_d\",\n            \"python312\", \"python312_d\",\n            \"python313\", \"python313_d\",\n            \"python314\", \"python314_d\",\n            \"python315\", \"python315_d\",\n            // free-threaded builds (3.13+)\n            \"python313t\", \"python313t_d\",\n            \"python314t\", \"python314t_d\",\n            \"python315t\", \"python315t_d\",\n            // PyPy (DLL is libpypy3.X-c.dll, not pythonXY.dll)\n            \"libpypy3.11-c\",\n        );\n    };\n    // Internal: generate cfg_attr for each DLL name. One of these will be selected\n    // by `pyo3-ffi`'s `build.rs`.\n    //\n    // On x86 Windows, Python DLLs export undecorated symbol names (no leading\n    // underscore), but the default for raw-dylib on x86 is fully-decorated\n    // (cdecl adds a `_` prefix). We use `import_name_type = \"undecorated\"` to\n    // match. The `import_name_type` key is only valid on x86, so we need\n    // separate cfg_attr arms per architecture.\n    (@impl $abi:literal { $($body:tt)* } $($dll:literal),* $(,)?) => {\n        $(\n            #[cfg_attr(all(windows, target_arch = \"x86\", pyo3_dll = $dll),\n                link(name = $dll, kind = \"raw-dylib\", import_name_type = \"undecorated\"))]\n            #[cfg_attr(all(windows, not(target_arch = \"x86\"), pyo3_dll = $dll),\n                link(name = $dll, kind = \"raw-dylib\"))]\n        )*\n        extern $abi {\n            extern_libpython_items! { $($body)* }\n        }\n    };\n    // Default ABI: \"C\"\n    ($($body:tt)*) => {\n        extern_libpython!(\"C\" { $($body)* });\n    };\n}\n"
  },
  {
    "path": "pyo3-ffi/src/impl_/mod.rs",
    "content": "#[cfg(Py_GIL_DISABLED)]\nmod atomic_c_ulong {\n    pub struct GetAtomicCULong<const WIDTH: usize>();\n\n    pub trait AtomicCULongType {\n        type Type;\n    }\n    impl AtomicCULongType for GetAtomicCULong<32> {\n        type Type = std::sync::atomic::AtomicU32;\n    }\n    impl AtomicCULongType for GetAtomicCULong<64> {\n        type Type = std::sync::atomic::AtomicU64;\n    }\n\n    pub type TYPE =\n        <GetAtomicCULong<{ std::mem::size_of::<std::ffi::c_ulong>() * 8 }> as AtomicCULongType>::Type;\n}\n\n/// Typedef for an atomic integer to match the platform-dependent c_ulong type.\n#[cfg(Py_GIL_DISABLED)]\n#[doc(hidden)]\npub type AtomicCULong = atomic_c_ulong::TYPE;\n"
  },
  {
    "path": "pyo3-ffi/src/import.rs",
    "content": "use crate::object::PyObject;\nuse std::ffi::{c_char, c_int, c_long};\n\nextern_libpython! {\n    pub fn PyImport_GetMagicNumber() -> c_long;\n    pub fn PyImport_GetMagicTag() -> *const c_char;\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_ExecCodeModule\")]\n    pub fn PyImport_ExecCodeModule(name: *const c_char, co: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_ExecCodeModuleEx\")]\n    pub fn PyImport_ExecCodeModuleEx(\n        name: *const c_char,\n        co: *mut PyObject,\n        pathname: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyImport_ExecCodeModuleWithPathnames(\n        name: *const c_char,\n        co: *mut PyObject,\n        pathname: *const c_char,\n        cpathname: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyImport_ExecCodeModuleObject(\n        name: *mut PyObject,\n        co: *mut PyObject,\n        pathname: *mut PyObject,\n        cpathname: *mut PyObject,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_GetModuleDict\")]\n    pub fn PyImport_GetModuleDict() -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_GetModule\")]\n    pub fn PyImport_GetModule(name: *mut PyObject) -> *mut PyObject;\n    pub fn PyImport_AddModuleObject(name: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_AddModule\")]\n    pub fn PyImport_AddModule(name: *const c_char) -> *mut PyObject;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_AddModuleRef\")]\n    pub fn PyImport_AddModuleRef(name: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_ImportModule\")]\n    pub fn PyImport_ImportModule(name: *const c_char) -> *mut PyObject;\n    #[deprecated(note = \"Python 3.13\")]\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_ImportModuleNoBlock\")]\n    pub fn PyImport_ImportModuleNoBlock(name: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_ImportModuleLevel\")]\n    pub fn PyImport_ImportModuleLevel(\n        name: *const c_char,\n        globals: *mut PyObject,\n        locals: *mut PyObject,\n        fromlist: *mut PyObject,\n        level: c_int,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_ImportModuleLevelObject\")]\n    pub fn PyImport_ImportModuleLevelObject(\n        name: *mut PyObject,\n        globals: *mut PyObject,\n        locals: *mut PyObject,\n        fromlist: *mut PyObject,\n        level: c_int,\n    ) -> *mut PyObject;\n}\n\n#[inline]\npub unsafe fn PyImport_ImportModuleEx(\n    name: *const c_char,\n    globals: *mut PyObject,\n    locals: *mut PyObject,\n    fromlist: *mut PyObject,\n) -> *mut PyObject {\n    PyImport_ImportModuleLevel(name, globals, locals, fromlist, 0)\n}\n\nextern_libpython! {\n    pub fn PyImport_GetImporter(path: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_Import\")]\n    pub fn PyImport_Import(name: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyImport_ReloadModule\")]\n    pub fn PyImport_ReloadModule(m: *mut PyObject) -> *mut PyObject;\n    #[cfg(not(Py_3_9))]\n    #[deprecated(note = \"Removed in Python 3.9 as it was \\\"For internal use only\\\".\")]\n    pub fn PyImport_Cleanup();\n    pub fn PyImport_ImportFrozenModuleObject(name: *mut PyObject) -> c_int;\n    pub fn PyImport_ImportFrozenModule(name: *const c_char) -> c_int;\n\n    pub fn PyImport_AppendInittab(\n        name: *const c_char,\n        initfunc: Option<unsafe extern \"C\" fn() -> *mut PyObject>,\n    ) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/intrcheck.rs",
    "content": "use std::ffi::c_int;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyOS_InterruptOccurred\")]\n    pub fn PyOS_InterruptOccurred() -> c_int;\n    #[cfg(not(Py_3_10))]\n    #[deprecated(note = \"Not documented in Python API; see Python 3.10 release notes\")]\n    pub fn PyOS_InitInterrupts();\n\n    pub fn PyOS_BeforeFork();\n    pub fn PyOS_AfterFork_Parent();\n    pub fn PyOS_AfterFork_Child();\n    #[deprecated(note = \"use PyOS_AfterFork_Child instead\")]\n    #[cfg_attr(PyPy, link_name = \"PyPyOS_AfterFork\")]\n    pub fn PyOS_AfterFork();\n\n    // skipped non-limited _PyOS_IsMainThread\n    // skipped non-limited Windows _PyOS_SigintEvent\n}\n"
  },
  {
    "path": "pyo3-ffi/src/iterobject.rs",
    "content": "use crate::object::*;\nuse std::ffi::c_int;\n\nextern_libpython! {\n    pub static mut PySeqIter_Type: PyTypeObject;\n    pub static mut PyCallIter_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PySeqIter_Check(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PySeqIter_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPySeqIter_New\")]\n    pub fn PySeqIter_New(arg1: *mut PyObject) -> *mut PyObject;\n}\n\n#[inline]\npub unsafe fn PyCallIter_Check(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyCallIter_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyCallIter_New\")]\n    pub fn PyCallIter_New(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/lib.rs",
    "content": "#![cfg_attr(docsrs, feature(doc_cfg))]\n//! Raw FFI declarations for Python's C API.\n//!\n//! PyO3 can be used to write native Python modules or run Python code and modules from Rust.\n//!\n//! This crate just provides low level bindings to the Python interpreter.\n//! It is meant for advanced users only - regular PyO3 users shouldn't\n//! need to interact with this crate at all.\n//!\n//! The contents of this crate are not documented here, as it would entail\n//! basically copying the documentation from CPython. Consult the [Python/C API Reference\n//! Manual][capi] for up-to-date documentation.\n//!\n//! # Safety\n//!\n//! The functions in this crate lack individual safety documentation, but\n//! generally the following apply:\n//! - Pointer arguments have to point to a valid Python object of the correct type,\n//! although null pointers are sometimes valid input.\n//! - The vast majority can only be used safely while the thread is attached to the Python interpreter.\n//! - Some functions have additional safety requirements, consult the\n//! [Python/C API Reference Manual][capi]\n//! for more information.\n//!\n//!\n//! # Feature flags\n//!\n//! PyO3 uses [feature flags] to enable you to opt-in to additional functionality. For a detailed\n//! description, see the [Features chapter of the guide].\n//!\n//! ## Optional feature flags\n//!\n//! The following features customize PyO3's behavior:\n//!\n//! - `abi3`: Restricts PyO3's API to a subset of the full Python API which is guaranteed by\n//! [PEP 384] to be forward-compatible with future Python versions.\n//!\n//! ## `rustc` environment flags\n//!\n//! PyO3 uses `rustc`'s `--cfg` flags to enable or disable code used for different Python versions.\n//! If you want to do this for your own crate, you can do so with the [`pyo3-build-config`] crate.\n//!\n//! - `Py_3_7`, `Py_3_8`, `Py_3_9`, `Py_3_10`, `Py_3_11`, `Py_3_12`, `Py_3_13`: Marks code that is\n//!    only enabled when compiling for a given minimum Python version.\n//! - `Py_LIMITED_API`: Marks code enabled when the `abi3` feature flag is enabled.\n//! - `Py_GIL_DISABLED`: Marks code that runs only in the free-threaded build of CPython.\n//! - `PyPy` - Marks code enabled when compiling for PyPy.\n//! - `GraalPy` - Marks code enabled when compiling for GraalPy.\n//!\n//! Additionally, you can query for the values `Py_DEBUG`, `Py_REF_DEBUG`,\n//! `Py_TRACE_REFS`, and `COUNT_ALLOCS` from `py_sys_config` to query for the\n//! corresponding C build-time defines. For example, to conditionally define\n//! debug code using `Py_DEBUG`, you could do:\n//!\n//! ```rust,ignore\n//! #[cfg(py_sys_config = \"Py_DEBUG\")]\n//! println!(\"only runs if python was compiled with Py_DEBUG\")\n//! ```\n//!\n//! To use these attributes, add [`pyo3-build-config`] as a build dependency in\n//! your `Cargo.toml`:\n//!\n//! ```toml\n//! [build-dependencies]\n#![doc = concat!(\"pyo3-build-config =\\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\"\")]\n//! ```\n//!\n//! And then either create a new `build.rs` file in the project root or modify\n//! the existing `build.rs` file to call `use_pyo3_cfgs()`:\n//!\n//! ```rust,ignore\n//! fn main() {\n//!     pyo3_build_config::use_pyo3_cfgs();\n//! }\n//! ```\n//!\n//! # Minimum supported Rust and Python versions\n//!\n//! `pyo3-ffi` supports the following Python distributions:\n//!   - CPython 3.7 or greater\n//!   - PyPy 7.3 (Python 3.11+)\n//!   - GraalPy 24.0 or greater (Python 3.10+)\n//!\n//! # Example: Building Python Native modules\n//!\n//! PyO3 can be used to generate a native Python module. The easiest way to try this out for the\n//! first time is to use [`maturin`]. `maturin` is a tool for building and publishing Rust-based\n//! Python packages with minimal configuration. The following steps set up some files for an example\n//! Python module, install `maturin`, and then show how to build and import the Python module.\n//!\n//! First, create a new folder (let's call it `string_sum`) containing the following two files:\n//!\n//! **`Cargo.toml`**\n//!\n//! ```toml\n//! [lib]\n//! name = \"string_sum\"\n//! # \"cdylib\" is necessary to produce a shared library for Python to import from.\n//! #\n//! # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able\n//! # to `use string_sum;` unless the \"rlib\" or \"lib\" crate type is also included, e.g.:\n//! # crate-type = [\"cdylib\", \"rlib\"]\n//! crate-type = [\"cdylib\"]\n//!\n//! [dependencies]\n#![doc = concat!(\"pyo3-ffi = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\"\")]\n//!\n//! [build-dependencies]\n//! # This is only necessary if you need to configure your build based on\n//! # the Python version or the compile-time configuration for the interpreter.\n#![doc = concat!(\"pyo3_build_config = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\"\")]\n//! ```\n//!\n//! If you need to use conditional compilation based on Python version or how\n//! Python was compiled, you need to add `pyo3-build-config` as a\n//! `build-dependency` in your `Cargo.toml` as in the example above and either\n//! create a new `build.rs` file or modify an existing one so that\n//! `pyo3_build_config::use_pyo3_cfgs()` gets called at build time:\n//!\n//! **`build.rs`**\n//! ```rust,ignore\n//! fn main() {\n//!     pyo3_build_config::use_pyo3_cfgs()\n//! }\n//! ```\n//!\n//! **`src/lib.rs`**\n//! ```rust,no_run\n//! #[cfg(Py_3_15)]\n//! use std::ffi::c_void;\n//! use std::ffi::{c_char, c_long};\n//! use std::ptr;\n//!\n//! use pyo3_ffi::*;\n//!\n//! #[cfg(not(Py_3_15))]\n//! static mut MODULE_DEF: PyModuleDef = PyModuleDef {\n//!     m_base: PyModuleDef_HEAD_INIT,\n//!     m_name: c\"string_sum\".as_ptr(),\n//!     m_doc: c\"A Python module written in Rust.\".as_ptr(),\n//!     m_size: 0,\n//!     m_methods: (&raw mut METHODS).cast(),\n//!     m_slots: (&raw mut SLOTS).cast(),\n//!     m_traverse: None,\n//!     m_clear: None,\n//!     m_free: None,\n//! };\n//!\n//! static mut METHODS: [PyMethodDef; 2] = [\n//!     PyMethodDef {\n//!         ml_name: c\"sum_as_string\".as_ptr(),\n//!         ml_meth: PyMethodDefPointer {\n//!             PyCFunctionFast: sum_as_string,\n//!         },\n//!         ml_flags: METH_FASTCALL,\n//!         ml_doc: c\"returns the sum of two integers as a string\".as_ptr(),\n//!     },\n//!     // A zeroed PyMethodDef to mark the end of the array.\n//!     PyMethodDef::zeroed(),\n//! ];\n//!\n//! #[cfg(Py_3_15)]\n//! PyABIInfo_VAR!(ABI_INFO);\n//!\n//! const SLOTS_LEN: usize =\n//!     1 + cfg!(Py_3_12) as usize + cfg!(Py_GIL_DISABLED) as usize + 4 * (cfg!(Py_3_15) as usize);\n//! static mut SLOTS: [PyModuleDef_Slot; SLOTS_LEN] = [\n//!     #[cfg(Py_3_15)]\n//!     PyModuleDef_Slot {\n//!         slot: Py_mod_abi,\n//!         value: (&raw mut ABI_INFO).cast(),\n//!     },\n//!     #[cfg(Py_3_15)]\n//!     PyModuleDef_Slot {\n//!         slot: Py_mod_name,\n//!         // safety: Python does not write to this field\n//!         value: c\"string_sum\".as_ptr() as *mut c_void,\n//!     },\n//!     #[cfg(Py_3_15)]\n//!     PyModuleDef_Slot {\n//!         slot: Py_mod_doc,\n//!         // safety: Python does not write to this field\n//!         value: c\"A Python module written in Rust.\".as_ptr() as *mut c_void,\n//!     },\n//!     #[cfg(Py_3_15)]\n//!     PyModuleDef_Slot {\n//!         slot: Py_mod_methods,\n//!         value: (&raw mut METHODS).cast(),\n//!     },\n//!     #[cfg(Py_3_12)]\n//!     PyModuleDef_Slot {\n//!         slot: Py_mod_multiple_interpreters,\n//!         value: Py_MOD_PER_INTERPRETER_GIL_SUPPORTED,\n//!     },\n//!     #[cfg(Py_GIL_DISABLED)]\n//!     PyModuleDef_Slot {\n//!         slot: Py_mod_gil,\n//!         value: Py_MOD_GIL_NOT_USED,\n//!     },\n//!     PyModuleDef_Slot {\n//!         slot: 0,\n//!         value: ptr::null_mut(),\n//!     },\n//! ];\n//!\n//! // The module initialization function\n//! #[cfg(not(Py_3_15))]\n//! #[allow(non_snake_case, reason = \"must be named `PyInit_<your_module>`\")]\n//! #[no_mangle]\n//! pub unsafe extern \"C\" fn PyInit_string_sum() -> *mut PyObject {\n//!     PyModuleDef_Init(&raw mut MODULE_DEF)\n//! }\n//!\n//! #[cfg(Py_3_15)]\n//! #[allow(non_snake_case, reason = \"must be named `PyModExport_<your_module>`\")]\n//! #[no_mangle]\n//! pub unsafe extern \"C\" fn PyModExport_string_sum() -> *mut PyModuleDef_Slot {\n//!     (&raw mut SLOTS).cast()\n//! }\n//!\n//! /// A helper to parse function arguments\n//! /// If we used PyO3's proc macros they'd handle all of this boilerplate for us :)\n//! unsafe fn parse_arg_as_i32(obj: *mut PyObject, n_arg: usize) -> Option<i32> {\n//!     if PyLong_Check(obj) == 0 {\n//!         let msg = format!(\n//!             \"sum_as_string expected an int for positional argument {}\\0\",\n//!             n_arg\n//!         );\n//!         PyErr_SetString(PyExc_TypeError, msg.as_ptr().cast::<c_char>());\n//!         return None;\n//!     }\n//!\n//!     // Let's keep the behaviour consistent on platforms where `c_long` is bigger than 32 bits.\n//!     // In particular, it is an i32 on Windows but i64 on most Linux systems\n//!     let mut overflow = 0;\n//!     let i_long: c_long = PyLong_AsLongAndOverflow(obj, &mut overflow);\n//!\n//!     #[allow(\n//!         irrefutable_let_patterns,\n//!         reason = \"some platforms have c_long equal to i32\"\n//!     )]\n//!     if overflow != 0 {\n//!         raise_overflowerror(obj);\n//!         None\n//!     } else if let Ok(i) = i_long.try_into() {\n//!         Some(i)\n//!     } else {\n//!         raise_overflowerror(obj);\n//!         None\n//!     }\n//! }\n//!\n//! unsafe fn raise_overflowerror(obj: *mut PyObject) {\n//!     let obj_repr = PyObject_Str(obj);\n//!     if !obj_repr.is_null() {\n//!         let mut size = 0;\n//!         let p = PyUnicode_AsUTF8AndSize(obj_repr, &mut size);\n//!         if !p.is_null() {\n//!             let s = std::str::from_utf8_unchecked(std::slice::from_raw_parts(\n//!                 p.cast::<u8>(),\n//!                 size as usize,\n//!             ));\n//!             let msg = format!(\"cannot fit {} in 32 bits\\0\", s);\n//!\n//!             PyErr_SetString(PyExc_OverflowError, msg.as_ptr().cast::<c_char>());\n//!         }\n//!         Py_DECREF(obj_repr);\n//!     }\n//! }\n//!\n//! pub unsafe extern \"C\" fn sum_as_string(\n//!     _self: *mut PyObject,\n//!     args: *mut *mut PyObject,\n//!     nargs: Py_ssize_t,\n//! ) -> *mut PyObject {\n//!     if nargs != 2 {\n//!         PyErr_SetString(\n//!             PyExc_TypeError,\n//!             c\"sum_as_string expected 2 positional arguments\".as_ptr(),\n//!         );\n//!         return std::ptr::null_mut();\n//!     }\n//!\n//!     let (first, second) = (*args, *args.add(1));\n//!\n//!     let first = match parse_arg_as_i32(first, 1) {\n//!         Some(x) => x,\n//!         None => return std::ptr::null_mut(),\n//!     };\n//!     let second = match parse_arg_as_i32(second, 2) {\n//!         Some(x) => x,\n//!         None => return std::ptr::null_mut(),\n//!     };\n//!\n//!     match first.checked_add(second) {\n//!         Some(sum) => {\n//!             let string = sum.to_string();\n//!             PyUnicode_FromStringAndSize(string.as_ptr().cast::<c_char>(), string.len() as isize)\n//!         }\n//!         None => {\n//!             PyErr_SetString(PyExc_OverflowError, c\"arguments too large to add\".as_ptr());\n//!             std::ptr::null_mut()\n//!         }\n//!     }\n//! }\n//! ```\n//!\n//! With those two files in place, now `maturin` needs to be installed. This can be done using\n//! Python's package manager `pip`. First, load up a new Python `virtualenv`, and install `maturin`\n//! into it:\n//! ```bash\n//! $ cd string_sum\n//! $ python -m venv .env\n//! $ source .env/bin/activate\n//! $ pip install maturin\n//! ```\n//!\n//! Now build and execute the module:\n//! ```bash\n//! $ maturin develop\n//! # lots of progress output as maturin runs the compilation...\n//! $ python\n//! >>> import string_sum\n//! >>> string_sum.sum_as_string(5, 20)\n//! '25'\n//! ```\n//!\n//! As well as with `maturin`, it is possible to build using [setuptools-rust] or\n//! [manually][manual_builds]. Both offer more flexibility than `maturin` but require further\n//! configuration.\n//!\n//! This example stores the module definition statically and uses the `PyModule_Create` function\n//! in the CPython C API to register the module. This is the \"old\" style for registering modules\n//! and has the limitation that it cannot support subinterpreters. You can also create a module\n//! using the new multi-phase initialization API that does support subinterpreters. See the\n//! `sequential` project located in the `examples` directory at the root of the `pyo3-ffi` crate\n//! for a worked example of how to this using `pyo3-ffi`.\n//!\n//! # Using Python from Rust\n//!\n//! To embed Python into a Rust binary, you need to ensure that your Python installation contains a\n//! shared library. The following steps demonstrate how to ensure this (for Ubuntu).\n//!\n//! To install the Python shared library on Ubuntu:\n//! ```bash\n//! sudo apt install python3-dev\n//! ```\n//!\n//! While most projects use the safe wrapper provided by pyo3,\n//! you can take a look at the [`orjson`] library as an example on how to use `pyo3-ffi` directly.\n//! For those well versed in C and Rust the [tutorials] from the CPython documentation\n//! can be easily converted to rust as well.\n//!\n//! [tutorials]: https://docs.python.org/3/extending/\n//! [`orjson`]: https://github.com/ijl/orjson\n//! [capi]: https://docs.python.org/3/c-api/index.html\n//! [`maturin`]: https://github.com/PyO3/maturin \"Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages\"\n//! [`pyo3-build-config`]: https://docs.rs/pyo3-build-config\n//! [feature flags]: https://doc.rust-lang.org/cargo/reference/features.html \"Features - The Cargo Book\"\n#![doc = concat!(\"[manual_builds]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/building-and-distribution.html#manual-builds \\\"Manual builds - Building and Distribution - PyO3 user guide\\\"\")]\n//! [setuptools-rust]: https://github.com/PyO3/setuptools-rust \"Setuptools plugin for Rust extensions\"\n//! [PEP 384]: https://www.python.org/dev/peps/pep-0384 \"PEP 384 -- Defining a Stable ABI\"\n#![doc = concat!(\"[Features chapter of the guide]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/features.html#features-reference \\\"Features reference - PyO3 user guide\\\"\")]\n#![allow(\n    missing_docs,\n    non_camel_case_types,\n    non_snake_case,\n    non_upper_case_globals,\n    clippy::upper_case_acronyms,\n    clippy::missing_safety_doc,\n    clippy::ptr_eq\n)]\n#![warn(elided_lifetimes_in_paths, unused_lifetimes)]\n// This crate is a hand-maintained translation of CPython's headers, so requiring \"unsafe\"\n// blocks within those translations increases maintenance burden without providing any\n// additional safety. The safety of the functions in this crate is determined by the\n// original CPython headers\n#![allow(unsafe_op_in_unsafe_fn)]\n\n// Until `extern type` is stabilized, use the recommended approach to\n// model opaque types:\n// https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs\nmacro_rules! opaque_struct {\n    ($(#[$attrs:meta])* $pub:vis $name:ident) => {\n        $(#[$attrs])*\n        #[repr(C)]\n        $pub struct $name([u8; 0]);\n    };\n}\n\n/// This is a helper macro to create a `&'static CStr`.\n///\n/// It can be used on all Rust versions supported by PyO3, unlike c\"\" literals which\n/// were stabilised in Rust 1.77.\n///\n/// Due to the nature of PyO3 making heavy use of C FFI interop with Python, it is\n/// common for PyO3 to use CStr.\n///\n/// Examples:\n///\n/// ```rust,no_run\n/// use std::ffi::CStr;\n///\n/// const HELLO: &CStr = pyo3_ffi::c_str!(\"hello\");\n/// static WORLD: &CStr = pyo3_ffi::c_str!(\"world\");\n/// ```\n#[macro_export]\nmacro_rules! c_str {\n    // TODO: deprecate this now MSRV is above 1.77\n    ($s:expr) => {\n        $crate::_cstr_from_utf8_with_nul_checked(concat!($s, \"\\0\"))\n    };\n}\n\n/// Private helper for `c_str!` macro.\n#[doc(hidden)]\npub const fn _cstr_from_utf8_with_nul_checked(s: &str) -> &std::ffi::CStr {\n    match std::ffi::CStr::from_bytes_with_nul(s.as_bytes()) {\n        Ok(cstr) => cstr,\n        Err(_) => panic!(\"string contains nul bytes\"),\n    }\n}\n\n// Macros for declaring `extern` blocks that link against libpython.\n// See `impl_/macros.rs` for the implementation.\ninclude!(\"impl_/macros.rs\");\n\npub mod compat;\nmod impl_;\n\npub use self::abstract_::*;\npub use self::bltinmodule::*;\npub use self::boolobject::*;\npub use self::bytearrayobject::*;\npub use self::bytesobject::*;\npub use self::ceval::*;\npub use self::codecs::*;\npub use self::compile::*;\npub use self::complexobject::*;\n#[cfg(all(Py_3_8, not(Py_LIMITED_API)))]\npub use self::context::*;\n#[cfg(not(Py_LIMITED_API))]\npub use self::datetime::*;\npub use self::descrobject::*;\npub use self::dictobject::*;\npub use self::enumobject::*;\npub use self::fileobject::*;\npub use self::fileutils::*;\npub use self::floatobject::*;\n#[cfg(Py_3_9)]\npub use self::genericaliasobject::*;\npub use self::import::*;\npub use self::intrcheck::*;\npub use self::iterobject::*;\npub use self::listobject::*;\npub use self::longobject::*;\n#[cfg(not(Py_LIMITED_API))]\npub use self::marshal::*;\npub use self::memoryobject::*;\npub use self::methodobject::*;\npub use self::modsupport::*;\npub use self::moduleobject::*;\npub use self::object::*;\npub use self::objimpl::*;\npub use self::osmodule::*;\n#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))]\npub use self::pyarena::*;\n#[cfg(Py_3_11)]\npub use self::pybuffer::*;\npub use self::pycapsule::*;\npub use self::pyerrors::*;\npub use self::pyframe::*;\npub use self::pyhash::*;\npub use self::pylifecycle::*;\npub use self::pymem::*;\npub use self::pyport::*;\npub use self::pystate::*;\npub use self::pystrtod::*;\npub use self::pythonrun::*;\npub use self::pytypedefs::*;\npub use self::rangeobject::*;\npub use self::refcount::*;\npub use self::setobject::*;\npub use self::sliceobject::*;\npub use self::structseq::*;\npub use self::sysmodule::*;\npub use self::traceback::*;\npub use self::tupleobject::*;\npub use self::typeslots::*;\npub use self::unicodeobject::*;\npub use self::warnings::*;\npub use self::weakrefobject::*;\n\nmod abstract_;\n// skipped asdl.h\n// skipped ast.h\nmod bltinmodule;\nmod boolobject;\nmod bytearrayobject;\nmod bytesobject;\n// skipped cellobject.h\nmod ceval;\n// skipped classobject.h\nmod codecs;\nmod compile;\nmod complexobject;\n#[cfg(all(Py_3_8, not(Py_LIMITED_API)))]\nmod context; // It's actually 3.7.1, but no cfg for patches.\n#[cfg(not(Py_LIMITED_API))]\npub(crate) mod datetime;\nmod descrobject;\nmod dictobject;\n// skipped dynamic_annotations.h\nmod enumobject;\n// skipped errcode.h\n// skipped exports.h\nmod fileobject;\nmod fileutils;\nmod floatobject;\n// skipped empty frameobject.h\nmod genericaliasobject;\nmod import;\n// skipped interpreteridobject.h\nmod intrcheck;\nmod iterobject;\nmod listobject;\n// skipped longintrepr.h\nmod longobject;\n#[cfg(not(Py_LIMITED_API))]\npub mod marshal;\nmod memoryobject;\nmod methodobject;\nmod modsupport;\nmod moduleobject;\n// skipped namespaceobject.h\nmod object;\nmod objimpl;\n// skipped odictobject.h\n// skipped opcode.h\n// skipped osdefs.h\nmod osmodule;\n// skipped parser_interface.h\n// skipped patchlevel.h\n// skipped picklebufobject.h\n// skipped pyctype.h\n// skipped py_curses.h\n#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))]\nmod pyarena;\n#[cfg(Py_3_11)]\nmod pybuffer;\nmod pycapsule;\n// skipped pydtrace.h\nmod pyerrors;\n// skipped pyexpat.h\n// skipped pyfpe.h\nmod pyframe;\nmod pyhash;\nmod pylifecycle;\n// skipped pymacconfig.h\n// skipped pymacro.h\n// skipped pymath.h\nmod pymem;\nmod pyport;\nmod pystate;\n// skipped pystats.h\nmod pythonrun;\n// skipped pystrhex.h\n// skipped pystrcmp.h\nmod pystrtod;\n// skipped pythread.h\n// skipped pytime.h\nmod pytypedefs;\nmod rangeobject;\nmod refcount;\nmod setobject;\nmod sliceobject;\nmod structseq;\nmod sysmodule;\nmod traceback;\n// skipped tracemalloc.h\nmod tupleobject;\nmod typeslots;\nmod unicodeobject;\nmod warnings;\nmod weakrefobject;\n\n// Additional headers that are not exported by Python.h\n#[deprecated(note = \"Python 3.12\")]\npub mod structmember;\n\n// \"Limited API\" definitions matching Python's `include/cpython` directory.\n#[cfg(not(Py_LIMITED_API))]\nmod cpython;\n\n#[cfg(not(Py_LIMITED_API))]\npub use self::cpython::*;\n"
  },
  {
    "path": "pyo3-ffi/src/listobject.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::c_int;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyList_Type\")]\n    pub static mut PyList_Type: PyTypeObject;\n    pub static mut PyListIter_Type: PyTypeObject;\n    pub static mut PyListRevIter_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyList_Check(op: *mut PyObject) -> c_int {\n    PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LIST_SUBCLASS)\n}\n\n#[inline]\npub unsafe fn PyList_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyList_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyList_New\")]\n    pub fn PyList_New(size: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyList_Size\")]\n    pub fn PyList_Size(arg1: *mut PyObject) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyList_GetItem\")]\n    pub fn PyList_GetItem(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyList_GetItemRef\")]\n    pub fn PyList_GetItemRef(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyList_SetItem\")]\n    pub fn PyList_SetItem(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyList_Insert\")]\n    pub fn PyList_Insert(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyList_Append\")]\n    pub fn PyList_Append(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyList_GetSlice\")]\n    pub fn PyList_GetSlice(\n        arg1: *mut PyObject,\n        arg2: Py_ssize_t,\n        arg3: Py_ssize_t,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyList_SetSlice\")]\n    pub fn PyList_SetSlice(\n        arg1: *mut PyObject,\n        arg2: Py_ssize_t,\n        arg3: Py_ssize_t,\n        arg4: *mut PyObject,\n    ) -> c_int;\n    #[cfg(Py_3_13)]\n    pub fn PyList_Extend(list: *mut PyObject, iterable: *mut PyObject) -> c_int;\n    #[cfg(Py_3_13)]\n    pub fn PyList_Clear(list: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyList_Sort\")]\n    pub fn PyList_Sort(arg1: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyList_Reverse\")]\n    pub fn PyList_Reverse(arg1: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyList_AsTuple\")]\n    pub fn PyList_AsTuple(arg1: *mut PyObject) -> *mut PyObject;\n\n    // CPython macros exported as functions on PyPy or GraalPy\n    #[cfg(any(PyPy, GraalPy))]\n    #[cfg_attr(PyPy, link_name = \"PyPyList_GET_ITEM\")]\n    #[cfg_attr(GraalPy, link_name = \"PyList_GetItem\")]\n    pub fn PyList_GET_ITEM(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject;\n    #[cfg(PyPy)]\n    #[cfg_attr(PyPy, link_name = \"PyPyList_GET_SIZE\")]\n    pub fn PyList_GET_SIZE(arg1: *mut PyObject) -> Py_ssize_t;\n    #[cfg(any(PyPy, GraalPy))]\n    #[cfg_attr(PyPy, link_name = \"PyPyList_SET_ITEM\")]\n    #[cfg_attr(GraalPy, link_name = \"_PyList_SET_ITEM\")]\n    pub fn PyList_SET_ITEM(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject);\n}\n"
  },
  {
    "path": "pyo3-ffi/src/longobject.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\nuse libc::size_t;\nuse std::ffi::{c_char, c_double, c_int, c_long, c_longlong, c_ulong, c_ulonglong, c_void};\n\nopaque_struct!(pub PyLongObject);\n\n#[inline]\npub unsafe fn PyLong_Check(op: *mut PyObject) -> c_int {\n    PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LONG_SUBCLASS)\n}\n\n#[inline]\npub unsafe fn PyLong_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyLong_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_FromLong\")]\n    pub fn PyLong_FromLong(arg1: c_long) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_FromUnsignedLong\")]\n    pub fn PyLong_FromUnsignedLong(arg1: c_ulong) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_FromSize_t\")]\n    pub fn PyLong_FromSize_t(arg1: size_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_FromSsize_t\")]\n    pub fn PyLong_FromSsize_t(arg1: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_FromDouble\")]\n    pub fn PyLong_FromDouble(arg1: c_double) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsLong\")]\n    pub fn PyLong_AsLong(arg1: *mut PyObject) -> c_long;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsLongAndOverflow\")]\n    pub fn PyLong_AsLongAndOverflow(arg1: *mut PyObject, arg2: *mut c_int) -> c_long;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsSsize_t\")]\n    pub fn PyLong_AsSsize_t(arg1: *mut PyObject) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsSize_t\")]\n    pub fn PyLong_AsSize_t(arg1: *mut PyObject) -> size_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsUnsignedLong\")]\n    pub fn PyLong_AsUnsignedLong(arg1: *mut PyObject) -> c_ulong;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsUnsignedLongMask\")]\n    pub fn PyLong_AsUnsignedLongMask(arg1: *mut PyObject) -> c_ulong;\n    // skipped non-limited _PyLong_AsInt\n    pub fn PyLong_GetInfo() -> *mut PyObject;\n    // skipped PyLong_AS_LONG\n\n    // skipped PyLong_FromPid\n    // skipped PyLong_AsPid\n    // skipped _Py_PARSE_INTPTR\n    // skipped _Py_PARSE_UINTPTR\n\n    // skipped non-limited _PyLong_UnsignedShort_Converter\n    // skipped non-limited _PyLong_UnsignedInt_Converter\n    // skipped non-limited _PyLong_UnsignedLong_Converter\n    // skipped non-limited _PyLong_UnsignedLongLong_Converter\n    // skipped non-limited _PyLong_Size_t_Converter\n\n    // skipped non-limited _PyLong_DigitValue\n    // skipped non-limited _PyLong_Frexp\n\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsDouble\")]\n    pub fn PyLong_AsDouble(arg1: *mut PyObject) -> c_double;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_FromVoidPtr\")]\n    pub fn PyLong_FromVoidPtr(arg1: *mut c_void) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsVoidPtr\")]\n    pub fn PyLong_AsVoidPtr(arg1: *mut PyObject) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_FromLongLong\")]\n    pub fn PyLong_FromLongLong(arg1: c_longlong) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_FromUnsignedLongLong\")]\n    pub fn PyLong_FromUnsignedLongLong(arg1: c_ulonglong) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsLongLong\")]\n    pub fn PyLong_AsLongLong(arg1: *mut PyObject) -> c_longlong;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsUnsignedLongLong\")]\n    pub fn PyLong_AsUnsignedLongLong(arg1: *mut PyObject) -> c_ulonglong;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsUnsignedLongLongMask\")]\n    pub fn PyLong_AsUnsignedLongLongMask(arg1: *mut PyObject) -> c_ulonglong;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_AsLongLongAndOverflow\")]\n    pub fn PyLong_AsLongLongAndOverflow(arg1: *mut PyObject, arg2: *mut c_int) -> c_longlong;\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_FromString\")]\n    pub fn PyLong_FromString(\n        arg1: *const c_char,\n        arg2: *mut *mut c_char,\n        arg3: c_int,\n    ) -> *mut PyObject;\n}\n\n#[cfg(not(Py_LIMITED_API))]\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"_PyPyLong_NumBits\")]\n    pub fn _PyLong_NumBits(obj: *mut PyObject) -> size_t;\n}\n\n// skipped non-limited _PyLong_Format\n// skipped non-limited _PyLong_FormatWriter\n// skipped non-limited _PyLong_FormatBytesWriter\n// skipped non-limited _PyLong_FormatAdvancedWriter\n\nextern_libpython! {\n    pub fn PyOS_strtoul(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_ulong;\n    pub fn PyOS_strtol(arg1: *const c_char, arg2: *mut *mut c_char, arg3: c_int) -> c_long;\n}\n\n// skipped non-limited _PyLong_Rshift\n// skipped non-limited _PyLong_Lshift\n"
  },
  {
    "path": "pyo3-ffi/src/marshal.rs",
    "content": "use super::{PyObject, Py_ssize_t};\nuse std::ffi::{c_char, c_int};\n\n// skipped Py_MARSHAL_VERSION\n// skipped PyMarshal_WriteLongToFile\n// skipped PyMarshal_WriteObjectToFile\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyMarshal_WriteObjectToString\")]\n    pub fn PyMarshal_WriteObjectToString(object: *mut PyObject, version: c_int) -> *mut PyObject;\n\n    // skipped non-limited PyMarshal_ReadLongFromFile\n    // skipped non-limited PyMarshal_ReadShortFromFile\n    // skipped non-limited PyMarshal_ReadObjectFromFile\n    // skipped non-limited PyMarshal_ReadLastObjectFromFile\n\n    #[cfg_attr(PyPy, link_name = \"PyPyMarshal_ReadObjectFromString\")]\n    pub fn PyMarshal_ReadObjectFromString(data: *const c_char, len: Py_ssize_t) -> *mut PyObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/memoryobject.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::{c_char, c_int};\n\n// skipped _PyManagedBuffer_Type\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyMemoryView_Type\")]\n    pub static mut PyMemoryView_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyMemoryView_Check(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyMemoryView_Type) as c_int\n}\n\n// skipped non-limited PyMemoryView_GET_BUFFER\n// skipped non-limited PyMemoryView_GET_BASE\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyMemoryView_FromObject\")]\n    pub fn PyMemoryView_FromObject(base: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyMemoryView_FromMemory\")]\n    pub fn PyMemoryView_FromMemory(\n        mem: *mut c_char,\n        size: Py_ssize_t,\n        flags: c_int,\n    ) -> *mut PyObject;\n    #[cfg(any(Py_3_11, not(Py_LIMITED_API)))]\n    #[cfg_attr(PyPy, link_name = \"PyPyMemoryView_FromBuffer\")]\n    pub fn PyMemoryView_FromBuffer(view: *const crate::Py_buffer) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyMemoryView_GetContiguous\")]\n    pub fn PyMemoryView_GetContiguous(\n        base: *mut PyObject,\n        buffertype: c_int,\n        order: c_char,\n    ) -> *mut PyObject;\n}\n\n// skipped remainder of file with comment:\n/* The structs are declared here so that macros can work, but they shouldn't\nbe considered public. Don't access their fields directly, use the macros\nand functions instead! */\n"
  },
  {
    "path": "pyo3-ffi/src/methodobject.rs",
    "content": "use crate::object::{PyObject, PyTypeObject, Py_TYPE};\n#[cfg(Py_3_9)]\nuse crate::PyObject_TypeCheck;\nuse std::ffi::{c_char, c_int, c_void};\nuse std::{mem, ptr};\n\n#[cfg(all(Py_3_9, not(Py_LIMITED_API), not(GraalPy)))]\npub struct PyCFunctionObject {\n    pub ob_base: PyObject,\n    pub m_ml: *mut PyMethodDef,\n    pub m_self: *mut PyObject,\n    pub m_module: *mut PyObject,\n    pub m_weakreflist: *mut PyObject,\n    #[cfg(not(PyPy))]\n    pub vectorcall: Option<crate::vectorcallfunc>,\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyCFunction_Type\")]\n    pub static mut PyCFunction_Type: PyTypeObject;\n}\n\n#[cfg(Py_3_9)]\n#[inline]\npub unsafe fn PyCFunction_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyCFunction_Type) as c_int\n}\n\n#[cfg(Py_3_9)]\n#[inline]\npub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyCFunction_Type)\n}\n\n#[cfg(not(Py_3_9))]\n#[inline]\npub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyCFunction_Type) as c_int\n}\n\npub type PyCFunction =\n    unsafe extern \"C\" fn(slf: *mut PyObject, args: *mut PyObject) -> *mut PyObject;\n\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\npub type PyCFunctionFast = unsafe extern \"C\" fn(\n    slf: *mut PyObject,\n    args: *mut *mut PyObject,\n    nargs: crate::pyport::Py_ssize_t,\n) -> *mut PyObject;\n\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n#[deprecated(note = \"renamed to `PyCFunctionFast`\")]\npub type _PyCFunctionFast = PyCFunctionFast;\n\npub type PyCFunctionWithKeywords = unsafe extern \"C\" fn(\n    slf: *mut PyObject,\n    args: *mut PyObject,\n    kwds: *mut PyObject,\n) -> *mut PyObject;\n\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\npub type PyCFunctionFastWithKeywords = unsafe extern \"C\" fn(\n    slf: *mut PyObject,\n    args: *const *mut PyObject,\n    nargs: crate::pyport::Py_ssize_t,\n    kwnames: *mut PyObject,\n) -> *mut PyObject;\n\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n#[deprecated(note = \"renamed to `PyCFunctionFastWithKeywords`\")]\npub type _PyCFunctionFastWithKeywords = PyCFunctionFastWithKeywords;\n\n#[cfg(all(Py_3_9, not(Py_LIMITED_API)))]\npub type PyCMethod = unsafe extern \"C\" fn(\n    slf: *mut PyObject,\n    defining_class: *mut PyTypeObject,\n    args: *const *mut PyObject,\n    nargs: crate::pyport::Py_ssize_t,\n    kwnames: *mut PyObject,\n) -> *mut PyObject;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyCFunction_GetFunction\")]\n    pub fn PyCFunction_GetFunction(f: *mut PyObject) -> Option<PyCFunction>;\n    pub fn PyCFunction_GetSelf(f: *mut PyObject) -> *mut PyObject;\n    pub fn PyCFunction_GetFlags(f: *mut PyObject) -> c_int;\n    #[cfg(not(Py_3_13))]\n    #[cfg_attr(Py_3_9, deprecated(note = \"Python 3.9\"))]\n    pub fn PyCFunction_Call(\n        f: *mut PyObject,\n        args: *mut PyObject,\n        kwds: *mut PyObject,\n    ) -> *mut PyObject;\n}\n\n/// Represents the [PyMethodDef](https://docs.python.org/3/c-api/structures.html#c.PyMethodDef)\n/// structure.\n///\n/// Note that CPython may leave fields uninitialized. You must ensure that\n/// `ml_name` != NULL before dereferencing or reading other fields.\n#[repr(C)]\n#[derive(Copy, Clone, PartialEq, Eq)]\npub struct PyMethodDef {\n    pub ml_name: *const c_char,\n    pub ml_meth: PyMethodDefPointer,\n    pub ml_flags: c_int,\n    pub ml_doc: *const c_char,\n}\n\nimpl PyMethodDef {\n    pub const fn zeroed() -> PyMethodDef {\n        PyMethodDef {\n            ml_name: ptr::null(),\n            ml_meth: PyMethodDefPointer {\n                Void: ptr::null_mut(),\n            },\n            ml_flags: 0,\n            ml_doc: ptr::null(),\n        }\n    }\n}\n\nimpl Default for PyMethodDef {\n    fn default() -> PyMethodDef {\n        PyMethodDef {\n            ml_name: ptr::null(),\n            ml_meth: PyMethodDefPointer {\n                Void: ptr::null_mut(),\n            },\n            ml_flags: 0,\n            ml_doc: ptr::null(),\n        }\n    }\n}\n\n/// Function types used to implement Python callables.\n///\n/// This function pointer must be accompanied by the correct [ml_flags](PyMethodDef::ml_flags),\n/// otherwise the behavior is undefined.\n///\n/// See the [Python C API documentation][1] for more information.\n///\n/// [1]: https://docs.python.org/3/c-api/structures.html#implementing-functions-and-methods\n#[repr(C)]\n#[derive(Copy, Clone, Eq)]\npub union PyMethodDefPointer {\n    /// This variant corresponds with [`METH_VARARGS`] *or* [`METH_NOARGS`] *or* [`METH_O`].\n    pub PyCFunction: PyCFunction,\n\n    /// This variant corresponds with [`METH_VARARGS`] | [`METH_KEYWORDS`].\n    pub PyCFunctionWithKeywords: PyCFunctionWithKeywords,\n\n    /// This variant corresponds with [`METH_FASTCALL`].\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    #[deprecated(note = \"renamed to `PyCFunctionFast`\")]\n    pub _PyCFunctionFast: PyCFunctionFast,\n\n    /// This variant corresponds with [`METH_FASTCALL`].\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    pub PyCFunctionFast: PyCFunctionFast,\n\n    /// This variant corresponds with [`METH_FASTCALL`] | [`METH_KEYWORDS`].\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    #[deprecated(note = \"renamed to `PyCFunctionFastWithKeywords`\")]\n    pub _PyCFunctionFastWithKeywords: PyCFunctionFastWithKeywords,\n\n    /// This variant corresponds with [`METH_FASTCALL`] | [`METH_KEYWORDS`].\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    pub PyCFunctionFastWithKeywords: PyCFunctionFastWithKeywords,\n\n    /// This variant corresponds with [`METH_METHOD`] | [`METH_FASTCALL`] | [`METH_KEYWORDS`].\n    #[cfg(all(Py_3_9, not(Py_LIMITED_API)))]\n    pub PyCMethod: PyCMethod,\n\n    Void: *mut c_void,\n}\n\nimpl PyMethodDefPointer {\n    pub fn as_ptr(&self) -> *mut c_void {\n        unsafe { self.Void }\n    }\n\n    pub fn is_null(&self) -> bool {\n        self.as_ptr().is_null()\n    }\n\n    pub const fn zeroed() -> PyMethodDefPointer {\n        PyMethodDefPointer {\n            Void: ptr::null_mut(),\n        }\n    }\n}\n\nimpl PartialEq for PyMethodDefPointer {\n    fn eq(&self, other: &Self) -> bool {\n        unsafe { self.Void == other.Void }\n    }\n}\n\nimpl std::fmt::Pointer for PyMethodDefPointer {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let ptr = unsafe { self.Void };\n        std::fmt::Pointer::fmt(&ptr, f)\n    }\n}\n\nconst _: () =\n    assert!(mem::size_of::<PyMethodDefPointer>() == mem::size_of::<Option<extern \"C\" fn()>>());\n\n#[cfg(not(Py_3_9))]\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyCFunction_New\")]\n    pub fn PyCFunction_New(ml: *mut PyMethodDef, slf: *mut PyObject) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyCFunction_NewEx\")]\n    pub fn PyCFunction_NewEx(\n        ml: *mut PyMethodDef,\n        slf: *mut PyObject,\n        module: *mut PyObject,\n    ) -> *mut PyObject;\n}\n\n#[cfg(Py_3_9)]\n#[inline]\npub unsafe fn PyCFunction_New(ml: *mut PyMethodDef, slf: *mut PyObject) -> *mut PyObject {\n    PyCFunction_NewEx(ml, slf, std::ptr::null_mut())\n}\n\n#[cfg(Py_3_9)]\n#[inline]\npub unsafe fn PyCFunction_NewEx(\n    ml: *mut PyMethodDef,\n    slf: *mut PyObject,\n    module: *mut PyObject,\n) -> *mut PyObject {\n    PyCMethod_New(ml, slf, module, std::ptr::null_mut())\n}\n\n#[cfg(Py_3_9)]\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyCMethod_New\")]\n    pub fn PyCMethod_New(\n        ml: *mut PyMethodDef,\n        slf: *mut PyObject,\n        module: *mut PyObject,\n        cls: *mut PyTypeObject,\n    ) -> *mut PyObject;\n}\n\n/* Flag passed to newmethodobject */\npub const METH_VARARGS: c_int = 0x0001;\npub const METH_KEYWORDS: c_int = 0x0002;\n/* METH_NOARGS and METH_O must not be combined with the flags above. */\npub const METH_NOARGS: c_int = 0x0004;\npub const METH_O: c_int = 0x0008;\n\n/* METH_CLASS and METH_STATIC are a little different; these control\nthe construction of methods for a class.  These cannot be used for\nfunctions in modules. */\npub const METH_CLASS: c_int = 0x0010;\npub const METH_STATIC: c_int = 0x0020;\n\n/* METH_COEXIST allows a method to be entered eventhough a slot has\nalready filled the entry.  When defined, the flag allows a separate\nmethod, \"__contains__\" for example, to coexist with a defined\nslot like sq_contains. */\n\npub const METH_COEXIST: c_int = 0x0040;\n\n/* METH_FASTCALL indicates the PEP 590 Vectorcall calling format. It may\nbe specified alone or with METH_KEYWORDS. */\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\npub const METH_FASTCALL: c_int = 0x0080;\n\n// skipped METH_STACKLESS\n\n#[cfg(all(Py_3_9, not(Py_LIMITED_API)))]\npub const METH_METHOD: c_int = 0x0200;\n\nextern_libpython! {\n    #[cfg(not(Py_3_9))]\n    pub fn PyCFunction_ClearFreeList() -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/modsupport.rs",
    "content": "use crate::methodobject::PyMethodDef;\nuse crate::moduleobject::PyModuleDef;\nuse crate::object::PyObject;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::{c_char, c_int, c_long};\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyArg_Parse\")]\n    pub fn PyArg_Parse(arg1: *mut PyObject, arg2: *const c_char, ...) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyArg_ParseTuple\")]\n    pub fn PyArg_ParseTuple(arg1: *mut PyObject, arg2: *const c_char, ...) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyArg_ParseTupleAndKeywords\")]\n    pub fn PyArg_ParseTupleAndKeywords(\n        arg1: *mut PyObject,\n        arg2: *mut PyObject,\n        arg3: *const c_char,\n        #[cfg(not(Py_3_13))] arg4: *mut *mut c_char,\n        #[cfg(Py_3_13)] arg4: *const *const c_char,\n        ...\n    ) -> c_int;\n\n    // skipped PyArg_VaParse\n    // skipped PyArg_VaParseTupleAndKeywords\n\n    pub fn PyArg_ValidateKeywordArguments(arg1: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyArg_UnpackTuple\")]\n    pub fn PyArg_UnpackTuple(\n        arg1: *mut PyObject,\n        arg2: *const c_char,\n        arg3: Py_ssize_t,\n        arg4: Py_ssize_t,\n        ...\n    ) -> c_int;\n\n    #[cfg_attr(PyPy, link_name = \"PyPy_BuildValue\")]\n    pub fn Py_BuildValue(arg1: *const c_char, ...) -> *mut PyObject;\n    // skipped Py_VaBuildValue\n\n    #[cfg(Py_3_13)]\n    pub fn PyModule_Add(module: *mut PyObject, name: *const c_char, value: *mut PyObject) -> c_int;\n    #[cfg(Py_3_10)]\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_AddObjectRef\")]\n    pub fn PyModule_AddObjectRef(\n        module: *mut PyObject,\n        name: *const c_char,\n        value: *mut PyObject,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_AddObject\")]\n    pub fn PyModule_AddObject(\n        module: *mut PyObject,\n        name: *const c_char,\n        value: *mut PyObject,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_AddIntConstant\")]\n    pub fn PyModule_AddIntConstant(\n        module: *mut PyObject,\n        name: *const c_char,\n        value: c_long,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_AddStringConstant\")]\n    pub fn PyModule_AddStringConstant(\n        module: *mut PyObject,\n        name: *const c_char,\n        value: *const c_char,\n    ) -> c_int;\n    #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_AddType\")]\n    pub fn PyModule_AddType(\n        module: *mut PyObject,\n        type_: *mut crate::object::PyTypeObject,\n    ) -> c_int;\n    // skipped PyModule_AddIntMacro\n    // skipped PyModule_AddStringMacro\n    pub fn PyModule_SetDocString(arg1: *mut PyObject, arg2: *const c_char) -> c_int;\n    pub fn PyModule_AddFunctions(arg1: *mut PyObject, arg2: *mut PyMethodDef) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_ExecDef\")]\n    pub fn PyModule_ExecDef(module: *mut PyObject, def: *mut PyModuleDef) -> c_int;\n}\n\npub const Py_CLEANUP_SUPPORTED: i32 = 0x2_0000;\n\npub const PYTHON_API_VERSION: i32 = 1013;\npub const PYTHON_ABI_VERSION: i32 = 3;\n\nextern_libpython! {\n\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_Create2\")]\n    pub fn PyModule_Create2(module: *mut PyModuleDef, apiver: c_int) -> *mut PyObject;\n}\n\n#[inline]\npub unsafe fn PyModule_Create(module: *mut PyModuleDef) -> *mut PyObject {\n    PyModule_Create2(\n        module,\n        if cfg!(Py_LIMITED_API) {\n            PYTHON_ABI_VERSION\n        } else {\n            PYTHON_API_VERSION\n        },\n    )\n}\n\nextern_libpython! {\n\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_FromDefAndSpec2\")]\n    pub fn PyModule_FromDefAndSpec2(\n        def: *mut PyModuleDef,\n        spec: *mut PyObject,\n        module_api_version: c_int,\n    ) -> *mut PyObject;\n\n}\n\n#[inline]\npub unsafe fn PyModule_FromDefAndSpec(def: *mut PyModuleDef, spec: *mut PyObject) -> *mut PyObject {\n    PyModule_FromDefAndSpec2(\n        def,\n        spec,\n        if cfg!(Py_LIMITED_API) {\n            PYTHON_ABI_VERSION\n        } else {\n            PYTHON_API_VERSION\n        },\n    )\n}\n\n#[cfg(Py_3_15)]\n#[repr(C)]\npub struct PyABIInfo {\n    pub abiinfo_major_version: u8,\n    pub abiinfo_minor_version: u8,\n    pub flags: u16,\n    pub build_version: u32,\n    pub abi_version: u32,\n}\n#[cfg(Py_3_15)]\npub const PyABIInfo_STABLE: u16 = 0x0001;\n#[cfg(Py_3_15)]\npub const PyABIInfo_GIL: u16 = 0x0002;\n#[cfg(Py_3_15)]\npub const PyABIInfo_FREETHREADED: u16 = 0x0004;\n#[cfg(Py_3_15)]\npub const PyABIInfo_INTERNAL: u16 = 0x0008;\n\n#[cfg(Py_3_15)]\npub const PyABIInfo_FREETHREADING_AGNOSTIC: u16 = PyABIInfo_GIL | PyABIInfo_FREETHREADED;\n\n#[cfg(Py_3_15)]\nextern_libpython! {\n    pub fn PyABIInfo_Check(info: *mut PyABIInfo, module_name: *const c_char) -> c_int;\n}\n\n#[cfg(all(Py_LIMITED_API, Py_3_15))]\nconst _PyABIInfo_DEFAULT_FLAG_STABLE: u16 = PyABIInfo_STABLE;\n#[cfg(all(Py_3_15, not(Py_LIMITED_API)))]\nconst _PyABIInfo_DEFAULT_FLAG_STABLE: u16 = 0;\n\n// skipped PyABIInfo_DEFAULT_ABI_VERSION: depends on Py_VERSION_HEX\n\n#[cfg(all(Py_3_15, Py_GIL_DISABLED))]\nconst _PyABIInfo_DEFAULT_FLAG_FT: u16 = PyABIInfo_FREETHREADED;\n#[cfg(all(Py_3_15, not(Py_GIL_DISABLED)))]\nconst _PyABIInfo_DEFAULT_FLAG_FT: u16 = PyABIInfo_GIL;\n\n#[cfg(Py_3_15)]\n// has an alternate definition if Py_BUILD_CORE is set, ignore that\nconst _PyABIInfo_DEFAULT_FLAG_INTERNAL: u16 = 0;\n\n#[cfg(Py_3_15)]\npub const PyABIInfo_DEFAULT_FLAGS: u16 =\n    _PyABIInfo_DEFAULT_FLAG_STABLE | _PyABIInfo_DEFAULT_FLAG_FT | _PyABIInfo_DEFAULT_FLAG_INTERNAL;\n\n#[cfg(Py_3_15)]\n// must be pub because it is used by PyABIInfo_VAR\npub const _PyABIInfo_DEFAULT: PyABIInfo = PyABIInfo {\n    abiinfo_major_version: 1,\n    abiinfo_minor_version: 0,\n    flags: PyABIInfo_DEFAULT_FLAGS,\n    build_version: 0,\n    abi_version: 0,\n};\n\n#[cfg(Py_3_15)]\n#[macro_export]\nmacro_rules! PyABIInfo_VAR {\n    ($name:ident) => {\n        static mut $name: pyo3_ffi::PyABIInfo = pyo3_ffi::_PyABIInfo_DEFAULT;\n    };\n}\n"
  },
  {
    "path": "pyo3-ffi/src/moduleobject.rs",
    "content": "use crate::methodobject::PyMethodDef;\nuse crate::object::*;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::{c_char, c_int, c_void};\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_Type\")]\n    pub static mut PyModule_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyModule_Check(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut PyModule_Type)\n}\n\n#[inline]\npub unsafe fn PyModule_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyModule_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_NewObject\")]\n    pub fn PyModule_NewObject(name: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_New\")]\n    pub fn PyModule_New(name: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_GetDict\")]\n    pub fn PyModule_GetDict(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg(not(PyPy))]\n    pub fn PyModule_GetNameObject(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_GetName\")]\n    pub fn PyModule_GetName(arg1: *mut PyObject) -> *const c_char;\n    #[cfg(not(all(windows, PyPy)))]\n    #[deprecated(note = \"Python 3.2\")]\n    pub fn PyModule_GetFilename(arg1: *mut PyObject) -> *const c_char;\n    #[cfg(not(PyPy))]\n    pub fn PyModule_GetFilenameObject(arg1: *mut PyObject) -> *mut PyObject;\n    // skipped non-limited _PyModule_Clear\n    // skipped non-limited _PyModule_ClearDict\n    // skipped non-limited _PyModuleSpec_IsInitializing\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_GetDef\")]\n    pub fn PyModule_GetDef(arg1: *mut PyObject) -> *mut PyModuleDef;\n    #[cfg_attr(PyPy, link_name = \"PyPyModule_GetState\")]\n    pub fn PyModule_GetState(arg1: *mut PyObject) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyModuleDef_Init\")]\n    pub fn PyModuleDef_Init(arg1: *mut PyModuleDef) -> *mut PyObject;\n}\n\nextern_libpython! {\n    pub static mut PyModuleDef_Type: PyTypeObject;\n}\n\n#[repr(C)]\npub struct PyModuleDef_Base {\n    pub ob_base: PyObject,\n    // Rust function pointers are non-null so an Option is needed here.\n    pub m_init: Option<extern \"C\" fn() -> *mut PyObject>,\n    pub m_index: Py_ssize_t,\n    pub m_copy: *mut PyObject,\n}\n\n#[allow(\n    clippy::declare_interior_mutable_const,\n    reason = \"contains atomic refcount on free-threaded builds\"\n)]\npub const PyModuleDef_HEAD_INIT: PyModuleDef_Base = PyModuleDef_Base {\n    ob_base: PyObject_HEAD_INIT,\n    m_init: None,\n    m_index: 0,\n    m_copy: std::ptr::null_mut(),\n};\n\n#[repr(C)]\n#[derive(Copy, Clone, Eq, PartialEq)]\npub struct PyModuleDef_Slot {\n    pub slot: c_int,\n    pub value: *mut c_void,\n}\n\nimpl Default for PyModuleDef_Slot {\n    fn default() -> PyModuleDef_Slot {\n        PyModuleDef_Slot {\n            slot: 0,\n            value: std::ptr::null_mut(),\n        }\n    }\n}\n\npub const Py_mod_create: c_int = 1;\npub const Py_mod_exec: c_int = 2;\n#[cfg(Py_3_12)]\npub const Py_mod_multiple_interpreters: c_int = 3;\n#[cfg(Py_3_13)]\npub const Py_mod_gil: c_int = 4;\n#[cfg(Py_3_15)]\npub const Py_mod_abi: c_int = 5;\n#[cfg(Py_3_15)]\npub const Py_mod_name: c_int = 6;\n#[cfg(Py_3_15)]\npub const Py_mod_doc: c_int = 7;\n#[cfg(Py_3_15)]\npub const Py_mod_state_size: c_int = 8;\n#[cfg(Py_3_15)]\npub const Py_mod_methods: c_int = 9;\n#[cfg(Py_3_15)]\npub const Py_mod_state_traverse: c_int = 10;\n#[cfg(Py_3_15)]\npub const Py_mod_state_clear: c_int = 11;\n#[cfg(Py_3_15)]\npub const Py_mod_state_free: c_int = 12;\n#[cfg(Py_3_15)]\npub const Py_mod_token: c_int = 13;\n\n// skipped private _Py_mod_LAST_SLOT\n\n#[cfg(Py_3_12)]\n#[allow(\n    clippy::zero_ptr,\n    reason = \"matches the way that the rest of these constants are defined\"\n)]\npub const Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED: *mut c_void = 0 as *mut c_void;\n#[cfg(Py_3_12)]\npub const Py_MOD_MULTIPLE_INTERPRETERS_SUPPORTED: *mut c_void = 1 as *mut c_void;\n#[cfg(Py_3_12)]\npub const Py_MOD_PER_INTERPRETER_GIL_SUPPORTED: *mut c_void = 2 as *mut c_void;\n\n#[cfg(Py_3_13)]\n#[allow(\n    clippy::zero_ptr,\n    reason = \"matches the way that the rest of these constants are defined\"\n)]\npub const Py_MOD_GIL_USED: *mut c_void = 0 as *mut c_void;\n#[cfg(Py_3_13)]\npub const Py_MOD_GIL_NOT_USED: *mut c_void = 1 as *mut c_void;\n\n#[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]\nextern_libpython! {\n    pub fn PyUnstable_Module_SetGIL(module: *mut PyObject, gil: *mut c_void) -> c_int;\n}\n\n#[cfg(Py_3_15)]\nextern_libpython! {\n    pub fn PyModule_FromSlotsAndSpec(\n        slots: *const PyModuleDef_Slot,\n        spec: *mut PyObject,\n    ) -> *mut PyObject;\n    pub fn PyModule_Exec(_mod: *mut PyObject) -> c_int;\n    pub fn PyModule_GetStateSize(_mod: *mut PyObject, result: *mut Py_ssize_t) -> c_int;\n    pub fn PyModule_GetToken(module: *mut PyObject, result: *mut *mut c_void) -> c_int;\n}\n\n#[repr(C)]\npub struct PyModuleDef {\n    pub m_base: PyModuleDef_Base,\n    pub m_name: *const c_char,\n    pub m_doc: *const c_char,\n    pub m_size: Py_ssize_t,\n    pub m_methods: *mut PyMethodDef,\n    pub m_slots: *mut PyModuleDef_Slot,\n    // Rust function pointers are non-null so an Option is needed here.\n    pub m_traverse: Option<traverseproc>,\n    pub m_clear: Option<inquiry>,\n    pub m_free: Option<freefunc>,\n}\n"
  },
  {
    "path": "pyo3-ffi/src/object.rs",
    "content": "use crate::pyport::{Py_hash_t, Py_ssize_t};\n#[cfg(Py_GIL_DISABLED)]\nuse crate::refcount;\n#[cfg(Py_GIL_DISABLED)]\nuse crate::PyMutex;\nuse std::ffi::{c_char, c_int, c_uint, c_ulong, c_void};\nuse std::mem;\n#[cfg(Py_GIL_DISABLED)]\nuse std::sync::atomic::{AtomicIsize, AtomicU32};\n\n#[cfg(Py_LIMITED_API)]\nopaque_struct!(pub PyTypeObject);\n\n#[cfg(not(Py_LIMITED_API))]\npub use crate::cpython::object::PyTypeObject;\n\n// skip PyObject_HEAD\n\n#[repr(C)]\n#[derive(Copy, Clone)]\n#[cfg(all(\n    target_pointer_width = \"64\",\n    Py_3_14,\n    not(Py_GIL_DISABLED),\n    target_endian = \"big\"\n))]\n/// This struct is anonymous in CPython, so the name was given by PyO3 because\n/// Rust structs need a name.\npub struct PyObjectObFlagsAndRefcnt {\n    pub ob_flags: u16,\n    pub ob_overflow: u16,\n    pub ob_refcnt: u32,\n}\n\n#[repr(C)]\n#[derive(Copy, Clone)]\n#[cfg(all(\n    target_pointer_width = \"64\",\n    Py_3_14,\n    not(Py_GIL_DISABLED),\n    target_endian = \"little\"\n))]\n/// This struct is anonymous in CPython, so the name was given by PyO3 because\n/// Rust structs need a name.\npub struct PyObjectObFlagsAndRefcnt {\n    pub ob_refcnt: u32,\n    pub ob_overflow: u16,\n    pub ob_flags: u16,\n}\n\n// 4-byte alignment comes from value of _PyObject_MIN_ALIGNMENT\n\n#[cfg(all(not(Py_GIL_DISABLED), Py_3_15))]\n#[repr(C, align(4))]\n#[derive(Copy, Clone)]\nstruct Aligner(c_char);\n\n#[repr(C)]\n#[derive(Copy, Clone)]\n#[cfg(all(Py_3_12, not(Py_GIL_DISABLED)))]\n/// This union is anonymous in CPython, so the name was given by PyO3 because\n/// Rust union need a name.\npub union PyObjectObRefcnt {\n    #[cfg(all(target_pointer_width = \"64\", Py_3_14))]\n    pub ob_refcnt_full: crate::PY_INT64_T,\n    #[cfg(all(target_pointer_width = \"64\", Py_3_14))]\n    pub refcnt_and_flags: PyObjectObFlagsAndRefcnt,\n    pub ob_refcnt: Py_ssize_t,\n    #[cfg(all(target_pointer_width = \"64\", not(Py_3_14)))]\n    pub ob_refcnt_split: [crate::PY_UINT32_T; 2],\n    #[cfg(all(not(Py_GIL_DISABLED), Py_3_15))]\n    _aligner: Aligner,\n}\n\n#[cfg(all(Py_3_12, not(Py_GIL_DISABLED)))]\nimpl std::fmt::Debug for PyObjectObRefcnt {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}\", unsafe { self.ob_refcnt })\n    }\n}\n\n#[cfg(all(not(Py_3_12), not(Py_GIL_DISABLED)))]\npub type PyObjectObRefcnt = Py_ssize_t;\n\nconst _PyObject_MIN_ALIGNMENT: usize = 4;\n\n// PyObject_HEAD_INIT comes before the PyObject definition in object.h\n// but we put it after PyObject because HEAD_INIT uses PyObject\n\n// repr(align(4)) corresponds to the use of _Py_ALIGNED_DEF in object.h. It is\n// not currently possible to use constant variables with repr(align()), see\n// https://github.com/rust-lang/rust/issues/52840\n\n#[cfg_attr(not(all(Py_3_15, Py_GIL_DISABLED)), repr(C))]\n#[cfg_attr(all(Py_3_15, Py_GIL_DISABLED), repr(C, align(4)))]\n#[derive(Debug)]\npub struct PyObject {\n    #[cfg(Py_GIL_DISABLED)]\n    pub ob_tid: libc::uintptr_t,\n    #[cfg(all(Py_GIL_DISABLED, not(Py_3_14)))]\n    pub _padding: u16,\n    #[cfg(all(Py_GIL_DISABLED, Py_3_14))]\n    pub ob_flags: u16,\n    #[cfg(Py_GIL_DISABLED)]\n    pub ob_mutex: PyMutex, // per-object lock\n    #[cfg(Py_GIL_DISABLED)]\n    pub ob_gc_bits: u8, // gc-related state\n    #[cfg(Py_GIL_DISABLED)]\n    pub ob_ref_local: AtomicU32, // local reference count\n    #[cfg(Py_GIL_DISABLED)]\n    pub ob_ref_shared: AtomicIsize, // shared reference count\n    #[cfg(not(Py_GIL_DISABLED))]\n    pub ob_refcnt: PyObjectObRefcnt,\n    #[cfg(PyPy)]\n    pub ob_pypy_link: Py_ssize_t,\n    pub ob_type: *mut PyTypeObject,\n}\n\nconst _: () = assert!(std::mem::align_of::<PyObject>() >= _PyObject_MIN_ALIGNMENT);\n\n#[allow(\n    clippy::declare_interior_mutable_const,\n    reason = \"contains atomic refcount on free-threaded builds\"\n)]\npub const PyObject_HEAD_INIT: PyObject = PyObject {\n    #[cfg(Py_GIL_DISABLED)]\n    ob_tid: 0,\n    #[cfg(all(Py_GIL_DISABLED, Py_3_15))]\n    ob_flags: refcount::_Py_STATICALLY_ALLOCATED_FLAG as u16,\n    #[cfg(all(Py_GIL_DISABLED, all(Py_3_14, not(Py_3_15))))]\n    ob_flags: 0,\n    #[cfg(all(Py_GIL_DISABLED, not(Py_3_14)))]\n    _padding: 0,\n    #[cfg(Py_GIL_DISABLED)]\n    ob_mutex: PyMutex::new(),\n    #[cfg(Py_GIL_DISABLED)]\n    ob_gc_bits: 0,\n    #[cfg(Py_GIL_DISABLED)]\n    ob_ref_local: AtomicU32::new(refcount::_Py_IMMORTAL_REFCNT_LOCAL),\n    #[cfg(Py_GIL_DISABLED)]\n    ob_ref_shared: AtomicIsize::new(0),\n    #[cfg(all(not(Py_GIL_DISABLED), Py_3_12))]\n    ob_refcnt: PyObjectObRefcnt { ob_refcnt: 1 },\n    #[cfg(not(Py_3_12))]\n    ob_refcnt: 1,\n    #[cfg(PyPy)]\n    ob_pypy_link: 0,\n    ob_type: std::ptr::null_mut(),\n};\n\n// skipped _Py_UNOWNED_TID\n\n// skipped _PyObject_CAST\n\n#[repr(C)]\n#[derive(Debug)]\npub struct PyVarObject {\n    pub ob_base: PyObject,\n    #[cfg(not(GraalPy))]\n    pub ob_size: Py_ssize_t,\n    // On GraalPy the field is physically there, but not always populated. We hide it to prevent accidental misuse\n    #[cfg(GraalPy)]\n    pub _ob_size_graalpy: Py_ssize_t,\n}\n\n// skipped private _PyVarObject_CAST\n\n#[inline]\n#[cfg(not(any(GraalPy, PyPy)))]\n#[cfg_attr(docsrs, doc(cfg(all())))]\npub unsafe fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int {\n    (x == y).into()\n}\n\n#[cfg(any(GraalPy, PyPy))]\n#[cfg_attr(docsrs, doc(cfg(all())))]\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPy_Is\")]\n    pub fn Py_Is(x: *mut PyObject, y: *mut PyObject) -> c_int;\n}\n\n// skipped _Py_GetThreadLocal_Addr\n\n// skipped _Py_ThreadID\n\n// skipped _Py_IsOwnedByCurrentThread\n\n#[cfg(GraalPy)]\nextern_libpython! {\n    #[cfg(GraalPy)]\n    fn _Py_TYPE(arg1: *const PyObject) -> *mut PyTypeObject;\n\n    #[cfg(GraalPy)]\n    fn _Py_SIZE(arg1: *const PyObject) -> Py_ssize_t;\n}\n\n#[inline]\n#[cfg(not(Py_3_14))]\npub unsafe fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject {\n    #[cfg(not(GraalPy))]\n    return (*ob).ob_type;\n    #[cfg(GraalPy)]\n    return _Py_TYPE(ob);\n}\n\n#[cfg(Py_3_14)]\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPy_TYPE\")]\n    pub fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject;\n}\n\n// skip _Py_TYPE compat shim\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyLong_Type\")]\n    pub static mut PyLong_Type: PyTypeObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyBool_Type\")]\n    pub static mut PyBool_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn Py_SIZE(ob: *mut PyObject) -> Py_ssize_t {\n    #[cfg(not(GraalPy))]\n    {\n        debug_assert_ne!((*ob).ob_type, &raw mut crate::PyLong_Type);\n        debug_assert_ne!((*ob).ob_type, &raw mut crate::PyBool_Type);\n        (*ob.cast::<PyVarObject>()).ob_size\n    }\n    #[cfg(GraalPy)]\n    _Py_SIZE(ob)\n}\n\n#[inline]\npub unsafe fn Py_IS_TYPE(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int {\n    (Py_TYPE(ob) == tp) as c_int\n}\n\n// skipped Py_SET_TYPE\n\n// skipped Py_SET_SIZE\n\npub type unaryfunc = unsafe extern \"C\" fn(*mut PyObject) -> *mut PyObject;\npub type binaryfunc = unsafe extern \"C\" fn(*mut PyObject, *mut PyObject) -> *mut PyObject;\npub type ternaryfunc =\n    unsafe extern \"C\" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> *mut PyObject;\npub type inquiry = unsafe extern \"C\" fn(*mut PyObject) -> c_int;\npub type lenfunc = unsafe extern \"C\" fn(*mut PyObject) -> Py_ssize_t;\npub type ssizeargfunc = unsafe extern \"C\" fn(*mut PyObject, Py_ssize_t) -> *mut PyObject;\npub type ssizessizeargfunc =\n    unsafe extern \"C\" fn(*mut PyObject, Py_ssize_t, Py_ssize_t) -> *mut PyObject;\npub type ssizeobjargproc = unsafe extern \"C\" fn(*mut PyObject, Py_ssize_t, *mut PyObject) -> c_int;\npub type ssizessizeobjargproc =\n    unsafe extern \"C\" fn(*mut PyObject, Py_ssize_t, Py_ssize_t, arg4: *mut PyObject) -> c_int;\npub type objobjargproc = unsafe extern \"C\" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;\n\npub type objobjproc = unsafe extern \"C\" fn(*mut PyObject, *mut PyObject) -> c_int;\npub type visitproc = unsafe extern \"C\" fn(object: *mut PyObject, arg: *mut c_void) -> c_int;\npub type traverseproc =\n    unsafe extern \"C\" fn(slf: *mut PyObject, visit: visitproc, arg: *mut c_void) -> c_int;\n\npub type freefunc = unsafe extern \"C\" fn(*mut c_void);\npub type destructor = unsafe extern \"C\" fn(*mut PyObject);\npub type getattrfunc = unsafe extern \"C\" fn(*mut PyObject, *mut c_char) -> *mut PyObject;\npub type getattrofunc = unsafe extern \"C\" fn(*mut PyObject, *mut PyObject) -> *mut PyObject;\npub type setattrfunc = unsafe extern \"C\" fn(*mut PyObject, *mut c_char, *mut PyObject) -> c_int;\npub type setattrofunc = unsafe extern \"C\" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;\npub type reprfunc = unsafe extern \"C\" fn(*mut PyObject) -> *mut PyObject;\npub type hashfunc = unsafe extern \"C\" fn(*mut PyObject) -> Py_hash_t;\npub type richcmpfunc = unsafe extern \"C\" fn(*mut PyObject, *mut PyObject, c_int) -> *mut PyObject;\npub type getiterfunc = unsafe extern \"C\" fn(*mut PyObject) -> *mut PyObject;\npub type iternextfunc = unsafe extern \"C\" fn(*mut PyObject) -> *mut PyObject;\npub type descrgetfunc =\n    unsafe extern \"C\" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> *mut PyObject;\npub type descrsetfunc = unsafe extern \"C\" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;\npub type initproc = unsafe extern \"C\" fn(*mut PyObject, *mut PyObject, *mut PyObject) -> c_int;\npub type newfunc =\n    unsafe extern \"C\" fn(*mut PyTypeObject, *mut PyObject, *mut PyObject) -> *mut PyObject;\npub type allocfunc = unsafe extern \"C\" fn(*mut PyTypeObject, Py_ssize_t) -> *mut PyObject;\n\n#[cfg(Py_3_8)]\npub type vectorcallfunc = unsafe extern \"C\" fn(\n    callable: *mut PyObject,\n    args: *const *mut PyObject,\n    nargsf: libc::size_t,\n    kwnames: *mut PyObject,\n) -> *mut PyObject;\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyType_Slot {\n    pub slot: c_int,\n    pub pfunc: *mut c_void,\n}\n\nimpl Default for PyType_Slot {\n    fn default() -> PyType_Slot {\n        unsafe { mem::zeroed() }\n    }\n}\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyType_Spec {\n    pub name: *const c_char,\n    pub basicsize: c_int,\n    pub itemsize: c_int,\n    pub flags: c_uint,\n    pub slots: *mut PyType_Slot,\n}\n\nimpl Default for PyType_Spec {\n    fn default() -> PyType_Spec {\n        unsafe { mem::zeroed() }\n    }\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyType_FromSpec\")]\n    pub fn PyType_FromSpec(arg1: *mut PyType_Spec) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyType_FromSpecWithBases\")]\n    pub fn PyType_FromSpecWithBases(arg1: *mut PyType_Spec, arg2: *mut PyObject) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyType_GetSlot\")]\n    pub fn PyType_GetSlot(arg1: *mut PyTypeObject, arg2: c_int) -> *mut c_void;\n\n    #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]\n    #[cfg_attr(PyPy, link_name = \"PyPyType_FromModuleAndSpec\")]\n    pub fn PyType_FromModuleAndSpec(\n        module: *mut PyObject,\n        spec: *mut PyType_Spec,\n        bases: *mut PyObject,\n    ) -> *mut PyObject;\n\n    #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]\n    #[cfg_attr(PyPy, link_name = \"PyPyType_GetModule\")]\n    pub fn PyType_GetModule(arg1: *mut PyTypeObject) -> *mut PyObject;\n\n    #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]\n    #[cfg_attr(PyPy, link_name = \"PyPyType_GetModuleState\")]\n    pub fn PyType_GetModuleState(arg1: *mut PyTypeObject) -> *mut c_void;\n\n    #[cfg(Py_3_11)]\n    #[cfg_attr(PyPy, link_name = \"PyPyType_GetName\")]\n    pub fn PyType_GetName(arg1: *mut PyTypeObject) -> *mut PyObject;\n\n    #[cfg(Py_3_11)]\n    #[cfg_attr(PyPy, link_name = \"PyPyType_GetQualName\")]\n    pub fn PyType_GetQualName(arg1: *mut PyTypeObject) -> *mut PyObject;\n\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyType_GetFullyQualifiedName\")]\n    pub fn PyType_GetFullyQualifiedName(arg1: *mut PyTypeObject) -> *mut PyObject;\n\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyType_GetModuleName\")]\n    pub fn PyType_GetModuleName(arg1: *mut PyTypeObject) -> *mut PyObject;\n\n    #[cfg(Py_3_12)]\n    #[cfg_attr(PyPy, link_name = \"PyPyType_FromMetaclass\")]\n    pub fn PyType_FromMetaclass(\n        metaclass: *mut PyTypeObject,\n        module: *mut PyObject,\n        spec: *mut PyType_Spec,\n        bases: *mut PyObject,\n    ) -> *mut PyObject;\n\n    #[cfg(Py_3_12)]\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GetTypeData\")]\n    pub fn PyObject_GetTypeData(obj: *mut PyObject, cls: *mut PyTypeObject) -> *mut c_void;\n\n    #[cfg(Py_3_12)]\n    #[cfg_attr(PyPy, link_name = \"PyPyType_GetTypeDataSize\")]\n    pub fn PyType_GetTypeDataSize(cls: *mut PyTypeObject) -> Py_ssize_t;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyType_IsSubtype\")]\n    pub fn PyType_IsSubtype(a: *mut PyTypeObject, b: *mut PyTypeObject) -> c_int;\n}\n\n#[inline]\npub unsafe fn PyObject_TypeCheck(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int {\n    (Py_IS_TYPE(ob, tp) != 0 || PyType_IsSubtype(Py_TYPE(ob), tp) != 0) as c_int\n}\n\nextern_libpython! {\n    /// built-in 'type'\n    #[cfg_attr(PyPy, link_name = \"PyPyType_Type\")]\n    pub static mut PyType_Type: PyTypeObject;\n    /// built-in 'object'\n    #[cfg_attr(PyPy, link_name = \"PyPyBaseObject_Type\")]\n    pub static mut PyBaseObject_Type: PyTypeObject;\n    /// built-in 'super'\n    pub static mut PySuper_Type: PyTypeObject;\n}\n\nextern_libpython! {\n    pub fn PyType_GetFlags(arg1: *mut PyTypeObject) -> c_ulong;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyType_Ready\")]\n    pub fn PyType_Ready(t: *mut PyTypeObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyType_GenericAlloc\")]\n    pub fn PyType_GenericAlloc(t: *mut PyTypeObject, nitems: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyType_GenericNew\")]\n    pub fn PyType_GenericNew(\n        t: *mut PyTypeObject,\n        args: *mut PyObject,\n        kwds: *mut PyObject,\n    ) -> *mut PyObject;\n    pub fn PyType_ClearCache() -> c_uint;\n    #[cfg_attr(PyPy, link_name = \"PyPyType_Modified\")]\n    pub fn PyType_Modified(t: *mut PyTypeObject);\n\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Repr\")]\n    pub fn PyObject_Repr(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Str\")]\n    pub fn PyObject_Str(o: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_ASCII\")]\n    pub fn PyObject_ASCII(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Bytes\")]\n    pub fn PyObject_Bytes(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_RichCompare\")]\n    pub fn PyObject_RichCompare(\n        arg1: *mut PyObject,\n        arg2: *mut PyObject,\n        arg3: c_int,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_RichCompareBool\")]\n    pub fn PyObject_RichCompareBool(arg1: *mut PyObject, arg2: *mut PyObject, arg3: c_int)\n        -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GetAttrString\")]\n    pub fn PyObject_GetAttrString(arg1: *mut PyObject, arg2: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_SetAttrString\")]\n    pub fn PyObject_SetAttrString(\n        arg1: *mut PyObject,\n        arg2: *const c_char,\n        arg3: *mut PyObject,\n    ) -> c_int;\n    #[cfg(any(Py_3_13, all(PyPy, not(Py_3_11))))] // CPython defined in 3.12 as an inline function in abstract.h\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_DelAttrString\")]\n    pub fn PyObject_DelAttrString(arg1: *mut PyObject, arg2: *const c_char) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_HasAttrString\")]\n    pub fn PyObject_HasAttrString(arg1: *mut PyObject, arg2: *const c_char) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GetAttr\")]\n    pub fn PyObject_GetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GetOptionalAttr\")]\n    pub fn PyObject_GetOptionalAttr(\n        arg1: *mut PyObject,\n        arg2: *mut PyObject,\n        arg3: *mut *mut PyObject,\n    ) -> c_int;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GetOptionalAttrString\")]\n    pub fn PyObject_GetOptionalAttrString(\n        arg1: *mut PyObject,\n        arg2: *const c_char,\n        arg3: *mut *mut PyObject,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_SetAttr\")]\n    pub fn PyObject_SetAttr(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject)\n        -> c_int;\n    #[cfg(any(Py_3_13, all(PyPy, not(Py_3_11))))] // CPython defined in 3.12 as an inline function in abstract.h\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_DelAttr\")]\n    pub fn PyObject_DelAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_HasAttr\")]\n    pub fn PyObject_HasAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_HasAttrWithError\")]\n    pub fn PyObject_HasAttrWithError(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_HasAttrStringWithError\")]\n    pub fn PyObject_HasAttrStringWithError(arg1: *mut PyObject, arg2: *const c_char) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_SelfIter\")]\n    pub fn PyObject_SelfIter(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GenericGetAttr\")]\n    pub fn PyObject_GenericGetAttr(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GenericSetAttr\")]\n    pub fn PyObject_GenericSetAttr(\n        arg1: *mut PyObject,\n        arg2: *mut PyObject,\n        arg3: *mut PyObject,\n    ) -> c_int;\n    #[cfg(not(all(Py_LIMITED_API, not(Py_3_10))))]\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GenericGetDict\")]\n    pub fn PyObject_GenericGetDict(arg1: *mut PyObject, arg2: *mut c_void) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GenericSetDict\")]\n    pub fn PyObject_GenericSetDict(\n        arg1: *mut PyObject,\n        arg2: *mut PyObject,\n        arg3: *mut c_void,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Hash\")]\n    pub fn PyObject_Hash(arg1: *mut PyObject) -> Py_hash_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_HashNotImplemented\")]\n    pub fn PyObject_HashNotImplemented(arg1: *mut PyObject) -> Py_hash_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_IsTrue\")]\n    pub fn PyObject_IsTrue(arg1: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Not\")]\n    pub fn PyObject_Not(arg1: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyCallable_Check\")]\n    pub fn PyCallable_Check(arg1: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_ClearWeakRefs\")]\n    pub fn PyObject_ClearWeakRefs(arg1: *mut PyObject);\n\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Dir\")]\n    pub fn PyObject_Dir(arg1: *mut PyObject) -> *mut PyObject;\n    pub fn Py_ReprEnter(arg1: *mut PyObject) -> c_int;\n    pub fn Py_ReprLeave(arg1: *mut PyObject);\n}\n\n// Flag bits for printing:\npub const Py_PRINT_RAW: c_int = 1; // No string quotes etc.\n\n// skipped because is a private API\n// const _Py_TPFLAGS_STATIC_BUILTIN: c_ulong = 1 << 1;\n\n#[cfg(all(Py_3_12, not(Py_LIMITED_API)))]\npub const Py_TPFLAGS_MANAGED_WEAKREF: c_ulong = 1 << 3;\n\n#[cfg(all(Py_3_11, not(Py_LIMITED_API)))]\npub const Py_TPFLAGS_MANAGED_DICT: c_ulong = 1 << 4;\n\n#[cfg(all(Py_3_10, not(Py_LIMITED_API)))]\npub const Py_TPFLAGS_SEQUENCE: c_ulong = 1 << 5;\n\n#[cfg(all(Py_3_10, not(Py_LIMITED_API)))]\npub const Py_TPFLAGS_MAPPING: c_ulong = 1 << 6;\n\n#[cfg(Py_3_10)]\npub const Py_TPFLAGS_DISALLOW_INSTANTIATION: c_ulong = 1 << 7;\n\n#[cfg(Py_3_10)]\npub const Py_TPFLAGS_IMMUTABLETYPE: c_ulong = 1 << 8;\n\n/// Set if the type object is dynamically allocated\npub const Py_TPFLAGS_HEAPTYPE: c_ulong = 1 << 9;\n\n/// Set if the type allows subclassing\npub const Py_TPFLAGS_BASETYPE: c_ulong = 1 << 10;\n\n/// Set if the type implements the vectorcall protocol (PEP 590)\n#[cfg(any(Py_3_12, all(Py_3_8, not(Py_LIMITED_API))))]\npub const Py_TPFLAGS_HAVE_VECTORCALL: c_ulong = 1 << 11;\n// skipped backwards-compatibility alias _Py_TPFLAGS_HAVE_VECTORCALL\n\n/// Set if the type is 'ready' -- fully initialized\npub const Py_TPFLAGS_READY: c_ulong = 1 << 12;\n\n/// Set while the type is being 'readied', to prevent recursive ready calls\npub const Py_TPFLAGS_READYING: c_ulong = 1 << 13;\n\n/// Objects support garbage collection (see objimp.h)\npub const Py_TPFLAGS_HAVE_GC: c_ulong = 1 << 14;\n\nconst Py_TPFLAGS_HAVE_STACKLESS_EXTENSION: c_ulong = 0;\n\n#[cfg(Py_3_8)]\npub const Py_TPFLAGS_METHOD_DESCRIPTOR: c_ulong = 1 << 17;\n\npub const Py_TPFLAGS_VALID_VERSION_TAG: c_ulong = 1 << 19;\n\n/* Type is abstract and cannot be instantiated */\npub const Py_TPFLAGS_IS_ABSTRACT: c_ulong = 1 << 20;\n\n// skipped non-limited / 3.10 Py_TPFLAGS_HAVE_AM_SEND\n#[cfg(Py_3_12)]\npub const Py_TPFLAGS_ITEMS_AT_END: c_ulong = 1 << 23;\n\n/* These flags are used to determine if a type is a subclass. */\npub const Py_TPFLAGS_LONG_SUBCLASS: c_ulong = 1 << 24;\npub const Py_TPFLAGS_LIST_SUBCLASS: c_ulong = 1 << 25;\npub const Py_TPFLAGS_TUPLE_SUBCLASS: c_ulong = 1 << 26;\npub const Py_TPFLAGS_BYTES_SUBCLASS: c_ulong = 1 << 27;\npub const Py_TPFLAGS_UNICODE_SUBCLASS: c_ulong = 1 << 28;\npub const Py_TPFLAGS_DICT_SUBCLASS: c_ulong = 1 << 29;\npub const Py_TPFLAGS_BASE_EXC_SUBCLASS: c_ulong = 1 << 30;\npub const Py_TPFLAGS_TYPE_SUBCLASS: c_ulong = 1 << 31;\n\npub const Py_TPFLAGS_DEFAULT: c_ulong = if cfg!(Py_3_10) {\n    Py_TPFLAGS_HAVE_STACKLESS_EXTENSION\n} else {\n    Py_TPFLAGS_HAVE_STACKLESS_EXTENSION | Py_TPFLAGS_HAVE_VERSION_TAG\n};\n\npub const Py_TPFLAGS_HAVE_FINALIZE: c_ulong = 1;\npub const Py_TPFLAGS_HAVE_VERSION_TAG: c_ulong = 1 << 18;\n\n#[cfg(Py_3_13)]\npub const Py_CONSTANT_NONE: c_uint = 0;\n#[cfg(Py_3_13)]\npub const Py_CONSTANT_FALSE: c_uint = 1;\n#[cfg(Py_3_13)]\npub const Py_CONSTANT_TRUE: c_uint = 2;\n#[cfg(Py_3_13)]\npub const Py_CONSTANT_ELLIPSIS: c_uint = 3;\n#[cfg(Py_3_13)]\npub const Py_CONSTANT_NOT_IMPLEMENTED: c_uint = 4;\n#[cfg(Py_3_13)]\npub const Py_CONSTANT_ZERO: c_uint = 5;\n#[cfg(Py_3_13)]\npub const Py_CONSTANT_ONE: c_uint = 6;\n#[cfg(Py_3_13)]\npub const Py_CONSTANT_EMPTY_STR: c_uint = 7;\n#[cfg(Py_3_13)]\npub const Py_CONSTANT_EMPTY_BYTES: c_uint = 8;\n#[cfg(Py_3_13)]\npub const Py_CONSTANT_EMPTY_TUPLE: c_uint = 9;\n\nextern_libpython! {\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPy_GetConstant\")]\n    pub fn Py_GetConstant(constant_id: c_uint) -> *mut PyObject;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPy_GetConstantBorrowed\")]\n    pub fn Py_GetConstantBorrowed(constant_id: c_uint) -> *mut PyObject;\n}\n\nextern_libpython! {\n    #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]\n    #[cfg_attr(PyPy, link_name = \"_PyPy_NoneStruct\")]\n    static mut _Py_NoneStruct: PyObject;\n\n    #[cfg(GraalPy)]\n    static mut _Py_NoneStructReference: *mut PyObject;\n}\n\n#[inline]\npub unsafe fn Py_None() -> *mut PyObject {\n    #[cfg(all(not(GraalPy), all(Py_3_13, Py_LIMITED_API)))]\n    return Py_GetConstantBorrowed(Py_CONSTANT_NONE);\n\n    #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]\n    return &raw mut _Py_NoneStruct;\n\n    #[cfg(GraalPy)]\n    return _Py_NoneStructReference;\n}\n\n#[inline]\npub unsafe fn Py_IsNone(x: *mut PyObject) -> c_int {\n    Py_Is(x, Py_None())\n}\n\n// skipped Py_RETURN_NONE\n\nextern_libpython! {\n    #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]\n    #[cfg_attr(PyPy, link_name = \"_PyPy_NotImplementedStruct\")]\n    static mut _Py_NotImplementedStruct: PyObject;\n\n    #[cfg(GraalPy)]\n    static mut _Py_NotImplementedStructReference: *mut PyObject;\n}\n\n#[inline]\npub unsafe fn Py_NotImplemented() -> *mut PyObject {\n    #[cfg(all(not(GraalPy), all(Py_3_13, Py_LIMITED_API)))]\n    return Py_GetConstantBorrowed(Py_CONSTANT_NOT_IMPLEMENTED);\n\n    #[cfg(all(not(GraalPy), not(all(Py_3_13, Py_LIMITED_API))))]\n    return &raw mut _Py_NotImplementedStruct;\n\n    #[cfg(GraalPy)]\n    return _Py_NotImplementedStructReference;\n}\n\n// skipped Py_RETURN_NOTIMPLEMENTED\n\n/* Rich comparison opcodes */\npub const Py_LT: c_int = 0;\npub const Py_LE: c_int = 1;\npub const Py_EQ: c_int = 2;\npub const Py_NE: c_int = 3;\npub const Py_GT: c_int = 4;\npub const Py_GE: c_int = 5;\n\n#[cfg(Py_3_10)]\n#[repr(C)]\n#[derive(Copy, Clone, Debug, PartialEq, Eq)]\npub enum PySendResult {\n    PYGEN_RETURN = 0,\n    PYGEN_ERROR = -1,\n    PYGEN_NEXT = 1,\n}\n\n// skipped Py_RETURN_RICHCOMPARE\n\n#[inline]\npub unsafe fn PyType_HasFeature(ty: *mut PyTypeObject, feature: c_ulong) -> c_int {\n    #[cfg(Py_LIMITED_API)]\n    let flags = PyType_GetFlags(ty);\n\n    #[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]\n    let flags = (*ty).tp_flags.load(std::sync::atomic::Ordering::Relaxed);\n\n    #[cfg(all(not(Py_LIMITED_API), not(Py_GIL_DISABLED)))]\n    let flags = (*ty).tp_flags;\n\n    ((flags & feature) != 0) as c_int\n}\n\n#[inline]\npub unsafe fn PyType_FastSubclass(t: *mut PyTypeObject, f: c_ulong) -> c_int {\n    PyType_HasFeature(t, f)\n}\n\n#[inline]\npub unsafe fn PyType_Check(op: *mut PyObject) -> c_int {\n    PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS)\n}\n\n// skipped _PyType_CAST\n\n#[inline]\npub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int {\n    Py_IS_TYPE(op, &raw mut PyType_Type)\n}\n\nextern_libpython! {\n    #[cfg(any(Py_3_13, all(Py_3_11, not(Py_LIMITED_API))))]\n    #[cfg_attr(PyPy, link_name = \"PyPyType_GetModuleByDef\")]\n    pub fn PyType_GetModuleByDef(\n        arg1: *mut crate::PyTypeObject,\n        arg2: *mut crate::PyModuleDef,\n    ) -> *mut PyObject;\n\n    #[cfg(Py_3_14)]\n    pub fn PyType_Freeze(tp: *mut crate::PyTypeObject) -> c_int;\n\n    #[cfg(Py_3_15)]\n    pub fn PyType_GetModuleByToken(_type: *mut PyTypeObject, token: *const c_void)\n        -> *mut PyObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/objimpl.rs",
    "content": "use libc::size_t;\nuse std::ffi::{c_int, c_void};\n\nuse crate::object::*;\nuse crate::pyport::Py_ssize_t;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Malloc\")]\n    pub fn PyObject_Malloc(size: size_t) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Calloc\")]\n    pub fn PyObject_Calloc(nelem: size_t, elsize: size_t) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Realloc\")]\n    pub fn PyObject_Realloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Free\")]\n    pub fn PyObject_Free(ptr: *mut c_void);\n\n    // skipped PyObject_MALLOC\n    // skipped PyObject_REALLOC\n    // skipped PyObject_FREE\n    // skipped PyObject_Del\n    // skipped PyObject_DEL\n\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_Init\")]\n    pub fn PyObject_Init(arg1: *mut PyObject, arg2: *mut PyTypeObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_InitVar\")]\n    pub fn PyObject_InitVar(\n        arg1: *mut PyVarObject,\n        arg2: *mut PyTypeObject,\n        arg3: Py_ssize_t,\n    ) -> *mut PyVarObject;\n\n    // skipped PyObject_INIT\n    // skipped PyObject_INIT_VAR\n\n    #[cfg_attr(PyPy, link_name = \"_PyPyObject_New\")]\n    fn _PyObject_New(typeobj: *mut PyTypeObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"_PyPyObject_NewVar\")]\n    fn _PyObject_NewVar(typeobj: *mut PyTypeObject, n: Py_ssize_t) -> *mut PyVarObject;\n}\n\n#[inline]\npub unsafe fn PyObject_New<T>(typeobj: *mut PyTypeObject) -> *mut T {\n    _PyObject_New(typeobj).cast()\n}\n\n// skipped PyObject_NEW\n\n#[inline]\npub unsafe fn PyObject_NewVar<T>(typeobj: *mut PyTypeObject, n: Py_ssize_t) -> *mut T {\n    _PyObject_NewVar(typeobj, n).cast()\n}\n\n// skipped PyObject_NEW_VAR\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyGC_Collect\")]\n    pub fn PyGC_Collect() -> Py_ssize_t;\n\n    #[cfg(Py_3_10)]\n    #[cfg_attr(PyPy, link_name = \"PyPyGC_Enable\")]\n    pub fn PyGC_Enable() -> c_int;\n\n    #[cfg(Py_3_10)]\n    #[cfg_attr(PyPy, link_name = \"PyPyGC_Disable\")]\n    pub fn PyGC_Disable() -> c_int;\n\n    #[cfg(Py_3_10)]\n    #[cfg_attr(PyPy, link_name = \"PyPyGC_IsEnabled\")]\n    pub fn PyGC_IsEnabled() -> c_int;\n}\n\n#[inline]\npub unsafe fn PyType_IS_GC(t: *mut PyTypeObject) -> c_int {\n    PyType_HasFeature(t, Py_TPFLAGS_HAVE_GC)\n}\n\nextern_libpython! {\n    fn _PyObject_GC_Resize(op: *mut PyVarObject, n: Py_ssize_t) -> *mut PyVarObject;\n}\n\n#[inline]\npub unsafe fn PyObject_GC_Resize<T>(op: *mut PyObject, n: Py_ssize_t) -> *mut T {\n    _PyObject_GC_Resize(op.cast(), n).cast()\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"_PyPyObject_GC_New\")]\n    fn _PyObject_GC_New(typeobj: *mut PyTypeObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"_PyPyObject_GC_NewVar\")]\n    fn _PyObject_GC_NewVar(typeobj: *mut PyTypeObject, n: Py_ssize_t) -> *mut PyVarObject;\n\n    #[cfg(not(PyPy))]\n    pub fn PyObject_GC_Track(arg1: *mut c_void);\n\n    #[cfg(not(PyPy))]\n    pub fn PyObject_GC_UnTrack(arg1: *mut c_void);\n\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GC_Del\")]\n    pub fn PyObject_GC_Del(arg1: *mut c_void);\n}\n\n#[inline]\npub unsafe fn PyObject_GC_New<T>(typeobj: *mut PyTypeObject) -> *mut T {\n    _PyObject_GC_New(typeobj).cast()\n}\n\n#[inline]\npub unsafe fn PyObject_GC_NewVar<T>(typeobj: *mut PyTypeObject, n: Py_ssize_t) -> *mut T {\n    _PyObject_GC_NewVar(typeobj, n).cast()\n}\n\nextern_libpython! {\n    #[cfg(any(all(Py_3_9, not(PyPy)), Py_3_10))] // added in 3.9, or 3.10 on PyPy\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GC_IsTracked\")]\n    pub fn PyObject_GC_IsTracked(arg1: *mut PyObject) -> c_int;\n    #[cfg(any(all(Py_3_9, not(PyPy)), Py_3_10))] // added in 3.9, or 3.10 on PyPy\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GC_IsFinalized\")]\n    pub fn PyObject_GC_IsFinalized(arg1: *mut PyObject) -> c_int;\n}\n\n// skipped Py_VISIT\n"
  },
  {
    "path": "pyo3-ffi/src/osmodule.rs",
    "content": "use crate::object::PyObject;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyOS_FSPath\")]\n    pub fn PyOS_FSPath(path: *mut PyObject) -> *mut PyObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/pyarena.rs",
    "content": "opaque_struct!(pub PyArena);\n"
  },
  {
    "path": "pyo3-ffi/src/pybuffer.rs",
    "content": "use crate::object::PyObject;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::{c_char, c_int, c_void};\nuse std::ptr;\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct Py_buffer {\n    pub buf: *mut c_void,\n    /// Owned reference\n    pub obj: *mut crate::PyObject,\n    pub len: Py_ssize_t,\n    pub itemsize: Py_ssize_t,\n    pub readonly: c_int,\n    pub ndim: c_int,\n    pub format: *mut c_char,\n    pub shape: *mut Py_ssize_t,\n    pub strides: *mut Py_ssize_t,\n    pub suboffsets: *mut Py_ssize_t,\n    pub internal: *mut c_void,\n    #[cfg(PyPy)]\n    pub flags: c_int,\n    #[cfg(PyPy)]\n    pub _strides: [Py_ssize_t; PyBUF_MAX_NDIM],\n    #[cfg(PyPy)]\n    pub _shape: [Py_ssize_t; PyBUF_MAX_NDIM],\n}\n\nimpl Py_buffer {\n    #[allow(clippy::new_without_default)]\n    pub const fn new() -> Self {\n        Py_buffer {\n            buf: ptr::null_mut(),\n            obj: ptr::null_mut(),\n            len: 0,\n            itemsize: 0,\n            readonly: 0,\n            ndim: 0,\n            format: ptr::null_mut(),\n            shape: ptr::null_mut(),\n            strides: ptr::null_mut(),\n            suboffsets: ptr::null_mut(),\n            internal: ptr::null_mut(),\n            #[cfg(PyPy)]\n            flags: 0,\n            #[cfg(PyPy)]\n            _strides: [0; PyBUF_MAX_NDIM],\n            #[cfg(PyPy)]\n            _shape: [0; PyBUF_MAX_NDIM],\n        }\n    }\n}\n\npub type getbufferproc = unsafe extern \"C\" fn(*mut PyObject, *mut crate::Py_buffer, c_int) -> c_int;\npub type releasebufferproc = unsafe extern \"C\" fn(*mut PyObject, *mut crate::Py_buffer);\n\n/* Return 1 if the getbuffer function is available, otherwise return 0. */\nextern_libpython! {\n    #[cfg(not(PyPy))]\n    pub fn PyObject_CheckBuffer(obj: *mut PyObject) -> c_int;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyObject_GetBuffer\")]\n    pub fn PyObject_GetBuffer(obj: *mut PyObject, view: *mut Py_buffer, flags: c_int) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_GetPointer\")]\n    pub fn PyBuffer_GetPointer(view: *const Py_buffer, indices: *const Py_ssize_t) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_SizeFromFormat\")]\n    pub fn PyBuffer_SizeFromFormat(format: *const c_char) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_ToContiguous\")]\n    pub fn PyBuffer_ToContiguous(\n        buf: *mut c_void,\n        view: *const Py_buffer,\n        len: Py_ssize_t,\n        order: c_char,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_FromContiguous\")]\n    pub fn PyBuffer_FromContiguous(\n        view: *const Py_buffer,\n        buf: *const c_void,\n        len: Py_ssize_t,\n        order: c_char,\n    ) -> c_int;\n    pub fn PyObject_CopyData(dest: *mut PyObject, src: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_IsContiguous\")]\n    pub fn PyBuffer_IsContiguous(view: *const Py_buffer, fort: c_char) -> c_int;\n    pub fn PyBuffer_FillContiguousStrides(\n        ndims: c_int,\n        shape: *mut Py_ssize_t,\n        strides: *mut Py_ssize_t,\n        itemsize: c_int,\n        fort: c_char,\n    );\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_FillInfo\")]\n    pub fn PyBuffer_FillInfo(\n        view: *mut Py_buffer,\n        o: *mut PyObject,\n        buf: *mut c_void,\n        len: Py_ssize_t,\n        readonly: c_int,\n        flags: c_int,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyBuffer_Release\")]\n    pub fn PyBuffer_Release(view: *mut Py_buffer);\n}\n\n/// Maximum number of dimensions\npub const PyBUF_MAX_NDIM: usize = 64;\n\n/* Flags for getting buffers */\npub const PyBUF_SIMPLE: c_int = 0;\npub const PyBUF_WRITABLE: c_int = 0x0001;\n/* we used to include an E, backwards compatible alias */\npub const PyBUF_WRITEABLE: c_int = PyBUF_WRITABLE;\npub const PyBUF_FORMAT: c_int = 0x0004;\npub const PyBUF_ND: c_int = 0x0008;\npub const PyBUF_STRIDES: c_int = 0x0010 | PyBUF_ND;\npub const PyBUF_C_CONTIGUOUS: c_int = 0x0020 | PyBUF_STRIDES;\npub const PyBUF_F_CONTIGUOUS: c_int = 0x0040 | PyBUF_STRIDES;\npub const PyBUF_ANY_CONTIGUOUS: c_int = 0x0080 | PyBUF_STRIDES;\npub const PyBUF_INDIRECT: c_int = 0x0100 | PyBUF_STRIDES;\n\npub const PyBUF_CONTIG: c_int = PyBUF_ND | PyBUF_WRITABLE;\npub const PyBUF_CONTIG_RO: c_int = PyBUF_ND;\n\npub const PyBUF_STRIDED: c_int = PyBUF_STRIDES | PyBUF_WRITABLE;\npub const PyBUF_STRIDED_RO: c_int = PyBUF_STRIDES;\n\npub const PyBUF_RECORDS: c_int = PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT;\npub const PyBUF_RECORDS_RO: c_int = PyBUF_STRIDES | PyBUF_FORMAT;\n\npub const PyBUF_FULL: c_int = PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT;\npub const PyBUF_FULL_RO: c_int = PyBUF_INDIRECT | PyBUF_FORMAT;\n\npub const PyBUF_READ: c_int = 0x100;\npub const PyBUF_WRITE: c_int = 0x200;\n"
  },
  {
    "path": "pyo3-ffi/src/pycapsule.rs",
    "content": "use crate::object::*;\nuse std::ffi::{c_char, c_int, c_void};\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_Type\")]\n    pub static mut PyCapsule_Type: PyTypeObject;\n}\n\npub type PyCapsule_Destructor = unsafe extern \"C\" fn(o: *mut PyObject);\n\n#[inline]\npub unsafe fn PyCapsule_CheckExact(ob: *mut PyObject) -> c_int {\n    (Py_TYPE(ob) == &raw mut PyCapsule_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_New\")]\n    pub fn PyCapsule_New(\n        pointer: *mut c_void,\n        name: *const c_char,\n        destructor: Option<PyCapsule_Destructor>,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_GetPointer\")]\n    pub fn PyCapsule_GetPointer(capsule: *mut PyObject, name: *const c_char) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_GetDestructor\")]\n    pub fn PyCapsule_GetDestructor(capsule: *mut PyObject) -> Option<PyCapsule_Destructor>;\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_GetName\")]\n    pub fn PyCapsule_GetName(capsule: *mut PyObject) -> *const c_char;\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_GetContext\")]\n    pub fn PyCapsule_GetContext(capsule: *mut PyObject) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_IsValid\")]\n    pub fn PyCapsule_IsValid(capsule: *mut PyObject, name: *const c_char) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_SetPointer\")]\n    pub fn PyCapsule_SetPointer(capsule: *mut PyObject, pointer: *mut c_void) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_SetDestructor\")]\n    pub fn PyCapsule_SetDestructor(\n        capsule: *mut PyObject,\n        destructor: Option<PyCapsule_Destructor>,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_SetName\")]\n    pub fn PyCapsule_SetName(capsule: *mut PyObject, name: *const c_char) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_SetContext\")]\n    pub fn PyCapsule_SetContext(capsule: *mut PyObject, context: *mut c_void) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyCapsule_Import\")]\n    pub fn PyCapsule_Import(name: *const c_char, no_block: c_int) -> *mut c_void;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/pyerrors.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::{c_char, c_int};\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_SetNone\")]\n    pub fn PyErr_SetNone(arg1: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_SetObject\")]\n    pub fn PyErr_SetObject(arg1: *mut PyObject, arg2: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_SetString\")]\n    pub fn PyErr_SetString(exception: *mut PyObject, string: *const c_char);\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_Occurred\")]\n    pub fn PyErr_Occurred() -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_Clear\")]\n    pub fn PyErr_Clear();\n    #[cfg_attr(Py_3_12, deprecated(note = \"Use PyErr_GetRaisedException() instead.\"))]\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_Fetch\")]\n    pub fn PyErr_Fetch(\n        arg1: *mut *mut PyObject,\n        arg2: *mut *mut PyObject,\n        arg3: *mut *mut PyObject,\n    );\n    #[cfg_attr(Py_3_12, deprecated(note = \"Use PyErr_SetRaisedException() instead.\"))]\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_Restore\")]\n    pub fn PyErr_Restore(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_GetExcInfo\")]\n    pub fn PyErr_GetExcInfo(\n        arg1: *mut *mut PyObject,\n        arg2: *mut *mut PyObject,\n        arg3: *mut *mut PyObject,\n    );\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_SetExcInfo\")]\n    pub fn PyErr_SetExcInfo(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPy_FatalError\")]\n    pub fn Py_FatalError(message: *const c_char) -> !;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_GivenExceptionMatches\")]\n    pub fn PyErr_GivenExceptionMatches(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_ExceptionMatches\")]\n    pub fn PyErr_ExceptionMatches(arg1: *mut PyObject) -> c_int;\n    #[cfg_attr(\n        Py_3_12,\n        deprecated(\n            note = \"Use PyErr_GetRaisedException() instead, to avoid any possible de-normalization.\"\n        )\n    )]\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_NormalizeException\")]\n    pub fn PyErr_NormalizeException(\n        arg1: *mut *mut PyObject,\n        arg2: *mut *mut PyObject,\n        arg3: *mut *mut PyObject,\n    );\n    #[cfg(Py_3_12)]\n    pub fn PyErr_GetRaisedException() -> *mut PyObject;\n    #[cfg(Py_3_12)]\n    pub fn PyErr_SetRaisedException(exc: *mut PyObject);\n    #[cfg(Py_3_11)]\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_GetHandledException\")]\n    pub fn PyErr_GetHandledException() -> *mut PyObject;\n    #[cfg(Py_3_11)]\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_SetHandledException\")]\n    pub fn PyErr_SetHandledException(exc: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPyException_SetTraceback\")]\n    pub fn PyException_SetTraceback(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyException_GetTraceback\")]\n    pub fn PyException_GetTraceback(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyException_GetCause\")]\n    pub fn PyException_GetCause(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyException_SetCause\")]\n    pub fn PyException_SetCause(arg1: *mut PyObject, arg2: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPyException_GetContext\")]\n    pub fn PyException_GetContext(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyException_SetContext\")]\n    pub fn PyException_SetContext(arg1: *mut PyObject, arg2: *mut PyObject);\n\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyExceptionInstance_Class\"]\n    pub fn PyExceptionInstance_Class(x: *mut PyObject) -> *mut PyObject;\n}\n\n#[inline]\npub unsafe fn PyExceptionClass_Check(x: *mut PyObject) -> c_int {\n    (PyType_Check(x) != 0\n        && PyType_FastSubclass(x as *mut PyTypeObject, Py_TPFLAGS_BASE_EXC_SUBCLASS) != 0)\n        as c_int\n}\n\n#[inline]\npub unsafe fn PyExceptionInstance_Check(x: *mut PyObject) -> c_int {\n    PyType_FastSubclass(Py_TYPE(x), Py_TPFLAGS_BASE_EXC_SUBCLASS)\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyExceptionInstance_Class(x: *mut PyObject) -> *mut PyObject {\n    Py_TYPE(x) as *mut PyObject\n}\n\n// ported from cpython exception.c (line 2096)\n#[cfg(PyPy)]\npub unsafe fn PyUnicodeDecodeError_Create(\n    encoding: *const c_char,\n    object: *const c_char,\n    length: Py_ssize_t,\n    start: Py_ssize_t,\n    end: Py_ssize_t,\n    reason: *const c_char,\n) -> *mut PyObject {\n    crate::_PyObject_CallFunction_SizeT(\n        PyExc_UnicodeDecodeError,\n        c\"sy#nns\".as_ptr(),\n        encoding,\n        object,\n        length,\n        start,\n        end,\n        reason,\n    )\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_BaseException\")]\n    pub static mut PyExc_BaseException: *mut PyObject;\n    #[cfg(Py_3_11)]\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_BaseExceptionGroup\")]\n    pub static mut PyExc_BaseExceptionGroup: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_Exception\")]\n    pub static mut PyExc_Exception: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_StopAsyncIteration\")]\n    pub static mut PyExc_StopAsyncIteration: *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_StopIteration\")]\n    pub static mut PyExc_StopIteration: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_GeneratorExit\")]\n    pub static mut PyExc_GeneratorExit: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ArithmeticError\")]\n    pub static mut PyExc_ArithmeticError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_LookupError\")]\n    pub static mut PyExc_LookupError: *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_AssertionError\")]\n    pub static mut PyExc_AssertionError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_AttributeError\")]\n    pub static mut PyExc_AttributeError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_BufferError\")]\n    pub static mut PyExc_BufferError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_EOFError\")]\n    pub static mut PyExc_EOFError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_FloatingPointError\")]\n    pub static mut PyExc_FloatingPointError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_OSError\")]\n    pub static mut PyExc_OSError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ImportError\")]\n    pub static mut PyExc_ImportError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ModuleNotFoundError\")]\n    pub static mut PyExc_ModuleNotFoundError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_IndexError\")]\n    pub static mut PyExc_IndexError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_KeyError\")]\n    pub static mut PyExc_KeyError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_KeyboardInterrupt\")]\n    pub static mut PyExc_KeyboardInterrupt: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_MemoryError\")]\n    pub static mut PyExc_MemoryError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_NameError\")]\n    pub static mut PyExc_NameError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_OverflowError\")]\n    pub static mut PyExc_OverflowError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_RuntimeError\")]\n    pub static mut PyExc_RuntimeError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_RecursionError\")]\n    pub static mut PyExc_RecursionError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_NotImplementedError\")]\n    pub static mut PyExc_NotImplementedError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_SyntaxError\")]\n    pub static mut PyExc_SyntaxError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_IndentationError\")]\n    pub static mut PyExc_IndentationError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_TabError\")]\n    pub static mut PyExc_TabError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ReferenceError\")]\n    pub static mut PyExc_ReferenceError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_SystemError\")]\n    pub static mut PyExc_SystemError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_SystemExit\")]\n    pub static mut PyExc_SystemExit: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_TypeError\")]\n    pub static mut PyExc_TypeError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_UnboundLocalError\")]\n    pub static mut PyExc_UnboundLocalError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_UnicodeError\")]\n    pub static mut PyExc_UnicodeError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_UnicodeEncodeError\")]\n    pub static mut PyExc_UnicodeEncodeError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_UnicodeDecodeError\")]\n    pub static mut PyExc_UnicodeDecodeError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_UnicodeTranslateError\")]\n    pub static mut PyExc_UnicodeTranslateError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ValueError\")]\n    pub static mut PyExc_ValueError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ZeroDivisionError\")]\n    pub static mut PyExc_ZeroDivisionError: *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_BlockingIOError\")]\n    pub static mut PyExc_BlockingIOError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_BrokenPipeError\")]\n    pub static mut PyExc_BrokenPipeError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ChildProcessError\")]\n    pub static mut PyExc_ChildProcessError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ConnectionError\")]\n    pub static mut PyExc_ConnectionError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ConnectionAbortedError\")]\n    pub static mut PyExc_ConnectionAbortedError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ConnectionRefusedError\")]\n    pub static mut PyExc_ConnectionRefusedError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ConnectionResetError\")]\n    pub static mut PyExc_ConnectionResetError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_FileExistsError\")]\n    pub static mut PyExc_FileExistsError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_FileNotFoundError\")]\n    pub static mut PyExc_FileNotFoundError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_InterruptedError\")]\n    pub static mut PyExc_InterruptedError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_IsADirectoryError\")]\n    pub static mut PyExc_IsADirectoryError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_NotADirectoryError\")]\n    pub static mut PyExc_NotADirectoryError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_PermissionError\")]\n    pub static mut PyExc_PermissionError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ProcessLookupError\")]\n    pub static mut PyExc_ProcessLookupError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_TimeoutError\")]\n    pub static mut PyExc_TimeoutError: *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_OSError\")]\n    pub static mut PyExc_EnvironmentError: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_OSError\")]\n    pub static mut PyExc_IOError: *mut PyObject;\n    #[cfg(windows)]\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_OSError\")]\n    pub static mut PyExc_WindowsError: *mut PyObject;\n\n    pub static mut PyExc_RecursionErrorInst: *mut PyObject;\n\n    /* Predefined warning categories */\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_Warning\")]\n    pub static mut PyExc_Warning: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_UserWarning\")]\n    pub static mut PyExc_UserWarning: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_DeprecationWarning\")]\n    pub static mut PyExc_DeprecationWarning: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_PendingDeprecationWarning\")]\n    pub static mut PyExc_PendingDeprecationWarning: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_SyntaxWarning\")]\n    pub static mut PyExc_SyntaxWarning: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_RuntimeWarning\")]\n    pub static mut PyExc_RuntimeWarning: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_FutureWarning\")]\n    pub static mut PyExc_FutureWarning: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ImportWarning\")]\n    pub static mut PyExc_ImportWarning: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_UnicodeWarning\")]\n    pub static mut PyExc_UnicodeWarning: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_BytesWarning\")]\n    pub static mut PyExc_BytesWarning: *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_ResourceWarning\")]\n    pub static mut PyExc_ResourceWarning: *mut PyObject;\n    #[cfg(Py_3_10)]\n    #[cfg_attr(PyPy, link_name = \"PyPyExc_EncodingWarning\")]\n    pub static mut PyExc_EncodingWarning: *mut PyObject;\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_BadArgument\")]\n    pub fn PyErr_BadArgument() -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_NoMemory\")]\n    pub fn PyErr_NoMemory() -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_SetFromErrno\")]\n    pub fn PyErr_SetFromErrno(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_SetFromErrnoWithFilenameObject\")]\n    pub fn PyErr_SetFromErrnoWithFilenameObject(\n        arg1: *mut PyObject,\n        arg2: *mut PyObject,\n    ) -> *mut PyObject;\n    pub fn PyErr_SetFromErrnoWithFilenameObjects(\n        arg1: *mut PyObject,\n        arg2: *mut PyObject,\n        arg3: *mut PyObject,\n    ) -> *mut PyObject;\n    pub fn PyErr_SetFromErrnoWithFilename(\n        exc: *mut PyObject,\n        filename: *const c_char,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_Format\")]\n    pub fn PyErr_Format(exception: *mut PyObject, format: *const c_char, ...) -> *mut PyObject;\n    pub fn PyErr_SetImportErrorSubclass(\n        arg1: *mut PyObject,\n        arg2: *mut PyObject,\n        arg3: *mut PyObject,\n        arg4: *mut PyObject,\n    ) -> *mut PyObject;\n    pub fn PyErr_SetImportError(\n        arg1: *mut PyObject,\n        arg2: *mut PyObject,\n        arg3: *mut PyObject,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_BadInternalCall\")]\n    pub fn PyErr_BadInternalCall();\n    pub fn _PyErr_BadInternalCall(filename: *const c_char, lineno: c_int);\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_NewException\")]\n    pub fn PyErr_NewException(\n        name: *const c_char,\n        base: *mut PyObject,\n        dict: *mut PyObject,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_NewExceptionWithDoc\")]\n    pub fn PyErr_NewExceptionWithDoc(\n        name: *const c_char,\n        doc: *const c_char,\n        base: *mut PyObject,\n        dict: *mut PyObject,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_WriteUnraisable\")]\n    pub fn PyErr_WriteUnraisable(arg1: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_CheckSignals\")]\n    pub fn PyErr_CheckSignals() -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_SetInterrupt\")]\n    pub fn PyErr_SetInterrupt();\n    #[cfg(Py_3_10)]\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_SetInterruptEx\")]\n    pub fn PyErr_SetInterruptEx(signum: c_int);\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_SyntaxLocation\")]\n    pub fn PyErr_SyntaxLocation(filename: *const c_char, lineno: c_int);\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_SyntaxLocationEx\")]\n    pub fn PyErr_SyntaxLocationEx(filename: *const c_char, lineno: c_int, col_offset: c_int);\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_ProgramText\")]\n    pub fn PyErr_ProgramText(filename: *const c_char, lineno: c_int) -> *mut PyObject;\n    #[cfg(not(PyPy))]\n    pub fn PyUnicodeDecodeError_Create(\n        encoding: *const c_char,\n        object: *const c_char,\n        length: Py_ssize_t,\n        start: Py_ssize_t,\n        end: Py_ssize_t,\n        reason: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyUnicodeEncodeError_GetEncoding(arg1: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicodeDecodeError_GetEncoding(arg1: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicodeEncodeError_GetObject(arg1: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicodeDecodeError_GetObject(arg1: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicodeTranslateError_GetObject(arg1: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicodeEncodeError_GetStart(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int;\n    pub fn PyUnicodeDecodeError_GetStart(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int;\n    pub fn PyUnicodeTranslateError_GetStart(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int;\n    pub fn PyUnicodeEncodeError_SetStart(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int;\n    pub fn PyUnicodeDecodeError_SetStart(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int;\n    pub fn PyUnicodeTranslateError_SetStart(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int;\n    pub fn PyUnicodeEncodeError_GetEnd(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int;\n    pub fn PyUnicodeDecodeError_GetEnd(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int;\n    pub fn PyUnicodeTranslateError_GetEnd(arg1: *mut PyObject, arg2: *mut Py_ssize_t) -> c_int;\n    pub fn PyUnicodeEncodeError_SetEnd(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int;\n    pub fn PyUnicodeDecodeError_SetEnd(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int;\n    pub fn PyUnicodeTranslateError_SetEnd(arg1: *mut PyObject, arg2: Py_ssize_t) -> c_int;\n    pub fn PyUnicodeEncodeError_GetReason(arg1: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicodeDecodeError_GetReason(arg1: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicodeTranslateError_GetReason(arg1: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicodeEncodeError_SetReason(exc: *mut PyObject, reason: *const c_char) -> c_int;\n    pub fn PyUnicodeDecodeError_SetReason(exc: *mut PyObject, reason: *const c_char) -> c_int;\n    pub fn PyUnicodeTranslateError_SetReason(exc: *mut PyObject, reason: *const c_char) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/pyframe.rs",
    "content": "#[cfg(not(GraalPy))]\n#[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]\nuse crate::PyCodeObject;\nuse crate::PyFrameObject;\nuse std::ffi::c_int;\n\nextern_libpython! {\n    pub fn PyFrame_GetLineNumber(frame: *mut PyFrameObject) -> c_int;\n\n    #[cfg(not(GraalPy))]\n    #[cfg(any(Py_3_10, all(Py_3_9, not(Py_LIMITED_API))))]\n    pub fn PyFrame_GetCode(frame: *mut PyFrameObject) -> *mut PyCodeObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/pyhash.rs",
    "content": "#[cfg(not(any(Py_LIMITED_API, PyPy)))]\nuse crate::pyport::{Py_hash_t, Py_ssize_t};\n#[cfg(not(any(Py_LIMITED_API, PyPy)))]\nuse std::ffi::c_void;\n\nuse std::ffi::{c_int, c_ulong};\n\nextern_libpython! {\n    // skipped non-limited _Py_HashDouble\n    // skipped non-limited _Py_HashPointer\n    // skipped non-limited _Py_HashPointerRaw\n\n    #[cfg(not(any(Py_LIMITED_API, PyPy)))]\n    pub fn _Py_HashBytes(src: *const c_void, len: Py_ssize_t) -> Py_hash_t;\n}\n\npub const _PyHASH_MULTIPLIER: c_ulong = 1000003;\n\n// skipped _PyHASH_BITS\n\n// skipped non-limited _Py_HashSecret_t\n\n// skipped Py_HASH_CUTOFF\n\npub const Py_HASH_EXTERNAL: c_int = 0;\npub const Py_HASH_SIPHASH24: c_int = 1;\npub const Py_HASH_FNV: c_int = 2;\n#[cfg(Py_3_11)]\npub const Py_HASH_SIPHASH13: c_int = 3;\n\n// skipped Py_HASH_ALGORITHM\n"
  },
  {
    "path": "pyo3-ffi/src/pylifecycle.rs",
    "content": "use crate::pytypedefs::PyThreadState;\n\nuse libc::wchar_t;\nuse std::ffi::{c_char, c_int};\n\nextern_libpython! {\n    pub fn Py_Initialize();\n    pub fn Py_InitializeEx(arg1: c_int);\n    pub fn Py_Finalize();\n    pub fn Py_FinalizeEx() -> c_int;\n\n    #[cfg_attr(PyPy, link_name = \"PyPy_IsInitialized\")]\n    pub fn Py_IsInitialized() -> c_int;\n\n    pub fn Py_NewInterpreter() -> *mut PyThreadState;\n    pub fn Py_EndInterpreter(arg1: *mut PyThreadState);\n\n    #[cfg_attr(PyPy, link_name = \"PyPy_AtExit\")]\n    pub fn Py_AtExit(func: Option<extern \"C\" fn()>) -> c_int;\n\n    pub fn Py_Exit(arg1: c_int) -> !;\n\n    pub fn Py_Main(argc: c_int, argv: *mut *mut wchar_t) -> c_int;\n    pub fn Py_BytesMain(argc: c_int, argv: *mut *mut c_char) -> c_int;\n\n    #[cfg_attr(\n        Py_3_11,\n        deprecated(note = \"Deprecated since Python 3.11. Use `PyConfig.program_name` instead.\")\n    )]\n    pub fn Py_SetProgramName(arg1: *const wchar_t);\n    #[cfg_attr(PyPy, link_name = \"PyPy_GetProgramName\")]\n    #[cfg_attr(\n        Py_3_13,\n        deprecated(note = \"Deprecated since Python 3.13. Use `sys.executable` instead.\")\n    )]\n    pub fn Py_GetProgramName() -> *mut wchar_t;\n\n    #[cfg_attr(\n        Py_3_11,\n        deprecated(note = \"Deprecated since Python 3.11. Use `PyConfig.home` instead.\")\n    )]\n    pub fn Py_SetPythonHome(arg1: *const wchar_t);\n    #[cfg_attr(\n        Py_3_13,\n        deprecated(\n            note = \"Deprecated since Python 3.13. Use `PyConfig.home` or the value of the `PYTHONHOME` environment variable instead.\"\n        )\n    )]\n    pub fn Py_GetPythonHome() -> *mut wchar_t;\n    #[cfg_attr(\n        Py_3_13,\n        deprecated(note = \"Deprecated since Python 3.13. Use `sys.executable` instead.\")\n    )]\n    pub fn Py_GetProgramFullPath() -> *mut wchar_t;\n    #[cfg_attr(\n        Py_3_13,\n        deprecated(note = \"Deprecated since Python 3.13. Use `sys.prefix` instead.\")\n    )]\n    pub fn Py_GetPrefix() -> *mut wchar_t;\n    #[cfg_attr(\n        Py_3_13,\n        deprecated(note = \"Deprecated since Python 3.13. Use `sys.exec_prefix` instead.\")\n    )]\n    pub fn Py_GetExecPrefix() -> *mut wchar_t;\n    #[cfg_attr(\n        Py_3_13,\n        deprecated(note = \"Deprecated since Python 3.13. Use `sys.path` instead.\")\n    )]\n    pub fn Py_GetPath() -> *mut wchar_t;\n    #[cfg(not(Py_3_13))]\n    #[cfg_attr(\n        Py_3_11,\n        deprecated(note = \"Deprecated since Python 3.11. Use `sys.path` instead.\")\n    )]\n    pub fn Py_SetPath(arg1: *const wchar_t);\n\n    // skipped _Py_CheckPython3\n\n    #[cfg_attr(PyPy, link_name = \"PyPy_GetVersion\")]\n    pub fn Py_GetVersion() -> *const c_char;\n    pub fn Py_GetPlatform() -> *const c_char;\n    pub fn Py_GetCopyright() -> *const c_char;\n    pub fn Py_GetCompiler() -> *const c_char;\n    pub fn Py_GetBuildInfo() -> *const c_char;\n}\n\ntype PyOS_sighandler_t = unsafe extern \"C\" fn(arg1: c_int);\n\nextern_libpython! {\n    pub fn PyOS_getsig(arg1: c_int) -> PyOS_sighandler_t;\n    pub fn PyOS_setsig(arg1: c_int, arg2: PyOS_sighandler_t) -> PyOS_sighandler_t;\n\n    #[cfg(Py_3_11)]\n    pub static Py_Version: std::ffi::c_ulong;\n\n    #[cfg(Py_3_13)]\n    pub fn Py_IsFinalizing() -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/pymem.rs",
    "content": "use libc::size_t;\nuse std::ffi::c_void;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyMem_Malloc\")]\n    pub fn PyMem_Malloc(size: size_t) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyMem_Calloc\")]\n    pub fn PyMem_Calloc(nelem: size_t, elsize: size_t) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyMem_Realloc\")]\n    pub fn PyMem_Realloc(ptr: *mut c_void, new_size: size_t) -> *mut c_void;\n    #[cfg_attr(PyPy, link_name = \"PyPyMem_Free\")]\n    pub fn PyMem_Free(ptr: *mut c_void);\n}\n"
  },
  {
    "path": "pyo3-ffi/src/pyport.rs",
    "content": "// NB libc does not define this constant on all platforms, so we hard code it\n// like CPython does.\n// https://github.com/python/cpython/blob/d8b9011702443bb57579f8834f3effe58e290dfc/Include/pyport.h#L372\npub const INT_MAX: std::ffi::c_int = 2147483647;\n\npub type PY_UINT32_T = u32;\npub type PY_UINT64_T = u64;\n\npub type PY_INT32_T = i32;\npub type PY_INT64_T = i64;\n\npub type Py_uintptr_t = ::libc::uintptr_t;\npub type Py_intptr_t = ::libc::intptr_t;\npub type Py_ssize_t = ::libc::ssize_t;\n\npub type Py_hash_t = Py_ssize_t;\npub type Py_uhash_t = ::libc::size_t;\n\npub const PY_SSIZE_T_MIN: Py_ssize_t = Py_ssize_t::MIN;\npub const PY_SSIZE_T_MAX: Py_ssize_t = Py_ssize_t::MAX;\n\n#[cfg(target_endian = \"big\")]\npub const PY_BIG_ENDIAN: usize = 1;\n#[cfg(target_endian = \"big\")]\npub const PY_LITTLE_ENDIAN: usize = 0;\n\n#[cfg(target_endian = \"little\")]\npub const PY_BIG_ENDIAN: usize = 0;\n#[cfg(target_endian = \"little\")]\npub const PY_LITTLE_ENDIAN: usize = 1;\n"
  },
  {
    "path": "pyo3-ffi/src/pystate.rs",
    "content": "use crate::moduleobject::PyModuleDef;\nuse crate::object::PyObject;\nuse crate::pytypedefs::{PyInterpreterState, PyThreadState};\nuse std::ffi::c_int;\n\n#[cfg(any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_10))]\n#[cfg(not(PyPy))]\nuse crate::PyFrameObject;\n\n#[cfg(not(PyPy))]\nuse std::ffi::c_long;\n\npub const MAX_CO_EXTRA_USERS: c_int = 255;\n\nextern_libpython! {\n    #[cfg(not(PyPy))]\n    pub fn PyInterpreterState_New() -> *mut PyInterpreterState;\n    #[cfg(not(PyPy))]\n    pub fn PyInterpreterState_Clear(arg1: *mut PyInterpreterState);\n    #[cfg(not(PyPy))]\n    pub fn PyInterpreterState_Delete(arg1: *mut PyInterpreterState);\n\n    #[cfg(all(Py_3_9, not(PyPy)))]\n    pub fn PyInterpreterState_Get() -> *mut PyInterpreterState;\n\n    #[cfg(all(Py_3_8, not(PyPy)))]\n    pub fn PyInterpreterState_GetDict(arg1: *mut PyInterpreterState) -> *mut PyObject;\n\n    #[cfg(not(PyPy))]\n    pub fn PyInterpreterState_GetID(arg1: *mut PyInterpreterState) -> i64;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyState_AddModule\")]\n    pub fn PyState_AddModule(arg1: *mut PyObject, arg2: *mut PyModuleDef) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyState_RemoveModule\")]\n    pub fn PyState_RemoveModule(arg1: *mut PyModuleDef) -> c_int;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyState_FindModule\")]\n    pub fn PyState_FindModule(arg1: *mut PyModuleDef) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyThreadState_New\")]\n    pub fn PyThreadState_New(arg1: *mut PyInterpreterState) -> *mut PyThreadState;\n    #[cfg_attr(PyPy, link_name = \"PyPyThreadState_Clear\")]\n    pub fn PyThreadState_Clear(arg1: *mut PyThreadState);\n    #[cfg_attr(PyPy, link_name = \"PyPyThreadState_Delete\")]\n    pub fn PyThreadState_Delete(arg1: *mut PyThreadState);\n\n    #[cfg_attr(PyPy, link_name = \"PyPyThreadState_Get\")]\n    pub fn PyThreadState_Get() -> *mut PyThreadState;\n}\n\n#[inline]\npub unsafe fn PyThreadState_GET() -> *mut PyThreadState {\n    PyThreadState_Get()\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyThreadState_Swap\")]\n    pub fn PyThreadState_Swap(arg1: *mut PyThreadState) -> *mut PyThreadState;\n    #[cfg_attr(PyPy, link_name = \"PyPyThreadState_GetDict\")]\n    pub fn PyThreadState_GetDict() -> *mut PyObject;\n    #[cfg(not(PyPy))]\n    pub fn PyThreadState_SetAsyncExc(arg1: c_long, arg2: *mut PyObject) -> c_int;\n\n    #[cfg(any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_10))]\n    #[cfg(not(PyPy))]\n    pub fn PyThreadState_GetInterpreter(arg1: *mut PyThreadState) -> *mut PyInterpreterState;\n    #[cfg(any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_10))]\n    #[cfg(not(PyPy))]\n    pub fn PyThreadState_GetFrame(arg1: *mut PyThreadState) -> *mut PyFrameObject;\n    #[cfg(any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_10))]\n    #[cfg(not(PyPy))]\n    pub fn PyThreadState_GetID(arg1: *mut PyThreadState) -> i64;\n}\n\n#[repr(C)]\n#[derive(Copy, Clone, Debug, PartialEq, Eq)]\npub enum PyGILState_STATE {\n    PyGILState_LOCKED,\n    PyGILState_UNLOCKED,\n}\n\n#[cfg(not(any(Py_3_14, target_arch = \"wasm32\")))]\nstruct HangThread;\n\n#[cfg(not(any(Py_3_14, target_arch = \"wasm32\")))]\nimpl Drop for HangThread {\n    fn drop(&mut self) {\n        loop {\n            std::thread::park(); // Block forever.\n        }\n    }\n}\n\n// The PyGILState_Ensure function will call pthread_exit during interpreter shutdown,\n// which causes undefined behavior. Redirect to the \"safe\" version that hangs instead,\n// as Python 3.14 does.\n//\n// See https://github.com/rust-lang/rust/issues/135929\n\n// C-unwind only supported (and necessary) since 1.71. Python 3.14+ does not do\n// pthread_exit from PyGILState_Ensure (https://github.com/python/cpython/issues/87135).\nmod raw {\n    #[cfg(not(any(Py_3_14, target_arch = \"wasm32\")))]\n    extern_libpython! { \"C-unwind\" {\n        #[cfg_attr(PyPy, link_name = \"PyPyGILState_Ensure\")]\n        pub fn PyGILState_Ensure() -> super::PyGILState_STATE;\n    }}\n\n    #[cfg(any(Py_3_14, target_arch = \"wasm32\"))]\n    extern_libpython! {\n        #[cfg_attr(PyPy, link_name = \"PyPyGILState_Ensure\")]\n        pub fn PyGILState_Ensure() -> super::PyGILState_STATE;\n    }\n}\n\n#[cfg(not(any(Py_3_14, target_arch = \"wasm32\")))]\npub unsafe extern \"C\" fn PyGILState_Ensure() -> PyGILState_STATE {\n    let guard = HangThread;\n    // If `PyGILState_Ensure` calls `pthread_exit`, which it does on Python < 3.14\n    // when the interpreter is shutting down, this will cause a forced unwind.\n    // doing a forced unwind through a function with a Rust destructor is unspecified\n    // behavior.\n    //\n    // However, currently it runs the destructor, which will cause the thread to\n    // hang as it should.\n    //\n    // And if we don't catch the unwinding here, then one of our callers probably has a destructor,\n    // so it's unspecified behavior anyway, and on many configurations causes the process to abort.\n    //\n    // The alternative is for pyo3 to contain custom C or C++ code that catches the `pthread_exit`,\n    // but that's also annoying from a portability point of view.\n    //\n    // On Windows, `PyGILState_Ensure` calls `_endthreadex` instead, which AFAICT can't be caught\n    // and therefore will cause unsafety if there are pinned objects on the stack. AFAICT there's\n    // nothing we can do it other than waiting for Python 3.14 or not using Windows. At least,\n    // if there is nothing pinned on the stack, it won't cause the process to crash.\n    let ret: PyGILState_STATE = raw::PyGILState_Ensure();\n    std::mem::forget(guard);\n    ret\n}\n\n#[cfg(any(Py_3_14, target_arch = \"wasm32\"))]\npub use self::raw::PyGILState_Ensure;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyGILState_Release\")]\n    pub fn PyGILState_Release(arg1: PyGILState_STATE);\n    #[cfg(not(PyPy))]\n    pub fn PyGILState_GetThisThreadState() -> *mut PyThreadState;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/pystrtod.rs",
    "content": "use crate::object::PyObject;\nuse std::ffi::{c_char, c_double, c_int};\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyOS_string_to_double\")]\n    pub fn PyOS_string_to_double(\n        str: *const c_char,\n        endptr: *mut *mut c_char,\n        overflow_exception: *mut PyObject,\n    ) -> c_double;\n    #[cfg_attr(PyPy, link_name = \"PyPyOS_double_to_string\")]\n    pub fn PyOS_double_to_string(\n        val: c_double,\n        format_code: c_char,\n        precision: c_int,\n        flags: c_int,\n        _type: *mut c_int,\n    ) -> *mut c_char;\n}\n\n// skipped non-limited _Py_string_to_number_with_underscores\n// skipped non-limited _Py_parse_inf_or_nan\n\n/* PyOS_double_to_string's \"flags\" parameter can be set to 0 or more of: */\npub const Py_DTSF_SIGN: c_int = 0x01; /* always add the sign */\npub const Py_DTSF_ADD_DOT_0: c_int = 0x02; /* if the result is an integer add \".0\" */\npub const Py_DTSF_ALT: c_int = 0x04; /* \"alternate\" formatting. it's format_code specific */\n\n/* PyOS_double_to_string's \"type\", if non-NULL, will be set to one of: */\npub const Py_DTST_FINITE: c_int = 0;\npub const Py_DTST_INFINITE: c_int = 1;\npub const Py_DTST_NAN: c_int = 2;\n"
  },
  {
    "path": "pyo3-ffi/src/pythonrun.rs",
    "content": "use crate::object::*;\n#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))]\nuse libc::FILE;\n#[cfg(any(Py_LIMITED_API, not(Py_3_10), PyPy, GraalPy))]\nuse std::ffi::c_char;\nuse std::ffi::c_int;\n\nextern_libpython! {\n    #[cfg(any(all(Py_LIMITED_API, not(PyPy)), GraalPy))]\n    pub fn Py_CompileString(string: *const c_char, p: *const c_char, s: c_int) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_Print\")]\n    pub fn PyErr_Print();\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_PrintEx\")]\n    pub fn PyErr_PrintEx(arg1: c_int);\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_Display\")]\n    pub fn PyErr_Display(arg1: *mut PyObject, arg2: *mut PyObject, arg3: *mut PyObject);\n\n    #[cfg(Py_3_12)]\n    pub fn PyErr_DisplayException(exc: *mut PyObject);\n}\n\n#[inline]\n#[cfg(PyPy)]\npub unsafe fn Py_CompileString(string: *const c_char, p: *const c_char, s: c_int) -> *mut PyObject {\n    // PyPy's implementation of Py_CompileString always forwards to Py_CompileStringFlags; this\n    // is only available in the non-limited API and has a real definition for all versions in\n    // the cpython/ subdirectory.\n    #[cfg(Py_LIMITED_API)]\n    extern_libpython! {\n        #[link_name = \"PyPy_CompileStringFlags\"]\n        pub fn Py_CompileStringFlags(\n            string: *const c_char,\n            p: *const c_char,\n            s: c_int,\n            f: *mut std::ffi::c_void, // Actually *mut Py_CompilerFlags in the real definition\n        ) -> *mut PyObject;\n    }\n    #[cfg(not(Py_LIMITED_API))]\n    use crate::Py_CompileStringFlags;\n\n    Py_CompileStringFlags(string, p, s, std::ptr::null_mut())\n}\n\n// skipped PyOS_InputHook\n\npub const PYOS_STACK_MARGIN: c_int = 2048;\n\n// skipped PyOS_CheckStack under Microsoft C\n\n#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))]\nopaque_struct!(pub _mod);\n\n#[cfg(not(any(PyPy, Py_3_10)))]\nopaque_struct!(pub symtable);\n#[cfg(not(any(PyPy, Py_3_10)))]\nopaque_struct!(pub _node);\n\n#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))]\n#[cfg_attr(Py_3_9, deprecated(note = \"Python 3.9\"))]\n#[inline]\npub unsafe fn PyParser_SimpleParseString(s: *const c_char, b: c_int) -> *mut _node {\n    #[allow(deprecated)]\n    crate::PyParser_SimpleParseStringFlags(s, b, 0)\n}\n\n#[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))]\n#[cfg_attr(Py_3_9, deprecated(note = \"Python 3.9\"))]\n#[inline]\npub unsafe fn PyParser_SimpleParseFile(fp: *mut FILE, s: *const c_char, b: c_int) -> *mut _node {\n    #[allow(deprecated)]\n    crate::PyParser_SimpleParseFileFlags(fp, s, b, 0)\n}\n\nextern_libpython! {\n    #[cfg(not(any(PyPy, Py_3_10)))]\n    pub fn Py_SymtableString(\n        str: *const c_char,\n        filename: *const c_char,\n        start: c_int,\n    ) -> *mut symtable;\n    #[cfg(not(any(PyPy, Py_LIMITED_API, Py_3_10)))]\n    pub fn Py_SymtableStringObject(\n        str: *const c_char,\n        filename: *mut PyObject,\n        start: c_int,\n    ) -> *mut symtable;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/pytypedefs.rs",
    "content": "// NB: unlike C, we do not need to forward declare structs in Rust.\n// So we only define opaque structs for those which do not have public structure.\n\n// PyModuleDef\n// PyModuleDef_Slot\n// PyMethodDef\n// PyGetSetDef\n// PyMemberDef\n\n// PyObject\n// PyLongObject\n// PyTypeObject\nopaque_struct!(pub PyCodeObject);\nopaque_struct!(pub PyFrameObject);\n\nopaque_struct!(pub PyThreadState);\nopaque_struct!(pub PyInterpreterState);\n"
  },
  {
    "path": "pyo3-ffi/src/rangeobject.rs",
    "content": "use crate::object::*;\nuse std::ffi::c_int;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyRange_Type\")]\n    pub static mut PyRange_Type: PyTypeObject;\n    pub static mut PyRangeIter_Type: PyTypeObject;\n    pub static mut PyLongRangeIter_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyRange_Check(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyRange_Type) as c_int\n}\n"
  },
  {
    "path": "pyo3-ffi/src/refcount.rs",
    "content": "use crate::pyport::Py_ssize_t;\nuse crate::PyObject;\n#[cfg(all(not(Py_LIMITED_API), py_sys_config = \"Py_REF_DEBUG\"))]\nuse std::ffi::c_char;\n#[cfg(any(Py_3_12, all(py_sys_config = \"Py_REF_DEBUG\", not(Py_LIMITED_API))))]\nuse std::ffi::c_int;\n#[cfg(all(Py_3_14, any(not(Py_GIL_DISABLED), target_pointer_width = \"32\")))]\nuse std::ffi::c_long;\n#[cfg(any(Py_GIL_DISABLED, all(Py_3_12, not(Py_3_14))))]\nuse std::ffi::c_uint;\n#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]\nuse std::ffi::c_ulong;\nuse std::ptr;\n#[cfg(Py_GIL_DISABLED)]\nuse std::sync::atomic::Ordering::Relaxed;\n\n#[cfg(all(Py_3_14, not(Py_3_15)))]\nconst _Py_STATICALLY_ALLOCATED_FLAG: c_int = 1 << 7;\n#[cfg(Py_3_15)]\npub(crate) const _Py_STATICALLY_ALLOCATED_FLAG: c_int = 1 << 2;\n\n#[cfg(all(Py_3_12, not(Py_3_14)))]\nconst _Py_IMMORTAL_REFCNT: Py_ssize_t = {\n    if cfg!(target_pointer_width = \"64\") {\n        c_uint::MAX as Py_ssize_t\n    } else {\n        // for 32-bit systems, use the lower 30 bits (see comment in CPython's object.h)\n        (c_uint::MAX >> 2) as Py_ssize_t\n    }\n};\n\n// comments in Python.h about the choices for these constants\n\n#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]\nconst _Py_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = {\n    if cfg!(target_pointer_width = \"64\") {\n        ((3 as c_ulong) << (30 as c_ulong)) as Py_ssize_t\n    } else {\n        ((5 as c_long) << (28 as c_long)) as Py_ssize_t\n    }\n};\n\n#[cfg(all(Py_3_14, not(Py_GIL_DISABLED)))]\nconst _Py_STATIC_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = {\n    if cfg!(target_pointer_width = \"64\") {\n        _Py_IMMORTAL_INITIAL_REFCNT\n            | ((_Py_STATICALLY_ALLOCATED_FLAG as Py_ssize_t) << (32 as Py_ssize_t))\n    } else {\n        ((7 as c_long) << (28 as c_long)) as Py_ssize_t\n    }\n};\n\n#[cfg(all(Py_3_14, target_pointer_width = \"32\"))]\nconst _Py_IMMORTAL_MINIMUM_REFCNT: Py_ssize_t = ((1 as c_long) << (30 as c_long)) as Py_ssize_t;\n\n#[cfg(all(Py_3_14, target_pointer_width = \"32\"))]\nconst _Py_STATIC_IMMORTAL_MINIMUM_REFCNT: Py_ssize_t =\n    ((6 as c_long) << (28 as c_long)) as Py_ssize_t;\n\n#[cfg(all(Py_3_14, Py_GIL_DISABLED))]\nconst _Py_IMMORTAL_INITIAL_REFCNT: Py_ssize_t = c_uint::MAX as Py_ssize_t;\n\n#[cfg(Py_GIL_DISABLED)]\npub(crate) const _Py_IMMORTAL_REFCNT_LOCAL: u32 = u32::MAX;\n\n#[cfg(Py_GIL_DISABLED)]\nconst _Py_REF_SHARED_SHIFT: isize = 2;\n// skipped private _Py_REF_SHARED_FLAG_MASK\n\n// skipped private _Py_REF_SHARED_INIT\n// skipped private _Py_REF_MAYBE_WEAKREF\n// skipped private _Py_REF_QUEUED\n// skipped private _Py_REF_MERGED\n\n// skipped private _Py_REF_SHARED\n\nextern_libpython! {\n    #[cfg(all(Py_3_14, Py_LIMITED_API))]\n    pub fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t;\n}\n\n#[cfg(not(all(Py_3_14, Py_LIMITED_API)))]\n#[inline]\npub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {\n    #[cfg(Py_GIL_DISABLED)]\n    {\n        let local = (*ob).ob_ref_local.load(Relaxed);\n        if local == _Py_IMMORTAL_REFCNT_LOCAL {\n            #[cfg(not(Py_3_14))]\n            return _Py_IMMORTAL_REFCNT;\n            #[cfg(Py_3_14)]\n            return _Py_IMMORTAL_INITIAL_REFCNT;\n        }\n        let shared = (*ob).ob_ref_shared.load(Relaxed);\n        local as Py_ssize_t + Py_ssize_t::from(shared >> _Py_REF_SHARED_SHIFT)\n    }\n\n    #[cfg(all(Py_LIMITED_API, Py_3_14))]\n    {\n        Py_REFCNT(ob)\n    }\n\n    #[cfg(all(not(Py_GIL_DISABLED), not(all(Py_LIMITED_API, Py_3_14)), Py_3_12))]\n    {\n        (*ob).ob_refcnt.ob_refcnt\n    }\n\n    #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), not(GraalPy)))]\n    {\n        (*ob).ob_refcnt\n    }\n\n    #[cfg(all(not(Py_GIL_DISABLED), not(Py_3_12), GraalPy))]\n    {\n        _Py_REFCNT(ob)\n    }\n}\n\n#[cfg(Py_3_12)]\n#[inline(always)]\nunsafe fn _Py_IsImmortal(op: *mut PyObject) -> c_int {\n    #[cfg(all(target_pointer_width = \"64\", not(Py_GIL_DISABLED)))]\n    {\n        (((*op).ob_refcnt.ob_refcnt as crate::PY_INT32_T) < 0) as c_int\n    }\n\n    #[cfg(all(target_pointer_width = \"32\", not(Py_GIL_DISABLED)))]\n    {\n        #[cfg(not(Py_3_14))]\n        {\n            ((*op).ob_refcnt.ob_refcnt == _Py_IMMORTAL_REFCNT) as c_int\n        }\n\n        #[cfg(Py_3_14)]\n        {\n            ((*op).ob_refcnt.ob_refcnt >= _Py_IMMORTAL_MINIMUM_REFCNT) as c_int\n        }\n    }\n\n    #[cfg(Py_GIL_DISABLED)]\n    {\n        ((*op).ob_ref_local.load(Relaxed) == _Py_IMMORTAL_REFCNT_LOCAL) as c_int\n    }\n}\n\n// skipped _Py_IsStaticImmortal\n\n// TODO: Py_SET_REFCNT\n\nextern_libpython! {\n    #[cfg(all(py_sys_config = \"Py_REF_DEBUG\", not(Py_LIMITED_API)))]\n    fn _Py_NegativeRefcount(filename: *const c_char, lineno: c_int, op: *mut PyObject);\n    #[cfg(all(Py_3_12, py_sys_config = \"Py_REF_DEBUG\", not(Py_LIMITED_API)))]\n    fn _Py_INCREF_IncRefTotal();\n    #[cfg(all(Py_3_12, py_sys_config = \"Py_REF_DEBUG\", not(Py_LIMITED_API)))]\n    fn _Py_DECREF_DecRefTotal();\n\n    #[cfg_attr(PyPy, link_name = \"_PyPy_Dealloc\")]\n    fn _Py_Dealloc(arg1: *mut PyObject);\n\n    #[cfg_attr(PyPy, link_name = \"PyPy_IncRef\")]\n    #[cfg_attr(GraalPy, link_name = \"_Py_IncRef\")]\n    pub fn Py_IncRef(o: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPy_DecRef\")]\n    #[cfg_attr(GraalPy, link_name = \"_Py_DecRef\")]\n    pub fn Py_DecRef(o: *mut PyObject);\n\n    #[cfg(all(Py_3_10, not(PyPy)))]\n    fn _Py_IncRef(o: *mut PyObject);\n    #[cfg(all(Py_3_10, not(PyPy)))]\n    fn _Py_DecRef(o: *mut PyObject);\n\n    #[cfg(GraalPy)]\n    fn _Py_REFCNT(arg1: *const PyObject) -> Py_ssize_t;\n}\n\n#[inline(always)]\npub unsafe fn Py_INCREF(op: *mut PyObject) {\n    // On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting\n    // TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance.\n    #[cfg(any(\n        Py_GIL_DISABLED,\n        Py_LIMITED_API,\n        py_sys_config = \"Py_REF_DEBUG\",\n        GraalPy\n    ))]\n    {\n        // _Py_IncRef was added to the ABI in 3.10; skips null checks\n        #[cfg(all(Py_3_10, not(PyPy)))]\n        {\n            _Py_IncRef(op);\n        }\n\n        #[cfg(any(not(Py_3_10), PyPy))]\n        {\n            Py_IncRef(op);\n        }\n    }\n\n    // version-specific builds are allowed to directly manipulate the reference count\n    #[cfg(not(any(\n        Py_GIL_DISABLED,\n        Py_LIMITED_API,\n        py_sys_config = \"Py_REF_DEBUG\",\n        GraalPy\n    )))]\n    {\n        #[cfg(all(Py_3_14, target_pointer_width = \"64\"))]\n        {\n            let cur_refcnt = (*op).ob_refcnt.ob_refcnt;\n            if (cur_refcnt as i32) < 0 {\n                return;\n            }\n            (*op).ob_refcnt.ob_refcnt = cur_refcnt.wrapping_add(1);\n        }\n\n        #[cfg(all(Py_3_12, not(Py_3_14), target_pointer_width = \"64\"))]\n        {\n            let cur_refcnt = (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN];\n            let new_refcnt = cur_refcnt.wrapping_add(1);\n            if new_refcnt == 0 {\n                return;\n            }\n            (*op).ob_refcnt.ob_refcnt_split[crate::PY_BIG_ENDIAN] = new_refcnt;\n        }\n\n        #[cfg(all(Py_3_12, target_pointer_width = \"32\"))]\n        {\n            if _Py_IsImmortal(op) != 0 {\n                return;\n            }\n            (*op).ob_refcnt.ob_refcnt += 1\n        }\n\n        #[cfg(not(Py_3_12))]\n        {\n            (*op).ob_refcnt += 1\n        }\n\n        // Skipped _Py_INCREF_STAT_INC - if anyone wants this, please file an issue\n        // or submit a PR supporting Py_STATS build option and pystats.h\n    }\n}\n\n// skipped _Py_DecRefShared\n// skipped _Py_DecRefSharedDebug\n// skipped _Py_MergeZeroLocalRefcount\n\n#[inline(always)]\n#[cfg_attr(\n    all(py_sys_config = \"Py_REF_DEBUG\", Py_3_12, not(Py_LIMITED_API)),\n    track_caller\n)]\npub unsafe fn Py_DECREF(op: *mut PyObject) {\n    // On limited API, the free-threaded build, or with refcount debugging, let the interpreter do refcounting\n    // On 3.12+ we implement refcount debugging to get better assertion locations on negative refcounts\n    // TODO: reimplement the logic in the header in the free-threaded build, for a little bit of performance.\n    #[cfg(any(\n        Py_GIL_DISABLED,\n        Py_LIMITED_API,\n        all(py_sys_config = \"Py_REF_DEBUG\", not(Py_3_12)),\n        GraalPy\n    ))]\n    {\n        // _Py_DecRef was added to the ABI in 3.10; skips null checks\n        #[cfg(all(Py_3_10, not(PyPy)))]\n        {\n            _Py_DecRef(op);\n        }\n\n        #[cfg(any(not(Py_3_10), PyPy))]\n        {\n            Py_DecRef(op);\n        }\n    }\n\n    #[cfg(not(any(\n        Py_GIL_DISABLED,\n        Py_LIMITED_API,\n        all(py_sys_config = \"Py_REF_DEBUG\", not(Py_3_12)),\n        GraalPy\n    )))]\n    {\n        #[cfg(Py_3_12)]\n        if _Py_IsImmortal(op) != 0 {\n            return;\n        }\n\n        // Skipped _Py_DECREF_STAT_INC - if anyone needs this, please file an issue\n        // or submit a PR supporting Py_STATS build option and pystats.h\n\n        #[cfg(py_sys_config = \"Py_REF_DEBUG\")]\n        _Py_DECREF_DecRefTotal();\n\n        #[cfg(Py_3_12)]\n        {\n            (*op).ob_refcnt.ob_refcnt -= 1;\n\n            #[cfg(py_sys_config = \"Py_REF_DEBUG\")]\n            if (*op).ob_refcnt.ob_refcnt < 0 {\n                let location = std::panic::Location::caller();\n                let filename = std::ffi::CString::new(location.file()).unwrap();\n                _Py_NegativeRefcount(filename.as_ptr(), location.line() as i32, op);\n            }\n\n            if (*op).ob_refcnt.ob_refcnt == 0 {\n                _Py_Dealloc(op);\n            }\n        }\n\n        #[cfg(not(Py_3_12))]\n        {\n            (*op).ob_refcnt -= 1;\n\n            if (*op).ob_refcnt == 0 {\n                _Py_Dealloc(op);\n            }\n        }\n    }\n}\n\n#[inline]\npub unsafe fn Py_CLEAR(op: *mut *mut PyObject) {\n    let tmp = *op;\n    if !tmp.is_null() {\n        *op = ptr::null_mut();\n        Py_DECREF(tmp);\n    }\n}\n\n#[inline]\npub unsafe fn Py_XINCREF(op: *mut PyObject) {\n    if !op.is_null() {\n        Py_INCREF(op)\n    }\n}\n\n#[inline]\npub unsafe fn Py_XDECREF(op: *mut PyObject) {\n    if !op.is_null() {\n        Py_DECREF(op)\n    }\n}\n\nextern_libpython! {\n    #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]\n    #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]\n    pub fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject;\n    #[cfg(all(Py_3_10, Py_LIMITED_API, not(PyPy)))]\n    #[cfg_attr(docsrs, doc(cfg(Py_3_10)))]\n    pub fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject;\n}\n\n// macro _Py_NewRef not public; reimplemented directly inside Py_NewRef here\n// macro _Py_XNewRef not public; reimplemented directly inside Py_XNewRef here\n\n#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]\n#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]\n#[inline]\npub unsafe fn Py_NewRef(obj: *mut PyObject) -> *mut PyObject {\n    Py_INCREF(obj);\n    obj\n}\n\n#[cfg(all(Py_3_10, any(not(Py_LIMITED_API), PyPy)))]\n#[cfg_attr(docsrs, doc(cfg(Py_3_10)))]\n#[inline]\npub unsafe fn Py_XNewRef(obj: *mut PyObject) -> *mut PyObject {\n    Py_XINCREF(obj);\n    obj\n}\n"
  },
  {
    "path": "pyo3-ffi/src/setobject.rs",
    "content": "use crate::object::*;\n#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\nuse crate::pyport::Py_hash_t;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::c_int;\n\npub const PySet_MINSIZE: usize = 8;\n\n#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n#[repr(C)]\n#[derive(Debug)]\npub struct setentry {\n    pub key: *mut PyObject,\n    pub hash: Py_hash_t,\n}\n\n#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n#[repr(C)]\n#[derive(Debug)]\npub struct PySetObject {\n    pub ob_base: PyObject,\n    pub fill: Py_ssize_t,\n    pub used: Py_ssize_t,\n    pub mask: Py_ssize_t,\n    pub table: *mut setentry,\n    pub hash: Py_hash_t,\n    pub finger: Py_ssize_t,\n    pub smalltable: [setentry; PySet_MINSIZE],\n    pub weakreflist: *mut PyObject,\n}\n\n// skipped\n#[inline]\n#[cfg(all(not(any(PyPy, GraalPy)), not(Py_LIMITED_API)))]\npub unsafe fn PySet_GET_SIZE(so: *mut PyObject) -> Py_ssize_t {\n    debug_assert_eq!(PyAnySet_Check(so), 1);\n    let so = so.cast::<PySetObject>();\n    (*so).used\n}\n\n// skipped _PySet_Dummy\n\nextern_libpython! {\n    #[cfg(not(Py_LIMITED_API))]\n    #[cfg_attr(PyPy, link_name = \"_PyPySet_NextEntry\")]\n    pub fn _PySet_NextEntry(\n        set: *mut PyObject,\n        pos: *mut Py_ssize_t,\n        key: *mut *mut PyObject,\n        hash: *mut super::Py_hash_t,\n    ) -> c_int;\n\n    // skipped non-limited _PySet_Update\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPySet_Type\")]\n    pub static mut PySet_Type: PyTypeObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyFrozenSet_Type\")]\n    pub static mut PyFrozenSet_Type: PyTypeObject;\n    pub static mut PySetIter_Type: PyTypeObject;\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPySet_New\")]\n    pub fn PySet_New(arg1: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyFrozenSet_New\")]\n    pub fn PyFrozenSet_New(arg1: *mut PyObject) -> *mut PyObject;\n\n    #[cfg_attr(PyPy, link_name = \"PyPySet_Add\")]\n    pub fn PySet_Add(set: *mut PyObject, key: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPySet_Clear\")]\n    pub fn PySet_Clear(set: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPySet_Contains\")]\n    pub fn PySet_Contains(anyset: *mut PyObject, key: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPySet_Discard\")]\n    pub fn PySet_Discard(set: *mut PyObject, key: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPySet_Pop\")]\n    pub fn PySet_Pop(set: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPySet_Size\")]\n    pub fn PySet_Size(anyset: *mut PyObject) -> Py_ssize_t;\n\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyFrozenSet_CheckExact\"]\n    pub fn PyFrozenSet_CheckExact(ob: *mut PyObject) -> c_int;\n}\n\n#[inline]\n#[cfg(not(any(PyPy, GraalPy)))]\npub unsafe fn PyFrozenSet_CheckExact(ob: *mut PyObject) -> c_int {\n    (Py_TYPE(ob) == &raw mut PyFrozenSet_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyFrozenSet_Check\"]\n    pub fn PyFrozenSet_Check(ob: *mut PyObject) -> c_int;\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyFrozenSet_Check(ob: *mut PyObject) -> c_int {\n    (Py_TYPE(ob) == &raw mut PyFrozenSet_Type\n        || PyType_IsSubtype(Py_TYPE(ob), &raw mut PyFrozenSet_Type) != 0) as c_int\n}\n\nextern_libpython! {\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyAnySet_CheckExact\"]\n    pub fn PyAnySet_CheckExact(ob: *mut PyObject) -> c_int;\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyAnySet_CheckExact(ob: *mut PyObject) -> c_int {\n    (Py_TYPE(ob) == &raw mut PySet_Type || Py_TYPE(ob) == &raw mut PyFrozenSet_Type) as c_int\n}\n\n#[inline]\npub unsafe fn PyAnySet_Check(ob: *mut PyObject) -> c_int {\n    (PyAnySet_CheckExact(ob) != 0\n        || PyType_IsSubtype(Py_TYPE(ob), &raw mut PySet_Type) != 0\n        || PyType_IsSubtype(Py_TYPE(ob), &raw mut PyFrozenSet_Type) != 0) as c_int\n}\n\n#[inline]\n#[cfg(Py_3_10)]\npub unsafe fn PySet_CheckExact(op: *mut PyObject) -> c_int {\n    crate::Py_IS_TYPE(op, &raw mut PySet_Type)\n}\n\nextern_libpython! {\n    #[cfg(PyPy)]\n    #[link_name = \"PyPySet_Check\"]\n    pub fn PySet_Check(ob: *mut PyObject) -> c_int;\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PySet_Check(ob: *mut PyObject) -> c_int {\n    (Py_TYPE(ob) == &raw mut PySet_Type || PyType_IsSubtype(Py_TYPE(ob), &raw mut PySet_Type) != 0)\n        as c_int\n}\n"
  },
  {
    "path": "pyo3-ffi/src/sliceobject.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::c_int;\n\nextern_libpython! {\n    #[cfg(not(GraalPy))]\n    #[cfg_attr(PyPy, link_name = \"_PyPy_EllipsisObject\")]\n    static mut _Py_EllipsisObject: PyObject;\n\n    #[cfg(GraalPy)]\n    static mut _Py_EllipsisObjectReference: *mut PyObject;\n}\n\n#[inline]\npub unsafe fn Py_Ellipsis() -> *mut PyObject {\n    #[cfg(not(GraalPy))]\n    return &raw mut _Py_EllipsisObject;\n    #[cfg(GraalPy)]\n    return _Py_EllipsisObjectReference;\n}\n\n#[cfg(not(Py_LIMITED_API))]\n#[repr(C)]\npub struct PySliceObject {\n    pub ob_base: PyObject,\n    #[cfg(not(GraalPy))]\n    pub start: *mut PyObject,\n    #[cfg(not(GraalPy))]\n    pub stop: *mut PyObject,\n    #[cfg(not(GraalPy))]\n    pub step: *mut PyObject,\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPySlice_Type\")]\n    pub static mut PySlice_Type: PyTypeObject;\n    pub static mut PyEllipsis_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PySlice_Check(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PySlice_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPySlice_New\")]\n    pub fn PySlice_New(\n        start: *mut PyObject,\n        stop: *mut PyObject,\n        step: *mut PyObject,\n    ) -> *mut PyObject;\n\n    // skipped non-limited _PySlice_FromIndices\n    // skipped non-limited _PySlice_GetLongIndices\n\n    #[cfg_attr(PyPy, link_name = \"PyPySlice_GetIndices\")]\n    pub fn PySlice_GetIndices(\n        r: *mut PyObject,\n        length: Py_ssize_t,\n        start: *mut Py_ssize_t,\n        stop: *mut Py_ssize_t,\n        step: *mut Py_ssize_t,\n    ) -> c_int;\n}\n\n#[inline]\npub unsafe fn PySlice_GetIndicesEx(\n    slice: *mut PyObject,\n    length: Py_ssize_t,\n    start: *mut Py_ssize_t,\n    stop: *mut Py_ssize_t,\n    step: *mut Py_ssize_t,\n    slicelength: *mut Py_ssize_t,\n) -> c_int {\n    if PySlice_Unpack(slice, start, stop, step) < 0 {\n        *slicelength = 0;\n        -1\n    } else {\n        *slicelength = PySlice_AdjustIndices(length, start, stop, *step);\n        0\n    }\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPySlice_Unpack\")]\n    pub fn PySlice_Unpack(\n        slice: *mut PyObject,\n        start: *mut Py_ssize_t,\n        stop: *mut Py_ssize_t,\n        step: *mut Py_ssize_t,\n    ) -> c_int;\n\n    #[cfg_attr(PyPy, link_name = \"PyPySlice_AdjustIndices\")]\n    pub fn PySlice_AdjustIndices(\n        length: Py_ssize_t,\n        start: *mut Py_ssize_t,\n        stop: *mut Py_ssize_t,\n        step: Py_ssize_t,\n    ) -> Py_ssize_t;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/structmember.rs",
    "content": "use std::ffi::c_int;\n\npub use crate::PyMemberDef;\n\npub use crate::Py_T_BOOL as T_BOOL;\npub use crate::Py_T_BYTE as T_BYTE;\npub use crate::Py_T_CHAR as T_CHAR;\npub use crate::Py_T_DOUBLE as T_DOUBLE;\npub use crate::Py_T_FLOAT as T_FLOAT;\npub use crate::Py_T_INT as T_INT;\npub use crate::Py_T_LONG as T_LONG;\npub use crate::Py_T_LONGLONG as T_LONGLONG;\npub use crate::Py_T_OBJECT_EX as T_OBJECT_EX;\npub use crate::Py_T_SHORT as T_SHORT;\npub use crate::Py_T_STRING as T_STRING;\npub use crate::Py_T_STRING_INPLACE as T_STRING_INPLACE;\npub use crate::Py_T_UBYTE as T_UBYTE;\npub use crate::Py_T_UINT as T_UINT;\npub use crate::Py_T_ULONG as T_ULONG;\npub use crate::Py_T_ULONGLONG as T_ULONGLONG;\npub use crate::Py_T_USHORT as T_USHORT;\n#[allow(deprecated)]\npub use crate::_Py_T_OBJECT as T_OBJECT;\n\npub use crate::Py_T_PYSSIZET as T_PYSSIZET;\n#[allow(deprecated)]\npub use crate::_Py_T_NONE as T_NONE;\n\n/* Flags */\npub use crate::Py_READONLY as READONLY;\npub const READ_RESTRICTED: c_int = 2;\npub const PY_WRITE_RESTRICTED: c_int = 4;\npub const RESTRICTED: c_int = READ_RESTRICTED | PY_WRITE_RESTRICTED;\n"
  },
  {
    "path": "pyo3-ffi/src/structseq.rs",
    "content": "use crate::object::{PyObject, PyTypeObject};\n#[cfg(not(PyPy))]\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::{c_char, c_int};\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyStructSequence_Field {\n    pub name: *const c_char,\n    pub doc: *const c_char,\n}\n\n#[repr(C)]\n#[derive(Copy, Clone)]\npub struct PyStructSequence_Desc {\n    pub name: *const c_char,\n    pub doc: *const c_char,\n    pub fields: *mut PyStructSequence_Field,\n    pub n_in_sequence: c_int,\n}\n\n// skipped PyStructSequence_UnnamedField;\n\nextern_libpython! {\n    #[cfg(not(Py_LIMITED_API))]\n    #[cfg_attr(PyPy, link_name = \"PyPyStructSequence_InitType\")]\n    pub fn PyStructSequence_InitType(_type: *mut PyTypeObject, desc: *mut PyStructSequence_Desc);\n\n    #[cfg(not(Py_LIMITED_API))]\n    #[cfg_attr(PyPy, link_name = \"PyPyStructSequence_InitType2\")]\n    pub fn PyStructSequence_InitType2(\n        _type: *mut PyTypeObject,\n        desc: *mut PyStructSequence_Desc,\n    ) -> c_int;\n\n    #[cfg(not(PyPy))]\n    pub fn PyStructSequence_NewType(desc: *mut PyStructSequence_Desc) -> *mut PyTypeObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyStructSequence_New\")]\n    pub fn PyStructSequence_New(_type: *mut PyTypeObject) -> *mut PyObject;\n}\n\n#[cfg(not(Py_LIMITED_API))]\npub type PyStructSequence = crate::PyTupleObject;\n\n#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n#[inline]\npub unsafe fn PyStructSequence_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) {\n    crate::PyTuple_SET_ITEM(op, i, v)\n}\n\n#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n#[inline]\npub unsafe fn PyStructSequence_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject {\n    crate::PyTuple_GET_ITEM(op, i)\n}\n\nextern_libpython! {\n    #[cfg(not(PyPy))]\n    pub fn PyStructSequence_SetItem(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject);\n\n    #[cfg(not(PyPy))]\n    pub fn PyStructSequence_GetItem(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/sysmodule.rs",
    "content": "use crate::object::PyObject;\nuse libc::wchar_t;\nuse std::ffi::{c_char, c_int};\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPySys_GetObject\")]\n    pub fn PySys_GetObject(arg1: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPySys_SetObject\")]\n    pub fn PySys_SetObject(arg1: *const c_char, arg2: *mut PyObject) -> c_int;\n\n    #[cfg_attr(\n        Py_3_11,\n        deprecated(\n            note = \"Deprecated in Python 3.11, use `PyConfig.argv` and `PyConfig.parse_argv` instead\"\n        )\n    )]\n    pub fn PySys_SetArgv(arg1: c_int, arg2: *mut *mut wchar_t);\n    #[cfg_attr(\n        Py_3_11,\n        deprecated(\n            note = \"Deprecated in Python 3.11, use `PyConfig.argv` and `PyConfig.parse_argv` instead\"\n        )\n    )]\n    pub fn PySys_SetArgvEx(arg1: c_int, arg2: *mut *mut wchar_t, arg3: c_int);\n    pub fn PySys_SetPath(arg1: *const wchar_t);\n\n    #[cfg_attr(PyPy, link_name = \"PyPySys_WriteStdout\")]\n    pub fn PySys_WriteStdout(format: *const c_char, ...);\n    #[cfg_attr(PyPy, link_name = \"PyPySys_WriteStderr\")]\n    pub fn PySys_WriteStderr(format: *const c_char, ...);\n    pub fn PySys_FormatStdout(format: *const c_char, ...);\n    pub fn PySys_FormatStderr(format: *const c_char, ...);\n\n    #[cfg_attr(\n        Py_3_13,\n        deprecated(\n            note = \"Deprecated since Python 3.13. Clear sys.warnoptions and warnings.filters instead.\"\n        )\n    )]\n    pub fn PySys_ResetWarnOptions();\n    #[cfg_attr(Py_3_11, deprecated(note = \"Python 3.11\"))]\n    pub fn PySys_AddWarnOption(arg1: *const wchar_t);\n    #[cfg_attr(Py_3_11, deprecated(note = \"Python 3.11\"))]\n    pub fn PySys_AddWarnOptionUnicode(arg1: *mut PyObject);\n    #[cfg_attr(Py_3_11, deprecated(note = \"Python 3.11\"))]\n    pub fn PySys_HasWarnOptions() -> c_int;\n\n    pub fn PySys_AddXOption(arg1: *const wchar_t);\n    pub fn PySys_GetXOptions() -> *mut PyObject;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/traceback.rs",
    "content": "use crate::object::*;\nuse std::ffi::c_int;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyTraceBack_Here\")]\n    pub fn PyTraceBack_Here(arg1: *mut crate::PyFrameObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyTraceBack_Print\")]\n    pub fn PyTraceBack_Print(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyTraceBack_Type\")]\n    pub static mut PyTraceBack_Type: PyTypeObject;\n\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyTraceBack_Check\"]\n    pub fn PyTraceBack_Check(op: *mut PyObject) -> c_int;\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyTraceBack_Check(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyTraceBack_Type) as c_int\n}\n"
  },
  {
    "path": "pyo3-ffi/src/tupleobject.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::c_int;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyTuple_Type\")]\n    pub static mut PyTuple_Type: PyTypeObject;\n    pub static mut PyTupleIter_Type: PyTypeObject;\n}\n\n#[inline]\npub unsafe fn PyTuple_Check(op: *mut PyObject) -> c_int {\n    PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TUPLE_SUBCLASS)\n}\n\n#[inline]\npub unsafe fn PyTuple_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyTuple_Type) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyTuple_New\")]\n    pub fn PyTuple_New(size: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyTuple_Size\")]\n    pub fn PyTuple_Size(arg1: *mut PyObject) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyTuple_GetItem\")]\n    pub fn PyTuple_GetItem(arg1: *mut PyObject, arg2: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyTuple_SetItem\")]\n    pub fn PyTuple_SetItem(arg1: *mut PyObject, arg2: Py_ssize_t, arg3: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyTuple_GetSlice\")]\n    pub fn PyTuple_GetSlice(\n        arg1: *mut PyObject,\n        arg2: Py_ssize_t,\n        arg3: Py_ssize_t,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyTuple_Pack\")]\n    pub fn PyTuple_Pack(arg1: Py_ssize_t, ...) -> *mut PyObject;\n    #[cfg(not(Py_3_9))]\n    pub fn PyTuple_ClearFreeList() -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/typeslots.rs",
    "content": "use std::ffi::c_int;\n\npub const Py_bf_getbuffer: c_int = 1;\npub const Py_bf_releasebuffer: c_int = 2;\npub const Py_mp_ass_subscript: c_int = 3;\npub const Py_mp_length: c_int = 4;\npub const Py_mp_subscript: c_int = 5;\npub const Py_nb_absolute: c_int = 6;\npub const Py_nb_add: c_int = 7;\npub const Py_nb_and: c_int = 8;\npub const Py_nb_bool: c_int = 9;\npub const Py_nb_divmod: c_int = 10;\npub const Py_nb_float: c_int = 11;\npub const Py_nb_floor_divide: c_int = 12;\npub const Py_nb_index: c_int = 13;\npub const Py_nb_inplace_add: c_int = 14;\npub const Py_nb_inplace_and: c_int = 15;\npub const Py_nb_inplace_floor_divide: c_int = 16;\npub const Py_nb_inplace_lshift: c_int = 17;\npub const Py_nb_inplace_multiply: c_int = 18;\npub const Py_nb_inplace_or: c_int = 19;\npub const Py_nb_inplace_power: c_int = 20;\npub const Py_nb_inplace_remainder: c_int = 21;\npub const Py_nb_inplace_rshift: c_int = 22;\npub const Py_nb_inplace_subtract: c_int = 23;\npub const Py_nb_inplace_true_divide: c_int = 24;\npub const Py_nb_inplace_xor: c_int = 25;\npub const Py_nb_int: c_int = 26;\npub const Py_nb_invert: c_int = 27;\npub const Py_nb_lshift: c_int = 28;\npub const Py_nb_multiply: c_int = 29;\npub const Py_nb_negative: c_int = 30;\npub const Py_nb_or: c_int = 31;\npub const Py_nb_positive: c_int = 32;\npub const Py_nb_power: c_int = 33;\npub const Py_nb_remainder: c_int = 34;\npub const Py_nb_rshift: c_int = 35;\npub const Py_nb_subtract: c_int = 36;\npub const Py_nb_true_divide: c_int = 37;\npub const Py_nb_xor: c_int = 38;\npub const Py_sq_ass_item: c_int = 39;\npub const Py_sq_concat: c_int = 40;\npub const Py_sq_contains: c_int = 41;\npub const Py_sq_inplace_concat: c_int = 42;\npub const Py_sq_inplace_repeat: c_int = 43;\npub const Py_sq_item: c_int = 44;\npub const Py_sq_length: c_int = 45;\npub const Py_sq_repeat: c_int = 46;\npub const Py_tp_alloc: c_int = 47;\npub const Py_tp_base: c_int = 48;\npub const Py_tp_bases: c_int = 49;\npub const Py_tp_call: c_int = 50;\npub const Py_tp_clear: c_int = 51;\npub const Py_tp_dealloc: c_int = 52;\npub const Py_tp_del: c_int = 53;\npub const Py_tp_descr_get: c_int = 54;\npub const Py_tp_descr_set: c_int = 55;\npub const Py_tp_doc: c_int = 56;\npub const Py_tp_getattr: c_int = 57;\npub const Py_tp_getattro: c_int = 58;\npub const Py_tp_hash: c_int = 59;\npub const Py_tp_init: c_int = 60;\npub const Py_tp_is_gc: c_int = 61;\npub const Py_tp_iter: c_int = 62;\npub const Py_tp_iternext: c_int = 63;\npub const Py_tp_methods: c_int = 64;\npub const Py_tp_new: c_int = 65;\npub const Py_tp_repr: c_int = 66;\npub const Py_tp_richcompare: c_int = 67;\npub const Py_tp_setattr: c_int = 68;\npub const Py_tp_setattro: c_int = 69;\npub const Py_tp_str: c_int = 70;\npub const Py_tp_traverse: c_int = 71;\npub const Py_tp_members: c_int = 72;\npub const Py_tp_getset: c_int = 73;\npub const Py_tp_free: c_int = 74;\npub const Py_nb_matrix_multiply: c_int = 75;\npub const Py_nb_inplace_matrix_multiply: c_int = 76;\npub const Py_am_await: c_int = 77;\npub const Py_am_aiter: c_int = 78;\npub const Py_am_anext: c_int = 79;\npub const Py_tp_finalize: c_int = 80;\n"
  },
  {
    "path": "pyo3-ffi/src/unicodeobject.rs",
    "content": "use crate::object::*;\nuse crate::pyport::Py_ssize_t;\nuse libc::wchar_t;\nuse std::ffi::{c_char, c_int, c_void};\n\n#[cfg(not(Py_LIMITED_API))]\n#[cfg_attr(\n    Py_3_13,\n    deprecated(note = \"Deprecated since Python 3.13. Use `libc::wchar_t` instead.\")\n)]\npub type Py_UNICODE = wchar_t;\n\npub type Py_UCS4 = u32;\npub type Py_UCS2 = u16;\npub type Py_UCS1 = u8;\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Type\")]\n    pub static mut PyUnicode_Type: PyTypeObject;\n    pub static mut PyUnicodeIter_Type: PyTypeObject;\n\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyUnicode_Check\"]\n    pub fn PyUnicode_Check(op: *mut PyObject) -> c_int;\n\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyUnicode_CheckExact\"]\n    pub fn PyUnicode_CheckExact(op: *mut PyObject) -> c_int;\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyUnicode_Check(op: *mut PyObject) -> c_int {\n    PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS)\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyUnicode_CheckExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut PyUnicode_Type) as c_int\n}\n\npub const Py_UNICODE_REPLACEMENT_CHARACTER: Py_UCS4 = 0xFFFD;\n\nextern_libpython! {\n\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_FromStringAndSize\")]\n    pub fn PyUnicode_FromStringAndSize(u: *const c_char, size: Py_ssize_t) -> *mut PyObject;\n    pub fn PyUnicode_FromString(u: *const c_char) -> *mut PyObject;\n\n    pub fn PyUnicode_Substring(\n        str: *mut PyObject,\n        start: Py_ssize_t,\n        end: Py_ssize_t,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_AsUCS4(\n        unicode: *mut PyObject,\n        buffer: *mut Py_UCS4,\n        buflen: Py_ssize_t,\n        copy_null: c_int,\n    ) -> *mut Py_UCS4;\n    pub fn PyUnicode_AsUCS4Copy(unicode: *mut PyObject) -> *mut Py_UCS4;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_GetLength\")]\n    pub fn PyUnicode_GetLength(unicode: *mut PyObject) -> Py_ssize_t;\n    #[cfg(not(Py_3_12))]\n    #[deprecated(note = \"Removed in Python 3.12\")]\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_GetSize\")]\n    pub fn PyUnicode_GetSize(unicode: *mut PyObject) -> Py_ssize_t;\n    pub fn PyUnicode_ReadChar(unicode: *mut PyObject, index: Py_ssize_t) -> Py_UCS4;\n    pub fn PyUnicode_WriteChar(\n        unicode: *mut PyObject,\n        index: Py_ssize_t,\n        character: Py_UCS4,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Resize\")]\n    pub fn PyUnicode_Resize(unicode: *mut *mut PyObject, length: Py_ssize_t) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_FromEncodedObject\")]\n    pub fn PyUnicode_FromEncodedObject(\n        obj: *mut PyObject,\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_FromObject\")]\n    pub fn PyUnicode_FromObject(obj: *mut PyObject) -> *mut PyObject;\n    // #[cfg_attr(PyPy, link_name = \"PyPyUnicode_FromFormatV\")]\n    // pub fn PyUnicode_FromFormatV(format: *const c_char, vargs: va_list) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_FromFormat\")]\n    pub fn PyUnicode_FromFormat(format: *const c_char, ...) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_InternInPlace\")]\n    pub fn PyUnicode_InternInPlace(arg1: *mut *mut PyObject);\n    #[cfg(not(Py_3_12))]\n    #[cfg_attr(Py_3_10, deprecated(note = \"Python 3.10\"))]\n    pub fn PyUnicode_InternImmortal(arg1: *mut *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_InternFromString\")]\n    pub fn PyUnicode_InternFromString(u: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_FromWideChar\")]\n    pub fn PyUnicode_FromWideChar(w: *const wchar_t, size: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsWideChar\")]\n    pub fn PyUnicode_AsWideChar(\n        unicode: *mut PyObject,\n        w: *mut wchar_t,\n        size: Py_ssize_t,\n    ) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsWideCharString\")]\n    pub fn PyUnicode_AsWideCharString(\n        unicode: *mut PyObject,\n        size: *mut Py_ssize_t,\n    ) -> *mut wchar_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_FromOrdinal\")]\n    pub fn PyUnicode_FromOrdinal(ordinal: c_int) -> *mut PyObject;\n    pub fn PyUnicode_ClearFreeList() -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_GetDefaultEncoding\")]\n    pub fn PyUnicode_GetDefaultEncoding() -> *const c_char;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Decode\")]\n    pub fn PyUnicode_Decode(\n        s: *const c_char,\n        size: Py_ssize_t,\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_AsDecodedObject(\n        unicode: *mut PyObject,\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_AsDecodedUnicode(\n        unicode: *mut PyObject,\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsEncodedObject\")]\n    pub fn PyUnicode_AsEncodedObject(\n        unicode: *mut PyObject,\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsEncodedString\")]\n    pub fn PyUnicode_AsEncodedString(\n        unicode: *mut PyObject,\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_AsEncodedUnicode(\n        unicode: *mut PyObject,\n        encoding: *const c_char,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_BuildEncodingMap(string: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicode_DecodeUTF7(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_DecodeUTF7Stateful(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n        consumed: *mut Py_ssize_t,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_DecodeUTF8\")]\n    pub fn PyUnicode_DecodeUTF8(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_DecodeUTF8Stateful(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n        consumed: *mut Py_ssize_t,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsUTF8String\")]\n    pub fn PyUnicode_AsUTF8String(unicode: *mut PyObject) -> *mut PyObject;\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsUTF8AndSize\")]\n    pub fn PyUnicode_AsUTF8AndSize(unicode: *mut PyObject, size: *mut Py_ssize_t) -> *const c_char;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_DecodeUTF32\")]\n    pub fn PyUnicode_DecodeUTF32(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n        byteorder: *mut c_int,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_DecodeUTF32Stateful(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n        byteorder: *mut c_int,\n        consumed: *mut Py_ssize_t,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsUTF32String\")]\n    pub fn PyUnicode_AsUTF32String(unicode: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_DecodeUTF16\")]\n    pub fn PyUnicode_DecodeUTF16(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n        byteorder: *mut c_int,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_DecodeUTF16Stateful(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n        byteorder: *mut c_int,\n        consumed: *mut Py_ssize_t,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsUTF16String\")]\n    pub fn PyUnicode_AsUTF16String(unicode: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicode_DecodeUnicodeEscape(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsUnicodeEscapeString\")]\n    pub fn PyUnicode_AsUnicodeEscapeString(unicode: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicode_DecodeRawUnicodeEscape(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_AsRawUnicodeEscapeString(unicode: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_DecodeLatin1\")]\n    pub fn PyUnicode_DecodeLatin1(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsLatin1String\")]\n    pub fn PyUnicode_AsLatin1String(unicode: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_DecodeASCII\")]\n    pub fn PyUnicode_DecodeASCII(\n        string: *const c_char,\n        length: Py_ssize_t,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_AsASCIIString\")]\n    pub fn PyUnicode_AsASCIIString(unicode: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicode_DecodeCharmap(\n        string: *const c_char,\n        length: Py_ssize_t,\n        mapping: *mut PyObject,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_AsCharmapString(\n        unicode: *mut PyObject,\n        mapping: *mut PyObject,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_DecodeLocaleAndSize(\n        str: *const c_char,\n        len: Py_ssize_t,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_DecodeLocale(str: *const c_char, errors: *const c_char) -> *mut PyObject;\n    pub fn PyUnicode_EncodeLocale(unicode: *mut PyObject, errors: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_FSConverter\")]\n    pub fn PyUnicode_FSConverter(arg1: *mut PyObject, arg2: *mut c_void) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_FSDecoder\")]\n    pub fn PyUnicode_FSDecoder(arg1: *mut PyObject, arg2: *mut c_void) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_DecodeFSDefault\")]\n    pub fn PyUnicode_DecodeFSDefault(s: *const c_char) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_DecodeFSDefaultAndSize\")]\n    pub fn PyUnicode_DecodeFSDefaultAndSize(s: *const c_char, size: Py_ssize_t) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_EncodeFSDefault\")]\n    pub fn PyUnicode_EncodeFSDefault(unicode: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Concat\")]\n    pub fn PyUnicode_Concat(left: *mut PyObject, right: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicode_Append(pleft: *mut *mut PyObject, right: *mut PyObject);\n    pub fn PyUnicode_AppendAndDel(pleft: *mut *mut PyObject, right: *mut PyObject);\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Split\")]\n    pub fn PyUnicode_Split(\n        s: *mut PyObject,\n        sep: *mut PyObject,\n        maxsplit: Py_ssize_t,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Splitlines\")]\n    pub fn PyUnicode_Splitlines(s: *mut PyObject, keepends: c_int) -> *mut PyObject;\n    pub fn PyUnicode_Partition(s: *mut PyObject, sep: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicode_RPartition(s: *mut PyObject, sep: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicode_RSplit(\n        s: *mut PyObject,\n        sep: *mut PyObject,\n        maxsplit: Py_ssize_t,\n    ) -> *mut PyObject;\n    pub fn PyUnicode_Translate(\n        str: *mut PyObject,\n        table: *mut PyObject,\n        errors: *const c_char,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Join\")]\n    pub fn PyUnicode_Join(separator: *mut PyObject, seq: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Tailmatch\")]\n    pub fn PyUnicode_Tailmatch(\n        str: *mut PyObject,\n        substr: *mut PyObject,\n        start: Py_ssize_t,\n        end: Py_ssize_t,\n        direction: c_int,\n    ) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Find\")]\n    pub fn PyUnicode_Find(\n        str: *mut PyObject,\n        substr: *mut PyObject,\n        start: Py_ssize_t,\n        end: Py_ssize_t,\n        direction: c_int,\n    ) -> Py_ssize_t;\n    pub fn PyUnicode_FindChar(\n        str: *mut PyObject,\n        ch: Py_UCS4,\n        start: Py_ssize_t,\n        end: Py_ssize_t,\n        direction: c_int,\n    ) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Count\")]\n    pub fn PyUnicode_Count(\n        str: *mut PyObject,\n        substr: *mut PyObject,\n        start: Py_ssize_t,\n        end: Py_ssize_t,\n    ) -> Py_ssize_t;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Replace\")]\n    pub fn PyUnicode_Replace(\n        str: *mut PyObject,\n        substr: *mut PyObject,\n        replstr: *mut PyObject,\n        maxcount: Py_ssize_t,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Compare\")]\n    pub fn PyUnicode_Compare(left: *mut PyObject, right: *mut PyObject) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_CompareWithASCIIString\")]\n    pub fn PyUnicode_CompareWithASCIIString(left: *mut PyObject, right: *const c_char) -> c_int;\n    #[cfg(Py_3_13)]\n    pub fn PyUnicode_EqualToUTF8(unicode: *mut PyObject, string: *const c_char) -> c_int;\n    #[cfg(Py_3_13)]\n    pub fn PyUnicode_EqualToUTF8AndSize(\n        unicode: *mut PyObject,\n        string: *const c_char,\n        size: Py_ssize_t,\n    ) -> c_int;\n\n    pub fn PyUnicode_RichCompare(\n        left: *mut PyObject,\n        right: *mut PyObject,\n        op: c_int,\n    ) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyUnicode_Format\")]\n    pub fn PyUnicode_Format(format: *mut PyObject, args: *mut PyObject) -> *mut PyObject;\n    pub fn PyUnicode_Contains(container: *mut PyObject, element: *mut PyObject) -> c_int;\n    pub fn PyUnicode_IsIdentifier(s: *mut PyObject) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/warnings.rs",
    "content": "use crate::object::PyObject;\nuse crate::pyport::Py_ssize_t;\nuse std::ffi::{c_char, c_int};\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_WarnEx\")]\n    pub fn PyErr_WarnEx(\n        category: *mut PyObject,\n        message: *const c_char,\n        stack_level: Py_ssize_t,\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_WarnFormat\")]\n    pub fn PyErr_WarnFormat(\n        category: *mut PyObject,\n        stack_level: Py_ssize_t,\n        format: *const c_char,\n        ...\n    ) -> c_int;\n    pub fn PyErr_ResourceWarning(\n        source: *mut PyObject,\n        stack_level: Py_ssize_t,\n        format: *const c_char,\n        ...\n    ) -> c_int;\n    #[cfg_attr(PyPy, link_name = \"PyPyErr_WarnExplicit\")]\n    pub fn PyErr_WarnExplicit(\n        category: *mut PyObject,\n        message: *const c_char,\n        filename: *const c_char,\n        lineno: c_int,\n        module: *const c_char,\n        registry: *mut PyObject,\n    ) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi/src/weakrefobject.rs",
    "content": "use crate::object::*;\nuse std::ffi::c_int;\n\n#[cfg(all(not(PyPy), Py_LIMITED_API, not(GraalPy)))]\nopaque_struct!(pub PyWeakReference);\n\n#[cfg(all(not(PyPy), not(Py_LIMITED_API), not(GraalPy)))]\npub use crate::_PyWeakReference as PyWeakReference;\n\nextern_libpython! {\n    // TODO: PyO3 is depending on this symbol in `reference.rs`, we should change this and\n    // remove the export as this is a private symbol.\n    pub static mut _PyWeakref_RefType: PyTypeObject;\n    static mut _PyWeakref_ProxyType: PyTypeObject;\n    static mut _PyWeakref_CallableProxyType: PyTypeObject;\n\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyWeakref_CheckRef\"]\n    pub fn PyWeakref_CheckRef(op: *mut PyObject) -> c_int;\n\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyWeakref_CheckRefExact\"]\n    pub fn PyWeakref_CheckRefExact(op: *mut PyObject) -> c_int;\n\n    #[cfg(PyPy)]\n    #[link_name = \"PyPyWeakref_CheckProxy\"]\n    pub fn PyWeakref_CheckProxy(op: *mut PyObject) -> c_int;\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyWeakref_CheckRef(op: *mut PyObject) -> c_int {\n    PyObject_TypeCheck(op, &raw mut _PyWeakref_RefType)\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyWeakref_CheckRefExact(op: *mut PyObject) -> c_int {\n    (Py_TYPE(op) == &raw mut _PyWeakref_RefType) as c_int\n}\n\n#[inline]\n#[cfg(not(PyPy))]\npub unsafe fn PyWeakref_CheckProxy(op: *mut PyObject) -> c_int {\n    ((Py_TYPE(op) == &raw mut _PyWeakref_ProxyType)\n        || (Py_TYPE(op) == &raw mut _PyWeakref_CallableProxyType)) as c_int\n}\n\n#[inline]\npub unsafe fn PyWeakref_Check(op: *mut PyObject) -> c_int {\n    (PyWeakref_CheckRef(op) != 0 || PyWeakref_CheckProxy(op) != 0) as c_int\n}\n\nextern_libpython! {\n    #[cfg_attr(PyPy, link_name = \"PyPyWeakref_NewRef\")]\n    pub fn PyWeakref_NewRef(ob: *mut PyObject, callback: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyWeakref_NewProxy\")]\n    pub fn PyWeakref_NewProxy(ob: *mut PyObject, callback: *mut PyObject) -> *mut PyObject;\n    #[cfg_attr(PyPy, link_name = \"PyPyWeakref_GetObject\")]\n    #[cfg_attr(\n        Py_3_13,\n        deprecated(note = \"deprecated since Python 3.13. Use `PyWeakref_GetRef` instead.\")\n    )]\n    pub fn PyWeakref_GetObject(reference: *mut PyObject) -> *mut PyObject;\n    #[cfg(Py_3_13)]\n    #[cfg_attr(PyPy, link_name = \"PyPyWeakref_GetRef\")]\n    pub fn PyWeakref_GetRef(reference: *mut PyObject, pobj: *mut *mut PyObject) -> c_int;\n}\n"
  },
  {
    "path": "pyo3-ffi-check/Cargo.toml",
    "content": "[package]\nname = \"pyo3-ffi-check\"\nversion = \"0.1.0\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\npyo3-ffi-check-macro = { path = \"./macro\" }\npyo3-ffi = { path = \"../pyo3-ffi\" }\n\n[build-dependencies]\nbindgen = \"0.69.4\"\npyo3-build-config = { path = \"../pyo3-build-config\" }\n\n[workspace]\nmembers = [\n    \"macro\"\n]\n"
  },
  {
    "path": "pyo3-ffi-check/README.md",
    "content": "# pyo3-ffi-check\n\nThis is a simple program which compares ffi definitions from `pyo3-ffi` against those produced by `bindgen`.\n\nIf any differ in size, these are printed to stdout and a the process will exit nonzero.\n\nThe main purpose of this program is to be run as part of PyO3's continuous integration pipeline to catch possible errors in PyO3's ffi definitions.\n"
  },
  {
    "path": "pyo3-ffi-check/build.rs",
    "content": "use std::env;\nuse std::path::PathBuf;\n\n#[derive(Debug)]\nstruct ParseCallbacks;\n\nimpl bindgen::callbacks::ParseCallbacks for ParseCallbacks {\n    // these are anonymous fields and structs in CPython that we needed to\n    // invent names for. Bindgen seems to generate stable names, so we remap the\n    // automatically generated names to the names we invented in the FFI\n    fn item_name(&self, _original_item_name: &str) -> Option<String> {\n        if _original_item_name == \"_object__bindgen_ty_1__bindgen_ty_1\" {\n            Some(\"PyObjectObFlagsAndRefcnt\".into())\n        } else if _original_item_name == \"_object__bindgen_ty_1\" {\n            Some(\"PyObjectObRefcnt\".into())\n        } else {\n            None\n        }\n    }\n}\n\nfn main() {\n    pyo3_build_config::add_libpython_rpath_link_args();\n\n    let config = pyo3_build_config::get();\n\n    let python_include_dir = config\n        .run_python_script(\n            \"import sysconfig; print(sysconfig.get_config_var('INCLUDEPY'), end='');\",\n        )\n        .expect(\"failed to get lib dir\");\n    let gil_disabled_on_windows = config\n        .run_python_script(\n            \"import sysconfig; import platform; print(sysconfig.get_config_var('Py_GIL_DISABLED') == 1 and platform.system() == 'Windows');\",\n        )\n        .expect(\"failed to get Py_GIL_DISABLED\").trim_end() == \"True\";\n\n    let clang_args = if gil_disabled_on_windows {\n        vec![\n            format!(\"-I{python_include_dir}\"),\n            \"-DPy_GIL_DISABLED\".to_string(),\n        ]\n    } else {\n        vec![format!(\"-I{python_include_dir}\")]\n    };\n\n    println!(\"cargo:rerun-if-changed=wrapper.h\");\n\n    let bindings = bindgen::Builder::default()\n        .header(\"wrapper.h\")\n        .clang_args(clang_args)\n        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))\n        .parse_callbacks(Box::new(ParseCallbacks))\n        // blocklist some values which apparently have conflicting definitions on unix\n        .blocklist_item(\"FP_NORMAL\")\n        .blocklist_item(\"FP_SUBNORMAL\")\n        .blocklist_item(\"FP_NAN\")\n        .blocklist_item(\"FP_INFINITE\")\n        .blocklist_item(\"FP_INT_UPWARD\")\n        .blocklist_item(\"FP_INT_DOWNWARD\")\n        .blocklist_item(\"FP_INT_TOWARDZERO\")\n        .blocklist_item(\"FP_INT_TONEARESTFROMZERO\")\n        .blocklist_item(\"FP_INT_TONEAREST\")\n        .blocklist_item(\"FP_ZERO\")\n        .generate()\n        .expect(\"Unable to generate bindings\");\n\n    let out_path = PathBuf::from(env::var(\"OUT_DIR\").unwrap());\n    bindings\n        .write_to_file(out_path.join(\"bindings.rs\"))\n        .expect(\"Couldn't write bindings!\");\n}\n"
  },
  {
    "path": "pyo3-ffi-check/macro/Cargo.toml",
    "content": "[package]\nname = \"pyo3-ffi-check-macro\"\nversion = \"0.1.0\"\nedition = \"2021\"\npublish = false\n\n[lib]\nproc-macro = true\n\n[dependencies]\nglob = \"0.3\"\nquote = \"1\"\nproc-macro2 = \"1.0.60\"\nscraper = \"0.17\"\npyo3-build-config = { path = \"../../pyo3-build-config\" }\n"
  },
  {
    "path": "pyo3-ffi-check/macro/src/lib.rs",
    "content": "use std::{env, fs, path::PathBuf};\n\nuse proc_macro2::{Ident, Span, TokenStream, TokenTree};\nuse pyo3_build_config::PythonVersion;\nuse quote::quote;\n\n/// Macro which expands to multiple macro calls, one per pyo3-ffi struct.\n#[proc_macro]\npub fn for_all_structs(input: proc_macro::TokenStream) -> proc_macro::TokenStream {\n    let input: TokenStream = input.into();\n    let mut input = input.into_iter();\n\n    let macro_name = match input.next() {\n        Some(TokenTree::Ident(i)) => i,\n        _ => {\n            return quote!(compile_error!(\n                \"for_all_structs!() takes only a single ident as input\"\n            ))\n            .into()\n        }\n    };\n\n    if input.next().is_some() {\n        return quote!(compile_error!(\n            \"for_all_structs!() takes only a single ident as input\"\n        ))\n        .into();\n    }\n\n    let doc_dir = get_doc_dir();\n    let structs_glob = format!(\"{}/doc/pyo3_ffi/struct.*.html\", doc_dir.display());\n\n    let mut output = TokenStream::new();\n\n    for entry in glob::glob(&structs_glob).expect(\"Failed to read glob pattern\") {\n        let entry = entry\n            .unwrap()\n            .file_name()\n            .unwrap()\n            .to_string_lossy()\n            .into_owned();\n        let struct_name = entry\n            .strip_prefix(\"struct.\")\n            .unwrap()\n            .strip_suffix(\".html\")\n            .unwrap();\n\n        if pyo3_build_config::get().version < PythonVersion::PY315 && struct_name == \"PyBytesWriter\"\n        {\n            // PyBytesWriter was added in Python 3.15\n            continue;\n        }\n\n        let struct_ident = Ident::new(struct_name, Span::call_site());\n        output.extend(quote!(#macro_name!(#struct_ident);));\n    }\n\n    if output.is_empty() {\n        quote!(compile_error!(concat!(\n            \"No files found at `\",\n            #structs_glob,\n            \"`, try running `cargo doc -p pyo3-ffi` first.\"\n        )))\n    } else {\n        output\n    }\n    .into()\n}\n\nfn get_doc_dir() -> PathBuf {\n    let path = PathBuf::from(env::var_os(\"OUT_DIR\").unwrap());\n    path.parent()\n        .unwrap()\n        .parent()\n        .unwrap()\n        .parent()\n        .unwrap()\n        .parent()\n        .unwrap()\n        .to_owned()\n}\n\n/// Macro which expands to multiple macro calls, one per field in a pyo3-ffi\n/// struct.\n#[proc_macro]\npub fn for_all_fields(input: proc_macro::TokenStream) -> proc_macro::TokenStream {\n    let input: TokenStream = input.into();\n    let mut input = input.into_iter();\n\n    let struct_name = match input.next() {\n        Some(TokenTree::Ident(i)) => i,\n        _ => {\n            return quote!(compile_error!(\n                \"for_all_fields!() takes exactly two idents as input\"\n            ))\n            .into()\n        }\n    };\n\n    match input.next() {\n        Some(TokenTree::Punct(punct)) if punct.as_char() == ',' => (),\n        _ => {\n            return quote!(compile_error!(\n                \"for_all_fields!() takes exactly two idents as input\"\n            ))\n            .into()\n        }\n    };\n\n    let macro_name = match input.next() {\n        Some(TokenTree::Ident(i)) => i,\n        _ => {\n            return quote!(compile_error!(\n                \"for_all_fields!() takes exactly two idents as input\"\n            ))\n            .into()\n        }\n    };\n\n    if input.next().is_some() {\n        return quote!(compile_error!(\n            \"for_all_fields!() takes exactly two idents as input\"\n        ))\n        .into();\n    }\n\n    let doc_dir = get_doc_dir();\n    let struct_file = fs::read_to_string(format!(\n        \"{}/doc/pyo3_ffi/struct.{}.html\",\n        doc_dir.display(),\n        struct_name\n    ))\n    .unwrap();\n\n    let html = scraper::Html::parse_document(&struct_file);\n    let selector = scraper::Selector::parse(\"span.structfield\").unwrap();\n\n    let mut output = TokenStream::new();\n\n    for el in html.select(&selector) {\n        let field_name = el\n            .value()\n            .id()\n            .unwrap()\n            .strip_prefix(\"structfield.\")\n            .unwrap();\n\n        let field_ident = Ident::new(field_name, Span::call_site());\n\n        let bindgen_field_ident = if (pyo3_build_config::get().version >= PythonVersion::PY312)\n            && struct_name == \"PyObject\"\n            && field_name == \"ob_refcnt\"\n        {\n            // PyObject since 3.12 implements ob_refcnt as a union; bindgen creates\n            // an anonymous name for the field\n            Ident::new(\"__bindgen_anon_1\", Span::call_site())\n        } else if struct_name == \"PyMemberDef\" && field_name == \"type_code\" {\n            // the field name in the C API is `type`, but that's a keyword in Rust\n            // so PyO3 picked type_code, bindgen picked type_\n            Ident::new(\"type_\", Span::call_site())\n        } else {\n            field_ident.clone()\n        };\n\n        output.extend(quote!(#macro_name!(#struct_name, #field_ident, #bindgen_field_ident);));\n    }\n\n    output.into()\n}\n"
  },
  {
    "path": "pyo3-ffi-check/src/main.rs",
    "content": "use std::{ffi::CStr, process::exit};\n\nfn main() {\n    println!(\n        \"comparing pyo3-ffi against headers generated for {}\",\n        CStr::from_bytes_with_nul(bindings::PY_VERSION)\n            .unwrap()\n            .to_string_lossy()\n    );\n\n    let mut failed = false;\n\n    macro_rules! check_struct {\n        ($name:ident) => {{\n            let pyo3_ffi_size = std::mem::size_of::<pyo3_ffi::$name>();\n            let bindgen_size = std::mem::size_of::<bindings::$name>();\n\n            let pyo3_ffi_align = std::mem::align_of::<pyo3_ffi::$name>();\n            let bindgen_align = std::mem::align_of::<bindings::$name>();\n\n            // Check if sizes differ, but ignore zero-sized types (probably \"opaque\" in pyo3-ffi)\n            if pyo3_ffi_size == 0 {\n                println!(\n                    \"warning: ignoring zero-sized pyo3_ffi type {}\",\n                    stringify!($name),\n                );\n            } else if pyo3_ffi_size != bindgen_size {\n                failed = true;\n                println!(\n                    \"error: size of {} differs between pyo3_ffi ({}) and bindgen ({})\",\n                    stringify!($name),\n                    pyo3_ffi_size,\n                    bindgen_size\n                );\n            } else if pyo3_ffi_align != bindgen_align {\n                failed = true;\n                println!(\n                    \"error: alignment of {} differs between pyo3_ffi ({}) and bindgen ({})\",\n                    stringify!($name),\n                    pyo3_ffi_align,\n                    bindgen_align\n                );\n            }\n\n            pyo3_ffi_check_macro::for_all_fields!($name, check_field);\n        }};\n    }\n\n    macro_rules! check_field {\n        ($struct_name:ident, $field:ident, $bindgen_field:ident) => {{\n            // some struct fields are deprecated but still present in the ABI\n            #[allow(clippy::used_underscore_binding, deprecated)]\n            let pyo3_ffi_offset = std::mem::offset_of!(pyo3_ffi::$struct_name, $field);\n            #[allow(clippy::used_underscore_binding)]\n            let bindgen_offset = std::mem::offset_of!(bindings::$struct_name, $bindgen_field);\n\n            if pyo3_ffi_offset != bindgen_offset {\n                failed = true;\n                println!(\n                    \"error: field offset of {}.{} differs between pyo3_ffi ({}) and bindgen ({})\",\n                    stringify!($struct_name),\n                    stringify!($field),\n                    pyo3_ffi_offset,\n                    bindgen_offset\n                );\n            }\n        }};\n    }\n\n    pyo3_ffi_check_macro::for_all_structs!(check_struct);\n\n    if failed {\n        exit(1);\n    } else {\n        exit(0);\n    }\n}\n\n#[allow(\n    non_snake_case,\n    non_camel_case_types,\n    non_upper_case_globals,\n    dead_code,\n    improper_ctypes,\n    clippy::all,\n    // clippy fails with lots of errors if this is not set specifically\n    clippy::used_underscore_binding\n)]\nmod bindings {\n    include!(concat!(env!(\"OUT_DIR\"), \"/bindings.rs\"));\n}\n"
  },
  {
    "path": "pyo3-ffi-check/wrapper.h",
    "content": "#include \"Python.h\"\n#include \"datetime.h\"\n#include \"frameobject.h\"\n#include \"structmember.h\"\n"
  },
  {
    "path": "pyo3-introspection/Cargo.toml",
    "content": "[package]\nname = \"pyo3-introspection\"\nversion = \"0.28.2\"\ndescription = \"Introspect dynamic libraries built with PyO3 to get metadata about the exported Python types\"\nauthors = [\"PyO3 Project and Contributors <https://github.com/PyO3>\"]\nhomepage = \"https://github.com/pyo3/pyo3\"\nrepository = \"https://github.com/pyo3/pyo3\"\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\n\n[dependencies]\nanyhow = \"1\"\ngoblin = \">=0.9, <0.11\"\nserde = { version = \"1\", features = [\"derive\"] }\nserde_json = \"1\"\n\n[dev-dependencies]\ntempfile = \"3.12.0\"\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "pyo3-introspection/src/introspection.rs",
    "content": "use crate::model::{\n    Argument, Arguments, Attribute, Class, Constant, Expr, Function, Module, Operator,\n    VariableLengthArgument,\n};\nuse anyhow::{anyhow, bail, ensure, Context, Result};\nuse goblin::elf::section_header::SHN_XINDEX;\nuse goblin::elf::Elf;\nuse goblin::mach::load_command::CommandVariant;\nuse goblin::mach::symbols::{NO_SECT, N_SECT};\nuse goblin::mach::{Mach, MachO, SingleArch};\nuse goblin::pe::PE;\nuse goblin::Object;\nuse serde::Deserialize;\nuse std::borrow::Cow;\nuse std::cmp::Ordering;\nuse std::collections::HashMap;\nuse std::path::Path;\nuse std::{fs, str};\n\n/// Introspect a cdylib built with PyO3 and returns the definition of a Python module.\n///\n/// This function currently supports the ELF (most *nix including Linux), Match-O (macOS) and PE (Windows) formats.\npub fn introspect_cdylib(library_path: impl AsRef<Path>, main_module_name: &str) -> Result<Module> {\n    let chunks = find_introspection_chunks_in_binary_object(library_path.as_ref())?;\n    parse_chunks(&chunks, main_module_name)\n}\n\n/// Parses the introspection chunks found in the binary\nfn parse_chunks(chunks: &[Chunk], main_module_name: &str) -> Result<Module> {\n    let mut chunks_by_id = HashMap::<&str, &Chunk>::new();\n    let mut chunks_by_parent = HashMap::<&str, Vec<&Chunk>>::new();\n    for chunk in chunks {\n        let (id, parent) = match chunk {\n            Chunk::Module { id, .. } => (Some(id.as_str()), None),\n            Chunk::Class { id, parent, .. } => (Some(id.as_str()), parent.as_deref()),\n            Chunk::Function { id, parent, .. } | Chunk::Attribute { id, parent, .. } => {\n                (id.as_deref(), parent.as_deref())\n            }\n        };\n        if let Some(id) = id {\n            chunks_by_id.insert(id, chunk);\n        }\n        if let Some(parent) = parent {\n            chunks_by_parent.entry(parent).or_default().push(chunk);\n        }\n    }\n    // We look for the root chunk\n    for chunk in chunks {\n        if let Chunk::Module {\n            id,\n            name,\n            members,\n            doc,\n            incomplete,\n        } = chunk\n        {\n            if name == main_module_name {\n                let type_hint_for_annotation_id = introspection_id_to_type_hint_for_root_module(\n                    chunk,\n                    &chunks_by_id,\n                    &chunks_by_parent,\n                );\n                return convert_module(\n                    id,\n                    name,\n                    members,\n                    *incomplete,\n                    doc.as_deref(),\n                    &chunks_by_id,\n                    &chunks_by_parent,\n                    &type_hint_for_annotation_id,\n                );\n            }\n        }\n    }\n    bail!(\"No module named {main_module_name} found\")\n}\n\n#[expect(clippy::too_many_arguments)]\nfn convert_module(\n    id: &str,\n    name: &str,\n    members: &[String],\n    mut incomplete: bool,\n    docstring: Option<&str>,\n    chunks_by_id: &HashMap<&str, &Chunk>,\n    chunks_by_parent: &HashMap<&str, Vec<&Chunk>>,\n    type_hint_for_annotation_id: &HashMap<String, Expr>,\n) -> Result<Module> {\n    let mut member_chunks = chunks_by_parent\n        .get(&id)\n        .into_iter()\n        .flatten()\n        .copied()\n        .collect::<Vec<_>>();\n    for member in members {\n        if let Some(c) = chunks_by_id.get(member.as_str()) {\n            member_chunks.push(*c);\n        } else {\n            incomplete = true; // We don't find an element\n        }\n    }\n    let (modules, classes, functions, attributes) = convert_members(\n        member_chunks,\n        chunks_by_id,\n        chunks_by_parent,\n        type_hint_for_annotation_id,\n    )?;\n\n    Ok(Module {\n        name: name.into(),\n        modules,\n        classes,\n        functions,\n        attributes,\n        incomplete,\n        docstring: docstring.map(Into::into),\n    })\n}\n\ntype Members = (Vec<Module>, Vec<Class>, Vec<Function>, Vec<Attribute>);\n\n/// Convert a list of members of a module or a class\nfn convert_members<'a>(\n    chunks: impl IntoIterator<Item = &'a Chunk>,\n    chunks_by_id: &HashMap<&str, &Chunk>,\n    chunks_by_parent: &HashMap<&str, Vec<&Chunk>>,\n    type_hint_for_annotation_id: &HashMap<String, Expr>,\n) -> Result<Members> {\n    let mut modules = Vec::new();\n    let mut classes = Vec::new();\n    let mut functions = Vec::new();\n    let mut attributes = Vec::new();\n    for chunk in chunks {\n        match chunk {\n            Chunk::Module {\n                name,\n                id,\n                members,\n                incomplete,\n                doc,\n            } => {\n                modules.push(convert_module(\n                    id,\n                    name,\n                    members,\n                    *incomplete,\n                    doc.as_deref(),\n                    chunks_by_id,\n                    chunks_by_parent,\n                    type_hint_for_annotation_id,\n                )?);\n            }\n            Chunk::Class {\n                name,\n                id,\n                bases,\n                decorators,\n                doc,\n                parent: _,\n            } => classes.push(convert_class(\n                id,\n                name,\n                bases,\n                decorators,\n                doc.as_deref(),\n                chunks_by_id,\n                chunks_by_parent,\n                type_hint_for_annotation_id,\n            )?),\n            Chunk::Function {\n                name,\n                id: _,\n                arguments,\n                parent: _,\n                decorators,\n                is_async,\n                returns,\n                doc,\n            } => functions.push(convert_function(\n                name,\n                arguments,\n                decorators,\n                returns,\n                *is_async,\n                doc.as_deref(),\n                type_hint_for_annotation_id,\n            )),\n            Chunk::Attribute {\n                name,\n                id: _,\n                parent: _,\n                value,\n                annotation,\n                doc,\n            } => attributes.push(convert_attribute(\n                name,\n                value,\n                annotation,\n                doc.as_deref(),\n                type_hint_for_annotation_id,\n            )),\n        }\n    }\n    // We sort elements to get a stable output\n    modules.sort_by(|l, r| l.name.cmp(&r.name));\n    classes.sort_by(|l, r| l.name.cmp(&r.name));\n    functions.sort_by(|l, r| match l.name.cmp(&r.name) {\n        Ordering::Equal => {\n            fn decorator_expr_key(expr: &Expr) -> (u32, Cow<'_, str>) {\n                // We put plain names before attributes for @property to be before @foo.property\n                match expr {\n                    Expr::Name { id, .. } => (0, Cow::Borrowed(id)),\n                    Expr::Attribute { value, attr } => {\n                        let (c, v) = decorator_expr_key(value);\n                        (c + 1, Cow::Owned(format!(\"{v}.{attr}\")))\n                    }\n                    _ => (0, Cow::Borrowed(\"\")), // We don't care\n                }\n            }\n            // We pick an ordering based on decorators\n            l.decorators\n                .iter()\n                .map(decorator_expr_key)\n                .cmp(r.decorators.iter().map(decorator_expr_key))\n        }\n        o => o,\n    });\n    attributes.sort_by(|l, r| l.name.cmp(&r.name));\n    Ok((modules, classes, functions, attributes))\n}\n\n#[expect(clippy::too_many_arguments)]\nfn convert_class(\n    id: &str,\n    name: &str,\n    bases: &[ChunkExpr],\n    decorators: &[ChunkExpr],\n    docstring: Option<&str>,\n    chunks_by_id: &HashMap<&str, &Chunk>,\n    chunks_by_parent: &HashMap<&str, Vec<&Chunk>>,\n    type_hint_for_annotation_id: &HashMap<String, Expr>,\n) -> Result<Class> {\n    let (nested_modules, nested_classes, methods, attributes) = convert_members(\n        chunks_by_parent.get(&id).into_iter().flatten().copied(),\n        chunks_by_id,\n        chunks_by_parent,\n        type_hint_for_annotation_id,\n    )?;\n    ensure!(\n        nested_modules.is_empty(),\n        \"Classes cannot contain nested modules\"\n    );\n    Ok(Class {\n        name: name.into(),\n        bases: bases\n            .iter()\n            .map(|e| convert_expr(e, type_hint_for_annotation_id))\n            .collect(),\n        methods,\n        attributes,\n        decorators: decorators\n            .iter()\n            .map(|e| convert_expr(e, type_hint_for_annotation_id))\n            .collect(),\n        inner_classes: nested_classes,\n        docstring: docstring.map(Into::into),\n    })\n}\n\nfn convert_function(\n    name: &str,\n    arguments: &ChunkArguments,\n    decorators: &[ChunkExpr],\n    returns: &Option<ChunkExpr>,\n    is_async: bool,\n    docstring: Option<&str>,\n    type_hint_for_annotation_id: &HashMap<String, Expr>,\n) -> Function {\n    Function {\n        name: name.into(),\n        decorators: decorators\n            .iter()\n            .map(|e| convert_expr(e, type_hint_for_annotation_id))\n            .collect(),\n        arguments: Arguments {\n            positional_only_arguments: arguments\n                .posonlyargs\n                .iter()\n                .map(|a| convert_argument(a, type_hint_for_annotation_id))\n                .collect(),\n            arguments: arguments\n                .args\n                .iter()\n                .map(|a| convert_argument(a, type_hint_for_annotation_id))\n                .collect(),\n            vararg: arguments\n                .vararg\n                .as_ref()\n                .map(|a| convert_variable_length_argument(a, type_hint_for_annotation_id)),\n            keyword_only_arguments: arguments\n                .kwonlyargs\n                .iter()\n                .map(|e| convert_argument(e, type_hint_for_annotation_id))\n                .collect(),\n            kwarg: arguments\n                .kwarg\n                .as_ref()\n                .map(|a| convert_variable_length_argument(a, type_hint_for_annotation_id)),\n        },\n        returns: returns\n            .as_ref()\n            .map(|a| convert_expr(a, type_hint_for_annotation_id)),\n        is_async,\n        docstring: docstring.map(Into::into),\n    }\n}\n\nfn convert_argument(\n    arg: &ChunkArgument,\n    type_hint_for_annotation_id: &HashMap<String, Expr>,\n) -> Argument {\n    Argument {\n        name: arg.name.clone(),\n        default_value: arg\n            .default\n            .as_ref()\n            .map(|e| convert_expr(e, type_hint_for_annotation_id)),\n        annotation: arg\n            .annotation\n            .as_ref()\n            .map(|a| convert_expr(a, type_hint_for_annotation_id)),\n    }\n}\n\nfn convert_variable_length_argument(\n    arg: &ChunkArgument,\n    type_hint_for_annotation_id: &HashMap<String, Expr>,\n) -> VariableLengthArgument {\n    VariableLengthArgument {\n        name: arg.name.clone(),\n        annotation: arg\n            .annotation\n            .as_ref()\n            .map(|a| convert_expr(a, type_hint_for_annotation_id)),\n    }\n}\n\nfn convert_attribute(\n    name: &str,\n    value: &Option<ChunkExpr>,\n    annotation: &Option<ChunkExpr>,\n    docstring: Option<&str>,\n    type_hint_for_annotation_id: &HashMap<String, Expr>,\n) -> Attribute {\n    Attribute {\n        name: name.into(),\n        value: value\n            .as_ref()\n            .map(|v| convert_expr(v, type_hint_for_annotation_id)),\n        annotation: annotation\n            .as_ref()\n            .map(|a| convert_expr(a, type_hint_for_annotation_id)),\n        docstring: docstring.map(ToString::to_string),\n    }\n}\n\nfn convert_expr(expr: &ChunkExpr, type_hint_for_annotation_id: &HashMap<String, Expr>) -> Expr {\n    match expr {\n        ChunkExpr::Name { id } => Expr::Name { id: id.clone() },\n        ChunkExpr::Attribute { value, attr } => Expr::Attribute {\n            value: Box::new(convert_expr(value, type_hint_for_annotation_id)),\n            attr: attr.clone(),\n        },\n        ChunkExpr::BinOp { left, op, right } => Expr::BinOp {\n            left: Box::new(convert_expr(left, type_hint_for_annotation_id)),\n            op: match op {\n                ChunkOperator::BitOr => Operator::BitOr,\n            },\n            right: Box::new(convert_expr(right, type_hint_for_annotation_id)),\n        },\n        ChunkExpr::Subscript { value, slice } => Expr::Subscript {\n            value: Box::new(convert_expr(value, type_hint_for_annotation_id)),\n            slice: Box::new(convert_expr(slice, type_hint_for_annotation_id)),\n        },\n        ChunkExpr::Tuple { elts } => Expr::Tuple {\n            elts: elts\n                .iter()\n                .map(|e| convert_expr(e, type_hint_for_annotation_id))\n                .collect(),\n        },\n        ChunkExpr::List { elts } => Expr::List {\n            elts: elts\n                .iter()\n                .map(|e| convert_expr(e, type_hint_for_annotation_id))\n                .collect(),\n        },\n        ChunkExpr::Constant { value } => Expr::Constant {\n            value: match value {\n                ChunkConstant::None => Constant::None,\n                ChunkConstant::Bool { value } => Constant::Bool(*value),\n                ChunkConstant::Int { value } => Constant::Int(value.clone()),\n                ChunkConstant::Float { value } => Constant::Float(value.clone()),\n                ChunkConstant::Str { value } => Constant::Str(value.clone()),\n                ChunkConstant::Ellipsis => Constant::Ellipsis,\n            },\n        },\n        ChunkExpr::Id { id } => {\n            if let Some(expr) = type_hint_for_annotation_id.get(id) {\n                expr.clone()\n            } else {\n                // This is a pyclass not exposed, we fallback to Any\n                Expr::Attribute {\n                    value: Box::new(Expr::Name {\n                        id: \"typing\".into(),\n                    }),\n                    attr: \"Any\".to_string(),\n                }\n            }\n        }\n    }\n}\n\n/// Returns the type hint for each class introspection id defined in the module and its submodule\nfn introspection_id_to_type_hint_for_root_module(\n    module_chunk: &Chunk,\n    chunks_by_id: &HashMap<&str, &Chunk>,\n    chunks_by_parent: &HashMap<&str, Vec<&Chunk>>,\n) -> HashMap<String, Expr> {\n    fn add_introspection_id_to_type_hint_for_module_members(\n        module_id: &str,\n        module_full_name: &str,\n        module_members: &[String],\n        chunks_by_id: &HashMap<&str, &Chunk>,\n        chunks_by_parent: &HashMap<&str, Vec<&Chunk>>,\n        output: &mut HashMap<String, Expr>,\n    ) {\n        for member in chunks_by_parent\n            .get(&module_id)\n            .into_iter()\n            .flatten()\n            .chain(\n                module_members\n                    .iter()\n                    .filter_map(|id| chunks_by_id.get(id.as_str())),\n            )\n            .copied()\n        {\n            match member {\n                Chunk::Module {\n                    name, id, members, ..\n                } => {\n                    add_introspection_id_to_type_hint_for_module_members(\n                        id,\n                        &format!(\"{}.{}\", module_full_name, name),\n                        members,\n                        chunks_by_id,\n                        chunks_by_parent,\n                        output,\n                    );\n                }\n                Chunk::Class { id, name, .. } => {\n                    output.insert(\n                        id.clone(),\n                        Expr::Attribute {\n                            value: Box::new(Expr::Name {\n                                id: module_full_name.into(),\n                            }),\n                            attr: name.clone(),\n                        },\n                    );\n                    add_introspection_id_to_type_hint_for_class_subclasses(\n                        id,\n                        name,\n                        module_full_name,\n                        chunks_by_parent,\n                        output,\n                    );\n                }\n                _ => (),\n            }\n        }\n    }\n\n    fn add_introspection_id_to_type_hint_for_class_subclasses(\n        class_id: &str,\n        class_name: &str,\n        class_module: &str,\n        chunks_by_parent: &HashMap<&str, Vec<&Chunk>>,\n        output: &mut HashMap<String, Expr>,\n    ) {\n        for member in chunks_by_parent.get(&class_id).into_iter().flatten() {\n            if let Chunk::Class { id, name, .. } = member {\n                let class_name = format!(\"{}.{}\", class_name, name);\n                add_introspection_id_to_type_hint_for_class_subclasses(\n                    id,\n                    &class_name,\n                    class_module,\n                    chunks_by_parent,\n                    output,\n                );\n                output.insert(\n                    id.clone(),\n                    Expr::Attribute {\n                        value: Box::new(Expr::Name {\n                            id: class_module.into(),\n                        }),\n                        attr: class_name,\n                    },\n                );\n            }\n        }\n    }\n\n    let mut output = HashMap::new();\n    let Chunk::Module {\n        id, name, members, ..\n    } = module_chunk\n    else {\n        unreachable!(\"The chunk must be a module\")\n    };\n    add_introspection_id_to_type_hint_for_module_members(\n        id,\n        name,\n        members,\n        chunks_by_id,\n        chunks_by_parent,\n        &mut output,\n    );\n    output\n}\n\nfn find_introspection_chunks_in_binary_object(path: &Path) -> Result<Vec<Chunk>> {\n    let library_content =\n        fs::read(path).with_context(|| format!(\"Failed to read {}\", path.display()))?;\n    match Object::parse(&library_content)\n        .context(\"The built library is not valid or not supported by our binary parser\")?\n    {\n        Object::Elf(elf) => find_introspection_chunks_in_elf(&elf, &library_content),\n        Object::Mach(Mach::Binary(macho)) => {\n            find_introspection_chunks_in_macho(&macho, &library_content)\n        }\n        Object::Mach(Mach::Fat(multi_arch)) => {\n            for arch in &multi_arch {\n                match arch? {\n                    SingleArch::MachO(macho) => {\n                        return find_introspection_chunks_in_macho(&macho, &library_content)\n                    }\n                    SingleArch::Archive(_) => (),\n                }\n            }\n            bail!(\"No Mach-o chunk found in the multi-arch Mach-o container\")\n        }\n        Object::PE(pe) => find_introspection_chunks_in_pe(&pe, &library_content),\n        other => {\n            bail!(\n                \"Only ELF, Mach-o and PE containers can be introspected, got {other:?} from file {path:?}\",\n                path = path.display()\n            )\n        }\n    }\n}\n\nfn find_introspection_chunks_in_elf(elf: &Elf<'_>, library_content: &[u8]) -> Result<Vec<Chunk>> {\n    let mut chunks = Vec::new();\n    for sym in &elf.syms {\n        if is_introspection_symbol(elf.strtab.get_at(sym.st_name).unwrap_or_default()) {\n            ensure!(u32::try_from(sym.st_shndx)? != SHN_XINDEX, \"Section names length is greater than SHN_LORESERVE in ELF, this is not supported by PyO3 yet\");\n            let section_header = &elf.section_headers[sym.st_shndx];\n            let data_offset = sym.st_value + section_header.sh_offset - section_header.sh_addr;\n            chunks.push(deserialize_chunk(\n                &library_content[usize::try_from(data_offset).context(\"File offset overflow\")?..],\n                elf.little_endian,\n            )?);\n        }\n    }\n    Ok(chunks)\n}\n\nfn find_introspection_chunks_in_macho(\n    macho: &MachO<'_>,\n    library_content: &[u8],\n) -> Result<Vec<Chunk>> {\n    if !macho.little_endian {\n        bail!(\"Only little endian Mach-o binaries are supported\");\n    }\n    ensure!(\n        !macho.load_commands.iter().any(|command| {\n            matches!(command.command, CommandVariant::DyldChainedFixups(_))\n        }),\n        \"Mach-O binaries with fixup chains are not supported yet, to avoid using fixup chains, use `--codegen=link-arg=-no_fixup_chains` option.\"\n    );\n\n    let sections = macho\n        .segments\n        .sections()\n        .flatten()\n        .map(|t| t.map(|s| s.0))\n        .collect::<Result<Vec<_>, _>>()?;\n    let mut chunks = Vec::new();\n    for symbol in macho.symbols() {\n        let (name, nlist) = symbol?;\n        if nlist.is_global()\n            && nlist.get_type() == N_SECT\n            && nlist.n_sect != NO_SECT as usize\n            && is_introspection_symbol(name)\n        {\n            let section = &sections[nlist.n_sect - 1]; // Sections are counted from 1\n            let data_offset = nlist.n_value + u64::from(section.offset) - section.addr;\n            chunks.push(deserialize_chunk(\n                &library_content[usize::try_from(data_offset).context(\"File offset overflow\")?..],\n                macho.little_endian,\n            )?);\n        }\n    }\n    Ok(chunks)\n}\n\nfn find_introspection_chunks_in_pe(pe: &PE<'_>, library_content: &[u8]) -> Result<Vec<Chunk>> {\n    let mut chunks = Vec::new();\n    for export in &pe.exports {\n        if is_introspection_symbol(export.name.unwrap_or_default()) {\n            chunks.push(deserialize_chunk(\n                &library_content[export.offset.context(\"No symbol offset\")?..],\n                true,\n            )?);\n        }\n    }\n    Ok(chunks)\n}\n\nfn deserialize_chunk(\n    content_with_chunk_at_the_beginning: &[u8],\n    is_little_endian: bool,\n) -> Result<Chunk> {\n    let length = content_with_chunk_at_the_beginning\n        .split_at(4)\n        .0\n        .try_into()\n        .context(\"The introspection chunk must contain a length\")?;\n    let length = if is_little_endian {\n        u32::from_le_bytes(length)\n    } else {\n        u32::from_be_bytes(length)\n    };\n    let chunk = content_with_chunk_at_the_beginning\n        .get(4..4 + length as usize)\n        .ok_or_else(|| {\n            anyhow!(\"The introspection chunk length {length} is greater that the binary size\")\n        })?;\n    serde_json::from_slice(chunk).with_context(|| {\n        format!(\n            \"Failed to parse introspection chunk: {:?}\",\n            String::from_utf8_lossy(chunk)\n        )\n    })\n}\n\nfn is_introspection_symbol(name: &str) -> bool {\n    name.strip_prefix('_')\n        .unwrap_or(name)\n        .starts_with(\"PYO3_INTROSPECTION_1_\")\n}\n\n#[derive(Deserialize)]\n#[serde(tag = \"type\", rename_all = \"lowercase\")]\nenum Chunk {\n    Module {\n        id: String,\n        name: String,\n        members: Vec<String>,\n        #[serde(default)]\n        doc: Option<String>,\n        incomplete: bool,\n    },\n    Class {\n        id: String,\n        name: String,\n        #[serde(default)]\n        bases: Vec<ChunkExpr>,\n        #[serde(default)]\n        decorators: Vec<ChunkExpr>,\n        #[serde(default)]\n        parent: Option<String>,\n        #[serde(default)]\n        doc: Option<String>,\n    },\n    Function {\n        #[serde(default)]\n        id: Option<String>,\n        name: String,\n        arguments: Box<ChunkArguments>,\n        #[serde(default)]\n        parent: Option<String>,\n        #[serde(default)]\n        decorators: Vec<ChunkExpr>,\n        #[serde(default)]\n        returns: Option<ChunkExpr>,\n        #[serde(default, rename = \"async\")]\n        is_async: bool,\n        #[serde(default)]\n        doc: Option<String>,\n    },\n    Attribute {\n        #[serde(default)]\n        id: Option<String>,\n        #[serde(default)]\n        parent: Option<String>,\n        name: String,\n        #[serde(default)]\n        value: Option<ChunkExpr>,\n        #[serde(default)]\n        annotation: Option<ChunkExpr>,\n        #[serde(default)]\n        doc: Option<String>,\n    },\n}\n\n#[derive(Deserialize)]\nstruct ChunkArguments {\n    #[serde(default)]\n    posonlyargs: Vec<ChunkArgument>,\n    #[serde(default)]\n    args: Vec<ChunkArgument>,\n    #[serde(default)]\n    vararg: Option<ChunkArgument>,\n    #[serde(default)]\n    kwonlyargs: Vec<ChunkArgument>,\n    #[serde(default)]\n    kwarg: Option<ChunkArgument>,\n}\n\n#[derive(Deserialize)]\nstruct ChunkArgument {\n    name: String,\n    #[serde(default)]\n    default: Option<ChunkExpr>,\n    #[serde(default)]\n    annotation: Option<ChunkExpr>,\n}\n\n#[derive(Deserialize)]\n#[serde(tag = \"type\", rename_all = \"lowercase\")]\nenum ChunkExpr {\n    /// A constant like `None` or `123`\n    Constant {\n        #[serde(flatten)]\n        value: ChunkConstant,\n    },\n    /// A name\n    Name { id: String },\n    /// An attribute `value.attr`\n    Attribute { value: Box<Self>, attr: String },\n    /// A binary operator\n    BinOp {\n        left: Box<Self>,\n        op: ChunkOperator,\n        right: Box<Self>,\n    },\n    /// A tuple\n    Tuple { elts: Vec<Self> },\n    /// A list\n    List { elts: Vec<Self> },\n    /// A subscript `value[slice]`\n    Subscript { value: Box<Self>, slice: Box<Self> },\n    /// An introspection id\n    Id { id: String },\n}\n\n#[derive(Deserialize)]\n#[serde(tag = \"kind\", rename_all = \"lowercase\")]\npub enum ChunkConstant {\n    None,\n    Bool { value: bool },\n    Int { value: String },\n    Float { value: String },\n    Str { value: String },\n    Ellipsis,\n}\n\n#[derive(Deserialize)]\n#[serde(rename_all = \"lowercase\")]\npub enum ChunkOperator {\n    BitOr,\n}\n"
  },
  {
    "path": "pyo3-introspection/src/lib.rs",
    "content": "//! Utilities to introspect cdylib built using PyO3 and generate [type stubs](https://typing.readthedocs.io/en/latest/source/stubs.html).\n\npub use crate::introspection::introspect_cdylib;\npub use crate::stubs::module_stub_files;\n\nmod introspection;\npub mod model;\nmod stubs;\n"
  },
  {
    "path": "pyo3-introspection/src/model.rs",
    "content": "#[derive(Debug, Eq, PartialEq, Clone, Hash)]\npub struct Module {\n    pub name: String,\n    pub modules: Vec<Module>,\n    pub classes: Vec<Class>,\n    pub functions: Vec<Function>,\n    pub attributes: Vec<Attribute>,\n    pub incomplete: bool,\n    pub docstring: Option<String>,\n}\n\n#[derive(Debug, Eq, PartialEq, Clone, Hash)]\npub struct Class {\n    pub name: String,\n    pub bases: Vec<Expr>,\n    pub methods: Vec<Function>,\n    pub attributes: Vec<Attribute>,\n    /// decorator like 'typing.final'\n    pub decorators: Vec<Expr>,\n    pub inner_classes: Vec<Class>,\n    pub docstring: Option<String>,\n}\n\n#[derive(Debug, Eq, PartialEq, Clone, Hash)]\npub struct Function {\n    pub name: String,\n    /// decorator like 'property' or 'staticmethod'\n    pub decorators: Vec<Expr>,\n    pub arguments: Arguments,\n    /// return type\n    pub returns: Option<Expr>,\n    pub is_async: bool,\n    pub docstring: Option<String>,\n}\n\n#[derive(Debug, Eq, PartialEq, Clone, Hash)]\npub struct Attribute {\n    pub name: String,\n    /// Value as a Python expression if easily expressible\n    pub value: Option<Expr>,\n    /// Type annotation as a Python expression\n    pub annotation: Option<Expr>,\n    pub docstring: Option<String>,\n}\n\n#[derive(Debug, Eq, PartialEq, Clone, Hash)]\npub struct Arguments {\n    /// Arguments before /\n    pub positional_only_arguments: Vec<Argument>,\n    /// Regular arguments (between / and *)\n    pub arguments: Vec<Argument>,\n    /// *vararg\n    pub vararg: Option<VariableLengthArgument>,\n    /// Arguments after *\n    pub keyword_only_arguments: Vec<Argument>,\n    /// **kwarg\n    pub kwarg: Option<VariableLengthArgument>,\n}\n\n#[derive(Debug, Eq, PartialEq, Clone, Hash)]\npub struct Argument {\n    pub name: String,\n    /// Default value as a Python expression\n    pub default_value: Option<Expr>,\n    /// Type annotation as a Python expression\n    pub annotation: Option<Expr>,\n}\n\n/// A variable length argument ie. *vararg or **kwarg\n#[derive(Debug, Eq, PartialEq, Clone, Hash)]\npub struct VariableLengthArgument {\n    pub name: String,\n    /// Type annotation as a Python expression\n    pub annotation: Option<Expr>,\n}\n\n/// A python expression\n///\n/// This is the `expr` production of the [Python `ast` module grammar](https://docs.python.org/3/library/ast.html#abstract-grammar)\n#[derive(Debug, Eq, PartialEq, Clone, Hash)]\npub enum Expr {\n    /// A constant like `None` or `123`\n    Constant { value: Constant },\n    /// A name\n    Name { id: String },\n    /// An attribute `value.attr`\n    Attribute { value: Box<Self>, attr: String },\n    /// A binary operator\n    BinOp {\n        left: Box<Self>,\n        op: Operator,\n        right: Box<Self>,\n    },\n    /// A tuple\n    Tuple { elts: Vec<Self> },\n    /// A list\n    List { elts: Vec<Self> },\n    /// A subscript `value[slice]`\n    Subscript { value: Box<Self>, slice: Box<Self> },\n}\n\n/// A PyO3 extension to the Python AST to know more about [`Expr::Constant`].\n///\n/// This enables advanced features like escaping.\n#[derive(Debug, Eq, PartialEq, Clone, Hash)]\npub enum Constant {\n    /// `None`\n    None,\n    /// `True` or `False`\n    Bool(bool),\n    /// An integer in base 10\n    Int(String),\n    /// A float in base 10 (does not include Inf and NaN)\n    Float(String),\n    /// A string (unescaped!)\n    Str(String),\n    /// `...`\n    Ellipsis,\n}\n\n/// An operator used in [`Expr::BinOp`].\n#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]\npub enum Operator {\n    /// `|` operator\n    BitOr,\n}\n"
  },
  {
    "path": "pyo3-introspection/src/stubs.rs",
    "content": "use crate::model::{\n    Argument, Arguments, Attribute, Class, Constant, Expr, Function, Module, Operator,\n    VariableLengthArgument,\n};\nuse std::collections::{BTreeMap, BTreeSet, HashMap};\nuse std::fmt::Write;\nuse std::iter::once;\nuse std::path::PathBuf;\nuse std::str::FromStr;\n\n/// Generates the [type stubs](https://typing.readthedocs.io/en/latest/source/stubs.html) of a given module.\n/// It returns a map between the file name and the file content.\n/// The root module stubs will be in the `__init__.pyi` file and the submodules directory\n/// in files with a relevant name.\npub fn module_stub_files(module: &Module) -> HashMap<PathBuf, String> {\n    let mut output_files = HashMap::new();\n    add_module_stub_files(module, &[], &mut output_files);\n    output_files\n}\n\nfn add_module_stub_files(\n    module: &Module,\n    module_path: &[&str],\n    output_files: &mut HashMap<PathBuf, String>,\n) {\n    let mut file_path = PathBuf::new();\n    for e in module_path {\n        file_path = file_path.join(e);\n    }\n    output_files.insert(\n        file_path.join(\"__init__.pyi\"),\n        module_stubs(module, module_path),\n    );\n    let mut module_path = module_path.to_vec();\n    module_path.push(&module.name);\n    for submodule in &module.modules {\n        if submodule.modules.is_empty() {\n            output_files.insert(\n                file_path.join(format!(\"{}.pyi\", submodule.name)),\n                module_stubs(submodule, &module_path),\n            );\n        } else {\n            add_module_stub_files(submodule, &module_path, output_files);\n        }\n    }\n}\n\n/// Generates the module stubs to a String, not including submodules\nfn module_stubs(module: &Module, parents: &[&str]) -> String {\n    let imports = Imports::create(module, parents);\n    let mut elements = Vec::new();\n    for attribute in &module.attributes {\n        elements.push(attribute_stubs(attribute, &imports));\n    }\n    for class in &module.classes {\n        elements.push(class_stubs(class, &imports));\n    }\n    for function in &module.functions {\n        elements.push(function_stubs(function, &imports, None));\n    }\n\n    // We generate a __getattr__ method to tag incomplete stubs\n    // See https://typing.python.org/en/latest/guides/writing_stubs.html#incomplete-stubs\n    if module.incomplete && !module.functions.iter().any(|f| f.name == \"__getattr__\") {\n        elements.push(function_stubs(\n            &Function {\n                name: \"__getattr__\".into(),\n                decorators: Vec::new(),\n                arguments: Arguments {\n                    positional_only_arguments: Vec::new(),\n                    arguments: vec![Argument {\n                        name: \"name\".to_string(),\n                        default_value: None,\n                        annotation: Some(Expr::Name { id: \"str\".into() }),\n                    }],\n                    vararg: None,\n                    keyword_only_arguments: Vec::new(),\n                    kwarg: None,\n                },\n                returns: Some(Expr::Attribute {\n                    value: Box::new(Expr::Name {\n                        id: \"_typeshed\".into(),\n                    }),\n                    attr: \"Incomplete\".into(),\n                }),\n                is_async: false,\n                docstring: None,\n            },\n            &imports,\n            None,\n        ));\n    }\n\n    let mut final_elements = Vec::new();\n    if let Some(docstring) = &module.docstring {\n        final_elements.push(format!(\"\\\"\\\"\\\"\\n{docstring}\\n\\\"\\\"\\\"\"));\n    }\n    final_elements.extend(imports.imports);\n    final_elements.extend(elements);\n\n    let mut output = String::new();\n\n    // We insert two line jumps (i.e. empty strings) only above and below multiple line elements (classes with methods, functions with decorators)\n    for element in final_elements {\n        let is_multiline = element.contains('\\n');\n        if is_multiline && !output.is_empty() && !output.ends_with(\"\\n\\n\") {\n            output.push('\\n');\n        }\n        output.push_str(&element);\n        output.push('\\n');\n        if is_multiline {\n            output.push('\\n');\n        }\n    }\n\n    // We remove a line jump at the end if they are two\n    if output.ends_with(\"\\n\\n\") {\n        output.pop();\n    }\n    output\n}\n\nfn class_stubs(class: &Class, imports: &Imports) -> String {\n    let mut buffer = String::new();\n    for decorator in &class.decorators {\n        buffer.push('@');\n        imports.serialize_expr(decorator, &mut buffer);\n        buffer.push('\\n');\n    }\n    buffer.push_str(\"class \");\n    buffer.push_str(&class.name);\n    if !class.bases.is_empty() {\n        buffer.push('(');\n        for (i, base) in class.bases.iter().enumerate() {\n            if i > 0 {\n                buffer.push_str(\", \");\n            }\n            imports.serialize_expr(base, &mut buffer);\n        }\n        buffer.push(')');\n    }\n    buffer.push(':');\n    if class.docstring.is_none()\n        && class.methods.is_empty()\n        && class.attributes.is_empty()\n        && class.inner_classes.is_empty()\n    {\n        buffer.push_str(\" ...\");\n    }\n    if let Some(docstring) = &class.docstring {\n        buffer.push_str(\"\\n    \\\"\\\"\\\"\");\n        for line in docstring.lines() {\n            buffer.push_str(\"\\n    \");\n            buffer.push_str(line);\n        }\n        buffer.push_str(\"\\n    \\\"\\\"\\\"\");\n    }\n    for attribute in &class.attributes {\n        // We do the indentation\n        buffer.push_str(\"\\n    \");\n        buffer.push_str(&attribute_stubs(attribute, imports).replace('\\n', \"\\n    \"));\n    }\n    for method in &class.methods {\n        // We do the indentation\n        buffer.push_str(\"\\n    \");\n        buffer\n            .push_str(&function_stubs(method, imports, Some(&class.name)).replace('\\n', \"\\n    \"));\n    }\n    for inner_class in &class.inner_classes {\n        // We do the indentation\n        buffer.push_str(\"\\n    \");\n        buffer.push_str(&class_stubs(inner_class, imports).replace('\\n', \"\\n    \"));\n    }\n    buffer\n}\n\nfn function_stubs(function: &Function, imports: &Imports, class_name: Option<&str>) -> String {\n    // Signature\n    let mut parameters = Vec::new();\n    for argument in &function.arguments.positional_only_arguments {\n        parameters.push(argument_stub(argument, imports));\n    }\n    if !function.arguments.positional_only_arguments.is_empty() {\n        parameters.push(\"/\".into());\n    }\n    for argument in &function.arguments.arguments {\n        parameters.push(argument_stub(argument, imports));\n    }\n    if let Some(argument) = &function.arguments.vararg {\n        parameters.push(format!(\n            \"*{}\",\n            variable_length_argument_stub(argument, imports)\n        ));\n    } else if !function.arguments.keyword_only_arguments.is_empty() {\n        parameters.push(\"*\".into());\n    }\n    for argument in &function.arguments.keyword_only_arguments {\n        parameters.push(argument_stub(argument, imports));\n    }\n    if let Some(argument) = &function.arguments.kwarg {\n        parameters.push(format!(\n            \"**{}\",\n            variable_length_argument_stub(argument, imports)\n        ));\n    }\n    let mut buffer = String::new();\n    for decorator in &function.decorators {\n        buffer.push('@');\n        // We remove the class name if it's a prefix to get nicer decorators\n        let mut decorator_buffer = String::new();\n        imports.serialize_expr(decorator, &mut decorator_buffer);\n        if let Some(class_name) = class_name {\n            if let Some(decorator) = decorator_buffer.strip_prefix(&format!(\"{class_name}.\")) {\n                decorator_buffer = decorator.into();\n            }\n        }\n        buffer.push_str(&decorator_buffer);\n        buffer.push('\\n');\n    }\n    if function.is_async {\n        buffer.push_str(\"async \");\n    }\n\n    buffer.push_str(\"def \");\n    buffer.push_str(&function.name);\n    buffer.push('(');\n    buffer.push_str(&parameters.join(\", \"));\n    buffer.push(')');\n    if let Some(returns) = &function.returns {\n        buffer.push_str(\" -> \");\n        imports.serialize_expr(returns, &mut buffer);\n    }\n    if let Some(docstring) = &function.docstring {\n        buffer.push_str(\":\\n    \\\"\\\"\\\"\");\n        for line in docstring.lines() {\n            buffer.push_str(\"\\n    \");\n            buffer.push_str(line);\n        }\n        buffer.push_str(\"\\n    \\\"\\\"\\\"\");\n    } else {\n        buffer.push_str(\": ...\");\n    }\n    buffer\n}\n\nfn attribute_stubs(attribute: &Attribute, imports: &Imports) -> String {\n    let mut buffer = attribute.name.clone();\n    if let Some(annotation) = &attribute.annotation {\n        buffer.push_str(\": \");\n        imports.serialize_expr(annotation, &mut buffer);\n    }\n    if let Some(value) = &attribute.value {\n        buffer.push_str(\" = \");\n        imports.serialize_expr(value, &mut buffer);\n    }\n    if let Some(docstring) = &attribute.docstring {\n        buffer.push_str(\"\\n\\\"\\\"\\\"\");\n        for line in docstring.lines() {\n            buffer.push('\\n');\n            buffer.push_str(line);\n        }\n        buffer.push_str(\"\\n\\\"\\\"\\\"\");\n    }\n    buffer\n}\n\nfn argument_stub(argument: &Argument, imports: &Imports) -> String {\n    let mut buffer = argument.name.clone();\n    if let Some(annotation) = &argument.annotation {\n        buffer.push_str(\": \");\n        imports.serialize_expr(annotation, &mut buffer);\n    }\n    if let Some(default_value) = &argument.default_value {\n        buffer.push_str(if argument.annotation.is_some() {\n            \" = \"\n        } else {\n            \"=\"\n        });\n        imports.serialize_expr(default_value, &mut buffer);\n    }\n    buffer\n}\n\nfn variable_length_argument_stub(argument: &VariableLengthArgument, imports: &Imports) -> String {\n    let mut buffer = argument.name.clone();\n    if let Some(annotation) = &argument.annotation {\n        buffer.push_str(\": \");\n        imports.serialize_expr(annotation, &mut buffer);\n    }\n    buffer\n}\n\n/// Datastructure to deduplicate, validate and generate imports\n#[derive(Default)]\nstruct Imports {\n    /// Import lines ready to use\n    imports: Vec<String>,\n    /// Renaming map: from module name and member name return the name to use in type hints\n    renaming: BTreeMap<(String, String), String>,\n}\n\nimpl Imports {\n    /// This generates a map from the builtin or module name to the actual alias used in the file\n    ///\n    /// For Python builtins and elements declared by the module the alias is always the actual name.\n    ///\n    /// For other elements, we can alias them using the `from X import Y as Z` syntax.\n    /// So, we first list all builtins and local elements, then iterate on imports\n    /// and create the aliases when needed.\n    fn create(module: &Module, module_parents: &[&str]) -> Self {\n        let mut elements_used_in_annotations = ElementsUsedInAnnotations::new();\n        elements_used_in_annotations.walk_module(module);\n\n        let mut imports = Vec::new();\n        let mut renaming = BTreeMap::new();\n        let mut local_name_to_module_and_attribute = BTreeMap::new();\n\n        // We get the current module full name\n        let current_module_name = module_parents\n            .iter()\n            .copied()\n            .chain(once(module.name.as_str()))\n            .collect::<Vec<_>>()\n            .join(\".\");\n\n        // We first list local elements, they are never aliased or imported\n        for name in module\n            .classes\n            .iter()\n            .map(|c| c.name.clone())\n            .chain(module.functions.iter().map(|f| f.name.clone()))\n            .chain(module.attributes.iter().map(|a| a.name.clone()))\n        {\n            local_name_to_module_and_attribute\n                .insert(name.clone(), (current_module_name.clone(), name.clone()));\n        }\n        // We don't process the current module elements, no need to care about them\n        local_name_to_module_and_attribute.remove(&current_module_name);\n\n        // We process then imports, normalizing local imports\n        for (module, attrs) in &elements_used_in_annotations.module_to_name {\n            let mut import_for_module = Vec::new();\n            for attr in attrs {\n                // We split nested classes A.B in \"A\" (the part that must be imported and can have naming conflicts) and \".B\"\n                let (root_attr, attr_path) = attr\n                    .split_once('.')\n                    .map_or((attr.as_str(), None), |(root, path)| (root, Some(path)));\n                let mut local_name = root_attr.to_owned();\n                let mut already_imported = false;\n                while let Some((possible_conflict_module, possible_conflict_attr)) =\n                    local_name_to_module_and_attribute.get(&local_name)\n                {\n                    if possible_conflict_module == module && *possible_conflict_attr == root_attr {\n                        // It's the same\n                        already_imported = true;\n                        break;\n                    }\n                    // We generate a new local name\n                    // TODO: we use currently a format like Foo2. It might be nicer to use something like ModFoo\n                    let number_of_digits_at_the_end = local_name\n                        .bytes()\n                        .rev()\n                        .take_while(|b| b.is_ascii_digit())\n                        .count();\n                    let (local_name_prefix, local_name_number) =\n                        local_name.split_at(local_name.len() - number_of_digits_at_the_end);\n                    local_name = format!(\n                        \"{local_name_prefix}{}\",\n                        u64::from_str(local_name_number).unwrap_or(1) + 1\n                    );\n                }\n                renaming.insert(\n                    (module.clone(), attr.clone()),\n                    if let Some(attr_path) = attr_path {\n                        format!(\"{local_name}.{attr_path}\")\n                    } else {\n                        local_name.clone()\n                    },\n                );\n                if !already_imported {\n                    local_name_to_module_and_attribute\n                        .insert(local_name.clone(), (module.clone(), root_attr.to_owned()));\n                    let is_not_aliased_builtin = module == \"builtins\" && local_name == root_attr;\n                    if !is_not_aliased_builtin {\n                        import_for_module.push(if local_name == root_attr {\n                            local_name\n                        } else {\n                            format!(\"{root_attr} as {local_name}\")\n                        });\n                    }\n                }\n            }\n            if !import_for_module.is_empty() {\n                imports.push(format!(\n                    \"from {module} import {}\",\n                    import_for_module.join(\", \")\n                ));\n            }\n        }\n        imports.sort(); // We make sure they are sorted\n\n        Self { imports, renaming }\n    }\n\n    fn serialize_expr(&self, expr: &Expr, buffer: &mut String) {\n        match expr {\n            Expr::Constant { value } => match value {\n                Constant::None => buffer.push_str(\"None\"),\n                Constant::Bool(value) => buffer.push_str(if *value { \"True\" } else { \"False\" }),\n                Constant::Int(value) => buffer.push_str(value),\n                Constant::Float(value) => {\n                    buffer.push_str(value);\n                    if !value.contains(['.', 'e', 'E']) {\n                        buffer.push('.'); // We make sure it's not parsed as an int\n                    }\n                }\n                Constant::Str(value) => {\n                    buffer.push('\"');\n                    for c in value.chars() {\n                        match c {\n                            '\"' => buffer.push_str(\"\\\\\\\"\"),\n                            '\\n' => buffer.push_str(\"\\\\n\"),\n                            '\\r' => buffer.push_str(\"\\\\r\"),\n                            '\\t' => buffer.push_str(\"\\\\t\"),\n                            '\\\\' => buffer.push_str(\"\\\\\\\\\"),\n                            '\\0' => buffer.push_str(\"\\\\0\"),\n                            c @ '\\x00'..'\\x20' => {\n                                write!(buffer, \"\\\\x{:02x}\", u32::from(c)).unwrap()\n                            }\n                            c => buffer.push(c),\n                        }\n                    }\n                    buffer.push('\"');\n                }\n                Constant::Ellipsis => buffer.push_str(\"...\"),\n            },\n            Expr::Name { id } => {\n                buffer.push_str(\n                    self.renaming\n                        .get(&(\"builtins\".into(), id.clone()))\n                        .expect(\"All type hint attributes should have been visited\"),\n                );\n            }\n            Expr::Attribute { value, attr } => {\n                if let Expr::Name { id, .. } = &**value {\n                    buffer.push_str(\n                        self.renaming\n                            .get(&(id.clone(), attr.clone()))\n                            .expect(\"All type hint attributes should have been visited\"),\n                    );\n                } else {\n                    self.serialize_expr(value, buffer);\n                    buffer.push('.');\n                    buffer.push_str(attr);\n                }\n            }\n            Expr::BinOp { left, op, right } => {\n                self.serialize_expr(left, buffer);\n                buffer.push(' ');\n                buffer.push(match op {\n                    Operator::BitOr => '|',\n                });\n                self.serialize_expr(right, buffer);\n            }\n            Expr::Tuple { elts } => {\n                buffer.push('(');\n                self.serialize_elts(elts, buffer);\n                if elts.len() == 1 {\n                    buffer.push(',');\n                }\n                buffer.push(')')\n            }\n            Expr::List { elts } => {\n                buffer.push('[');\n                self.serialize_elts(elts, buffer);\n                buffer.push(']')\n            }\n            Expr::Subscript { value, slice } => {\n                self.serialize_expr(value, buffer);\n                buffer.push('[');\n                if let Expr::Tuple { elts } = &**slice {\n                    // We don't display the tuple parentheses\n                    self.serialize_elts(elts, buffer);\n                } else {\n                    self.serialize_expr(slice, buffer);\n                }\n                buffer.push(']');\n            }\n        }\n    }\n\n    fn serialize_elts(&self, elts: &[Expr], buffer: &mut String) {\n        for (i, elt) in elts.iter().enumerate() {\n            if i > 0 {\n                buffer.push_str(\", \");\n            }\n            self.serialize_expr(elt, buffer);\n        }\n    }\n}\n\n/// Lists all the elements used in annotations\nstruct ElementsUsedInAnnotations {\n    /// module -> name where module is global (from the root of the interpreter).\n    module_to_name: BTreeMap<String, BTreeSet<String>>,\n}\n\nimpl ElementsUsedInAnnotations {\n    fn new() -> Self {\n        Self {\n            module_to_name: BTreeMap::new(),\n        }\n    }\n\n    fn walk_module(&mut self, module: &Module) {\n        for attr in &module.attributes {\n            self.walk_attribute(attr);\n        }\n        for class in &module.classes {\n            self.walk_class(class);\n        }\n        for function in &module.functions {\n            self.walk_function(function);\n        }\n        if module.incomplete {\n            self.module_to_name\n                .entry(\"builtins\".into())\n                .or_default()\n                .insert(\"str\".into());\n            self.module_to_name\n                .entry(\"_typeshed\".into())\n                .or_default()\n                .insert(\"Incomplete\".into());\n        }\n    }\n\n    fn walk_class(&mut self, class: &Class) {\n        for base in &class.bases {\n            self.walk_expr(base);\n        }\n        for decorator in &class.decorators {\n            self.walk_expr(decorator);\n        }\n        for method in &class.methods {\n            self.walk_function(method);\n        }\n        for attr in &class.attributes {\n            self.walk_attribute(attr);\n        }\n        for class in &class.inner_classes {\n            self.walk_class(class);\n        }\n    }\n\n    fn walk_attribute(&mut self, attribute: &Attribute) {\n        if let Some(type_hint) = &attribute.annotation {\n            self.walk_expr(type_hint);\n        }\n    }\n\n    fn walk_function(&mut self, function: &Function) {\n        for decorator in &function.decorators {\n            self.walk_expr(decorator);\n        }\n        for arg in function\n            .arguments\n            .positional_only_arguments\n            .iter()\n            .chain(&function.arguments.arguments)\n            .chain(&function.arguments.keyword_only_arguments)\n        {\n            if let Some(type_hint) = &arg.annotation {\n                self.walk_expr(type_hint);\n            }\n        }\n        for arg in function\n            .arguments\n            .vararg\n            .as_ref()\n            .iter()\n            .chain(&function.arguments.kwarg.as_ref())\n        {\n            if let Some(type_hint) = &arg.annotation {\n                self.walk_expr(type_hint);\n            }\n        }\n        if let Some(type_hint) = &function.returns {\n            self.walk_expr(type_hint);\n        }\n    }\n\n    fn walk_expr(&mut self, expr: &Expr) {\n        match expr {\n            Expr::Name { id } => {\n                self.module_to_name\n                    .entry(\"builtins\".into())\n                    .or_default()\n                    .insert(id.clone());\n            }\n            Expr::Attribute { value, attr } => {\n                if let Expr::Name { id } = &**value {\n                    self.module_to_name\n                        .entry(id.into())\n                        .or_default()\n                        .insert(attr.clone());\n                } else {\n                    self.walk_expr(value)\n                }\n            }\n            Expr::BinOp { left, right, .. } => {\n                self.walk_expr(left);\n                self.walk_expr(right);\n            }\n            Expr::Subscript { value, slice } => {\n                self.walk_expr(value);\n                self.walk_expr(slice);\n            }\n            Expr::Tuple { elts } | Expr::List { elts } => {\n                for elt in elts {\n                    self.walk_expr(elt)\n                }\n            }\n            Expr::Constant { .. } => (),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::model::Arguments;\n\n    #[test]\n    fn function_stubs_with_variable_length() {\n        let function = Function {\n            name: \"func\".into(),\n            decorators: Vec::new(),\n            arguments: Arguments {\n                positional_only_arguments: vec![Argument {\n                    name: \"posonly\".into(),\n                    default_value: None,\n                    annotation: None,\n                }],\n                arguments: vec![Argument {\n                    name: \"arg\".into(),\n                    default_value: None,\n                    annotation: None,\n                }],\n                vararg: Some(VariableLengthArgument {\n                    name: \"varargs\".into(),\n                    annotation: None,\n                }),\n                keyword_only_arguments: vec![Argument {\n                    name: \"karg\".into(),\n                    default_value: None,\n                    annotation: Some(Expr::Constant {\n                        value: Constant::Str(\"str\".into()),\n                    }),\n                }],\n                kwarg: Some(VariableLengthArgument {\n                    name: \"kwarg\".into(),\n                    annotation: Some(Expr::Constant {\n                        value: Constant::Str(\"str\".into()),\n                    }),\n                }),\n            },\n            returns: Some(Expr::Constant {\n                value: Constant::Str(\"list[str]\".into()),\n            }),\n            is_async: false,\n            docstring: None,\n        };\n        assert_eq!(\n            \"def func(posonly, /, arg, *varargs, karg: \\\"str\\\", **kwarg: \\\"str\\\") -> \\\"list[str]\\\": ...\",\n            function_stubs(&function, &Imports::default(), None)\n        )\n    }\n\n    #[test]\n    fn function_stubs_without_variable_length() {\n        let function = Function {\n            name: \"afunc\".into(),\n            decorators: Vec::new(),\n            arguments: Arguments {\n                positional_only_arguments: vec![Argument {\n                    name: \"posonly\".into(),\n                    default_value: Some(Expr::Constant {\n                        value: Constant::Int(\"1\".into()),\n                    }),\n                    annotation: None,\n                }],\n                arguments: vec![Argument {\n                    name: \"arg\".into(),\n                    default_value: Some(Expr::Constant {\n                        value: Constant::Bool(true),\n                    }),\n                    annotation: None,\n                }],\n                vararg: None,\n                keyword_only_arguments: vec![Argument {\n                    name: \"karg\".into(),\n                    default_value: Some(Expr::Constant {\n                        value: Constant::Str(\"foo\".into()),\n                    }),\n                    annotation: Some(Expr::Constant {\n                        value: Constant::Str(\"str\".into()),\n                    }),\n                }],\n                kwarg: None,\n            },\n            returns: None,\n            is_async: false,\n            docstring: None,\n        };\n        assert_eq!(\n            \"def afunc(posonly=1, /, arg=True, *, karg: \\\"str\\\" = \\\"foo\\\"): ...\",\n            function_stubs(&function, &Imports::default(), None)\n        )\n    }\n\n    #[test]\n    fn test_function_async() {\n        let function = Function {\n            name: \"foo\".into(),\n            decorators: Vec::new(),\n            arguments: Arguments {\n                positional_only_arguments: Vec::new(),\n                arguments: Vec::new(),\n                vararg: None,\n                keyword_only_arguments: Vec::new(),\n                kwarg: None,\n            },\n            returns: None,\n            is_async: true,\n            docstring: None,\n        };\n        assert_eq!(\n            \"async def foo(): ...\",\n            function_stubs(&function, &Imports::default(), None)\n        )\n    }\n\n    #[test]\n    fn test_import() {\n        let big_type = Expr::Subscript {\n            value: Box::new(Expr::Name { id: \"dict\".into() }),\n            slice: Box::new(Expr::Tuple {\n                elts: vec![\n                    Expr::Attribute {\n                        value: Box::new(Expr::Name {\n                            id: \"foo.bar\".into(),\n                        }),\n                        attr: \"A\".into(),\n                    },\n                    Expr::Tuple {\n                        elts: vec![\n                            Expr::Attribute {\n                                value: Box::new(Expr::Name { id: \"foo\".into() }),\n                                attr: \"A.C\".into(),\n                            },\n                            Expr::Attribute {\n                                value: Box::new(Expr::Attribute {\n                                    value: Box::new(Expr::Name { id: \"foo\".into() }),\n                                    attr: \"A\".into(),\n                                }),\n                                attr: \"D\".into(),\n                            },\n                            Expr::Attribute {\n                                value: Box::new(Expr::Name { id: \"foo\".into() }),\n                                attr: \"B\".into(),\n                            },\n                            Expr::Attribute {\n                                value: Box::new(Expr::Name { id: \"bat\".into() }),\n                                attr: \"A\".into(),\n                            },\n                            Expr::Attribute {\n                                value: Box::new(Expr::Name {\n                                    id: \"foo.bar\".into(),\n                                }),\n                                attr: \"int\".into(),\n                            },\n                            Expr::Name { id: \"int\".into() },\n                            Expr::Name { id: \"float\".into() },\n                        ],\n                    },\n                ],\n            }),\n        };\n        let imports = Imports::create(\n            &Module {\n                name: \"bar\".into(),\n                modules: Vec::new(),\n                classes: vec![\n                    Class {\n                        name: \"A\".into(),\n                        bases: vec![Expr::Name { id: \"dict\".into() }],\n                        methods: Vec::new(),\n                        attributes: Vec::new(),\n                        decorators: vec![Expr::Attribute {\n                            value: Box::new(Expr::Name {\n                                id: \"typing\".into(),\n                            }),\n                            attr: \"final\".into(),\n                        }],\n                        inner_classes: Vec::new(),\n                        docstring: None,\n                    },\n                    Class {\n                        name: \"int\".into(),\n                        bases: Vec::new(),\n                        methods: Vec::new(),\n                        attributes: Vec::new(),\n                        decorators: Vec::new(),\n                        inner_classes: Vec::new(),\n                        docstring: None,\n                    },\n                ],\n                functions: vec![Function {\n                    name: String::new(),\n                    decorators: Vec::new(),\n                    arguments: Arguments {\n                        positional_only_arguments: Vec::new(),\n                        arguments: Vec::new(),\n                        vararg: None,\n                        keyword_only_arguments: Vec::new(),\n                        kwarg: None,\n                    },\n                    returns: Some(big_type.clone()),\n                    is_async: false,\n                    docstring: None,\n                }],\n                attributes: Vec::new(),\n                incomplete: true,\n                docstring: None,\n            },\n            &[\"foo\"],\n        );\n        assert_eq!(\n            &imports.imports,\n            &[\n                \"from _typeshed import Incomplete\",\n                \"from bat import A as A2\",\n                \"from builtins import int as int2\",\n                \"from foo import A as A3, B\",\n                \"from typing import final\"\n            ]\n        );\n        let mut output = String::new();\n        imports.serialize_expr(&big_type, &mut output);\n        assert_eq!(output, \"dict[A, (A3.C, A3.D, B, A2, int, int2, float)]\");\n    }\n}\n"
  },
  {
    "path": "pyo3-introspection/tests/test.rs",
    "content": "use anyhow::{ensure, Result};\nuse pyo3_introspection::{introspect_cdylib, module_stub_files};\nuse std::collections::HashMap;\nuse std::io::{Read, Seek, SeekFrom, Write};\nuse std::path::{Path, PathBuf};\nuse std::process::Command;\nuse std::{env, fs};\nuse tempfile::NamedTempFile;\n\n#[test]\nfn pytests_stubs() -> Result<()> {\n    // We run the introspection\n    let binary = env::var_os(\"PYO3_PYTEST_LIB_PATH\")\n        .expect(\"The PYO3_PYTEST_LIB_PATH constant must be set and target the pyo3-pytests cdylib\");\n    let module = introspect_cdylib(binary, \"pyo3_pytests\")?;\n    let actual_stubs = module_stub_files(&module);\n\n    // We read the expected stubs\n    let expected_subs_dir = Path::new(env!(\"CARGO_MANIFEST_DIR\"))\n        .parent()\n        .unwrap()\n        .join(\"pytests\")\n        .join(\"stubs\");\n    let mut expected_subs = HashMap::new();\n    add_dir_files(\n        &expected_subs_dir,\n        &expected_subs_dir.canonicalize()?,\n        &mut expected_subs,\n    )?;\n\n    // We ensure we do not have extra generated files\n    for file_name in actual_stubs.keys() {\n        assert!(\n            expected_subs.contains_key(file_name),\n            \"The generated file {} is not in the expected stubs directory pytests/stubs\",\n            file_name.display()\n        );\n    }\n\n    // We ensure the expected files are generated properly\n    for (file_name, expected_file_content) in &expected_subs {\n        let actual_file_content = actual_stubs.get(file_name).unwrap_or_else(|| {\n            panic!(\n                \"The expected stub file {} has not been generated\",\n                file_name.display()\n            )\n        });\n\n        let actual_file_content = format_with_ruff(actual_file_content)?;\n\n        // We normalize line jumps for compatibility with Windows\n        assert_eq!(\n            expected_file_content.replace('\\r', \"\"),\n            actual_file_content.replace('\\r', \"\"),\n            \"The content of file {} is different\",\n            file_name.display()\n        )\n    }\n\n    Ok(())\n}\n\nfn add_dir_files(\n    dir_path: &Path,\n    base_dir_path: &Path,\n    output: &mut HashMap<PathBuf, String>,\n) -> Result<()> {\n    for entry in fs::read_dir(dir_path)? {\n        let entry = entry?;\n        if entry.file_type()?.is_dir() {\n            add_dir_files(&entry.path(), base_dir_path, output)?;\n        } else {\n            output.insert(\n                entry\n                    .path()\n                    .canonicalize()?\n                    .strip_prefix(base_dir_path)?\n                    .into(),\n                fs::read_to_string(entry.path())?,\n            );\n        }\n    }\n    Ok(())\n}\n\nfn format_with_ruff(code: &str) -> Result<String> {\n    let temp_file = NamedTempFile::with_suffix(\".pyi\")?;\n    // Write to file\n    {\n        let mut file = temp_file.as_file();\n        file.write_all(code.as_bytes())?;\n        file.flush()?;\n        file.seek(SeekFrom::Start(0))?;\n    }\n    ensure!(\n        Command::new(\"ruff\")\n            .arg(\"format\")\n            .arg(temp_file.path())\n            .status()?\n            .success(),\n        \"Failed to run ruff\"\n    );\n    let mut content = String::new();\n    temp_file.as_file().read_to_string(&mut content)?;\n    Ok(content)\n}\n"
  },
  {
    "path": "pyo3-macros/Cargo.toml",
    "content": "[package]\nname = \"pyo3-macros\"\nversion = \"0.28.2\"\ndescription = \"Proc macros for PyO3 package\"\nauthors = [\"PyO3 Project and Contributors <https://github.com/PyO3>\"]\nkeywords = [\"pyo3\", \"python\", \"cpython\", \"ffi\"]\nhomepage = \"https://github.com/pyo3/pyo3\"\nrepository = \"https://github.com/pyo3/pyo3\"\ncategories = [\"api-bindings\", \"development-tools::ffi\"]\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version.workspace = true\n\n[lib]\nproc-macro = true\n\n[features]\nmultiple-pymethods = []\nexperimental-async = [\"pyo3-macros-backend/experimental-async\"]\nexperimental-inspect = [\"pyo3-macros-backend/experimental-inspect\"]\n\n[dependencies]\nproc-macro2 = { version = \"1.0.60\", default-features = false }\nquote = \"1\"\nsyn = { version = \"2\", features = [\"full\", \"extra-traits\"] }\npyo3-macros-backend = { path = \"../pyo3-macros-backend\", version = \"=0.28.2\" }\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "pyo3-macros/src/lib.rs",
    "content": "//! This crate declares only the proc macro attributes, as a crate defining proc macro attributes\n//! must not contain any other public items.\n\n#![cfg_attr(docsrs, feature(doc_cfg))]\nuse proc_macro::TokenStream;\nuse proc_macro2::TokenStream as TokenStream2;\nuse pyo3_macros_backend::{\n    build_derive_from_pyobject, build_derive_into_pyobject, build_py_class, build_py_enum,\n    build_py_function, build_py_methods, pymodule_function_impl, pymodule_module_impl, PyClassArgs,\n    PyClassMethodsType, PyFunctionOptions, PyModuleOptions,\n};\nuse quote::quote;\nuse syn::{parse_macro_input, Item};\n\n/// A proc macro used to implement Python modules.\n///\n/// The name of the module will be taken from the function name, unless `#[pyo3(name = \"my_name\")]`\n/// is also annotated on the function to override the name. **Important**: the module name should\n/// match the `lib.name` setting in `Cargo.toml`, so that Python is able to import the module\n/// without needing a custom import loader.\n///\n/// Functions annotated with `#[pymodule]` can also be annotated with the following:\n///\n/// |  Annotation  |  Description |\n/// | :-  | :- |\n/// | `#[pyo3(name = \"...\")]` | Defines the name of the module in Python. |\n/// | `#[pyo3(submodule)]`    | Skips adding a `PyInit_` FFI symbol to the compiled binary. |\n/// | `#[pyo3(module = \"...\")]` | Defines the Python `dotted.path` to the parent module for use in introspection. |\n/// | `#[pyo3(crate = \"pyo3\")]` | Defines the path to PyO3 to use code generated by the macro. |\n/// | `#[pyo3(gil_used = true)]` | Declares the GIL is needed to run this module safely under free-threaded Python. |\n///\n/// For more on creating Python modules see the [module section of the guide][1].\n///\n/// Due to technical limitations on how `#[pymodule]` is implemented, a function marked\n/// `#[pymodule]` cannot have a module with the same name in the same scope. (The\n/// `#[pymodule]` implementation generates a hidden module with the same name containing\n/// metadata about the module, which is used by `wrap_pymodule!`).\n///\n#[doc = concat!(\"[1]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/module.html\")]\n#[proc_macro_attribute]\npub fn pymodule(args: TokenStream, input: TokenStream) -> TokenStream {\n    let options = parse_macro_input!(args as PyModuleOptions);\n\n    let mut ast = parse_macro_input!(input as Item);\n    let expanded = match &mut ast {\n        Item::Mod(module) => {\n            match pymodule_module_impl(module, options) {\n                // #[pymodule] on a module will rebuild the original ast, so we don't emit it here\n                Ok(expanded) => return expanded.into(),\n                Err(e) => Err(e),\n            }\n        }\n        Item::Fn(function) => pymodule_function_impl(function, options),\n        unsupported => Err(syn::Error::new_spanned(\n            unsupported,\n            \"#[pymodule] only supports modules and functions.\",\n        )),\n    }\n    .unwrap_or_compile_error();\n\n    quote!(\n        #ast\n        #expanded\n    )\n    .into()\n}\n\n#[proc_macro_attribute]\npub fn pyclass(attr: TokenStream, input: TokenStream) -> TokenStream {\n    let item = parse_macro_input!(input as Item);\n    match item {\n        Item::Struct(struct_) => pyclass_impl(attr, struct_, methods_type()),\n        Item::Enum(enum_) => pyclass_enum_impl(attr, enum_, methods_type()),\n        unsupported => {\n            syn::Error::new_spanned(unsupported, \"#[pyclass] only supports structs and enums.\")\n                .into_compile_error()\n                .into()\n        }\n    }\n}\n\n/// A proc macro used to expose methods to Python.\n///\n/// Methods within a `#[pymethods]` block can be annotated with  as well as the following:\n///\n/// |  Annotation  |  Description |\n/// | :-  | :- |\n/// | [`#[new]`][4]  | Defines the class constructor, like Python's `__new__` method. |\n/// | [`#[getter]`][5] and [`#[setter]`][5] | These define getters and setters, similar to Python's `@property` decorator. This is useful for getters/setters that require computation or side effects; if that is not the case consider using [`#[pyo3(get, set)]`][12] on the struct's field(s).|\n/// | [`#[staticmethod]`][6]| Defines the method as a staticmethod, like Python's `@staticmethod` decorator.|\n/// | [`#[classmethod]`][7]  | Defines the method as a classmethod, like Python's `@classmethod` decorator.|\n/// | [`#[classattr]`][9]  | Defines a class variable. |\n/// | [`#[args]`][10]  | Deprecated way to define a method's default arguments and allows the function to receive `*args` and `**kwargs`. Use `#[pyo3(signature = (...))]` instead. |\n/// | <nobr>[`#[pyo3(<option> = <value>)`][11]</nobr> | Any of the `#[pyo3]` options supported on [`macro@pyfunction`]. |\n///\n/// For more on creating class methods,\n/// see the [class section of the guide][1].\n///\n/// If the [`multiple-pymethods`][2] feature is enabled, it is possible to implement\n/// multiple `#[pymethods]` blocks for a single `#[pyclass]`.\n/// This will add a transitive dependency on the [`inventory`][3] crate.\n///\n#[doc = concat!(\"[1]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#instance-methods\")]\n#[doc = concat!(\"[2]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/features.html#multiple-pymethods\")]\n/// [3]: https://docs.rs/inventory/\n#[doc = concat!(\"[4]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#constructor\")]\n#[doc = concat!(\"[5]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#object-properties-using-getter-and-setter\")]\n#[doc = concat!(\"[6]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#static-methods\")]\n#[doc = concat!(\"[7]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#class-methods\")]\n#[doc = concat!(\"[8]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#callable-objects\")]\n#[doc = concat!(\"[9]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#class-attributes\")]\n#[doc = concat!(\"[10]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#method-arguments\")]\n#[doc = concat!(\"[11]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/function.html#function-options\")]\n#[doc = concat!(\"[12]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#object-properties-using-pyo3get-set\")]\n#[proc_macro_attribute]\npub fn pymethods(attr: TokenStream, input: TokenStream) -> TokenStream {\n    let methods_type = if cfg!(feature = \"multiple-pymethods\") {\n        PyClassMethodsType::Inventory\n    } else {\n        PyClassMethodsType::Specialization\n    };\n    pymethods_impl(attr, input, methods_type)\n}\n\n/// A proc macro used to expose Rust functions to Python.\n///\n/// Functions annotated with `#[pyfunction]` can also be annotated with the following `#[pyo3]`\n/// options:\n///\n/// |  Annotation  |  Description |\n/// | :-  | :- |\n/// | `#[pyo3(name = \"...\")]` | Defines the name of the function in Python. |\n/// | `#[pyo3(text_signature = \"...\")]` | Defines the `__text_signature__` attribute of the function in Python. |\n/// | `#[pyo3(pass_module)]` | Passes the module containing the function as a `&PyModule` first argument to the function. |\n/// | `#[pyo3(warn(message = \"...\", category = ...))]` | Generate warning given a message and a category |\n///\n/// For more on exposing functions see the [function section of the guide][1].\n///\n/// Due to technical limitations on how `#[pyfunction]` is implemented, a function marked\n/// `#[pyfunction]` cannot have a module with the same name in the same scope. (The\n/// `#[pyfunction]` implementation generates a hidden module with the same name containing\n/// metadata about the function, which is used by `wrap_pyfunction!`).\n///\n#[doc = concat!(\"[1]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/function.html\")]\n#[proc_macro_attribute]\npub fn pyfunction(attr: TokenStream, input: TokenStream) -> TokenStream {\n    let mut ast = parse_macro_input!(input as syn::ItemFn);\n    let options = parse_macro_input!(attr as PyFunctionOptions);\n\n    let expanded = build_py_function(&mut ast, options).unwrap_or_compile_error();\n\n    quote!(\n        #ast\n        #expanded\n    )\n    .into()\n}\n\n#[proc_macro_derive(IntoPyObject, attributes(pyo3))]\npub fn derive_into_py_object(item: TokenStream) -> TokenStream {\n    let ast = parse_macro_input!(item as syn::DeriveInput);\n    let expanded = build_derive_into_pyobject::<false>(&ast).unwrap_or_compile_error();\n    quote!(\n        #expanded\n    )\n    .into()\n}\n\n#[proc_macro_derive(IntoPyObjectRef, attributes(pyo3))]\npub fn derive_into_py_object_ref(item: TokenStream) -> TokenStream {\n    let ast = parse_macro_input!(item as syn::DeriveInput);\n    let expanded =\n        pyo3_macros_backend::build_derive_into_pyobject::<true>(&ast).unwrap_or_compile_error();\n    quote!(\n        #expanded\n    )\n    .into()\n}\n\n#[proc_macro_derive(FromPyObject, attributes(pyo3))]\npub fn derive_from_py_object(item: TokenStream) -> TokenStream {\n    let ast = parse_macro_input!(item as syn::DeriveInput);\n    let expanded = build_derive_from_pyobject(&ast).unwrap_or_compile_error();\n    quote!(\n        #expanded\n    )\n    .into()\n}\n\nfn pyclass_impl(\n    attrs: TokenStream,\n    mut ast: syn::ItemStruct,\n    methods_type: PyClassMethodsType,\n) -> TokenStream {\n    let args = parse_macro_input!(attrs with PyClassArgs::parse_struct_args);\n    let expanded = build_py_class(&mut ast, args, methods_type).unwrap_or_compile_error();\n\n    quote!(\n        #ast\n        #expanded\n    )\n    .into()\n}\n\nfn pyclass_enum_impl(\n    attrs: TokenStream,\n    mut ast: syn::ItemEnum,\n    methods_type: PyClassMethodsType,\n) -> TokenStream {\n    let args = parse_macro_input!(attrs with PyClassArgs::parse_enum_args);\n    let expanded = build_py_enum(&mut ast, args, methods_type).unwrap_or_compile_error();\n\n    quote!(\n        #ast\n        #expanded\n    )\n    .into()\n}\n\nfn pymethods_impl(\n    attr: TokenStream,\n    input: TokenStream,\n    methods_type: PyClassMethodsType,\n) -> TokenStream {\n    let mut ast = parse_macro_input!(input as syn::ItemImpl);\n    // Apply all options as a #[pyo3] attribute on the ItemImpl\n    // e.g. #[pymethods(crate = \"crate\")] impl Foo { }\n    // -> #[pyo3(crate = \"crate\")] impl Foo { }\n    let attr: TokenStream2 = attr.into();\n    ast.attrs.push(syn::parse_quote!( #[pyo3(#attr)] ));\n    let expanded = build_py_methods(&mut ast, methods_type).unwrap_or_compile_error();\n\n    quote!(\n        #ast\n        #expanded\n    )\n    .into()\n}\n\nfn methods_type() -> PyClassMethodsType {\n    if cfg!(feature = \"multiple-pymethods\") {\n        PyClassMethodsType::Inventory\n    } else {\n        PyClassMethodsType::Specialization\n    }\n}\n\ntrait UnwrapOrCompileError {\n    fn unwrap_or_compile_error(self) -> TokenStream2;\n}\n\nimpl UnwrapOrCompileError for syn::Result<TokenStream2> {\n    fn unwrap_or_compile_error(self) -> TokenStream2 {\n        self.unwrap_or_else(|e| e.into_compile_error())\n    }\n}\n"
  },
  {
    "path": "pyo3-macros-backend/Cargo.toml",
    "content": "[package]\nname = \"pyo3-macros-backend\"\nversion = \"0.28.2\"\ndescription = \"Code generation for PyO3 package\"\nauthors = [\"PyO3 Project and Contributors <https://github.com/PyO3>\"]\nkeywords = [\"pyo3\", \"python\", \"cpython\", \"ffi\"]\nhomepage = \"https://github.com/pyo3/pyo3\"\nrepository = \"https://github.com/pyo3/pyo3\"\ncategories = [\"api-bindings\", \"development-tools::ffi\"]\nlicense = \"MIT OR Apache-2.0\"\nedition = \"2021\"\nrust-version.workspace = true\n\n# Note: we use default-features = false for proc-macro related crates\n# not to depend on proc-macro itself.\n# See https://github.com/PyO3/pyo3/pull/810 for more.\n[dependencies]\nheck = \"0.5\"\nproc-macro2 = { version = \"1.0.60\", default-features = false }\nquote = { version = \"1.0.37\", default-features = false }\n\n[dependencies.syn]\n# 2.0.59 for `LitCStr`\nversion = \"2.0.59\"\ndefault-features = false\nfeatures = [\"derive\", \"parsing\", \"printing\", \"clone-impls\", \"full\", \"extra-traits\", \"visit-mut\"]\n\n[lints]\nworkspace = true\n\n[features]\nexperimental-async = []\nexperimental-inspect = []\n"
  },
  {
    "path": "pyo3-macros-backend/src/attributes.rs",
    "content": "use proc_macro2::TokenStream;\nuse quote::{quote, ToTokens};\nuse syn::parse::Parser;\nuse syn::{\n    ext::IdentExt,\n    parse::{Parse, ParseStream},\n    punctuated::Punctuated,\n    spanned::Spanned,\n    token::Comma,\n    Attribute, Expr, ExprPath, Ident, Index, LitBool, LitStr, Member, Path, Result, Token,\n};\n\nuse crate::combine_errors::CombineErrors;\n\npub mod kw {\n    syn::custom_keyword!(annotation);\n    syn::custom_keyword!(attribute);\n    syn::custom_keyword!(cancel_handle);\n    syn::custom_keyword!(constructor);\n    syn::custom_keyword!(dict);\n    syn::custom_keyword!(eq);\n    syn::custom_keyword!(eq_int);\n    syn::custom_keyword!(extends);\n    syn::custom_keyword!(freelist);\n    syn::custom_keyword!(from_py_with);\n    syn::custom_keyword!(frozen);\n    syn::custom_keyword!(get);\n    syn::custom_keyword!(get_all);\n    syn::custom_keyword!(hash);\n    syn::custom_keyword!(into_py_with);\n    syn::custom_keyword!(item);\n    syn::custom_keyword!(immutable_type);\n    syn::custom_keyword!(from_item_all);\n    syn::custom_keyword!(mapping);\n    syn::custom_keyword!(module);\n    syn::custom_keyword!(name);\n    syn::custom_keyword!(ord);\n    syn::custom_keyword!(pass_module);\n    syn::custom_keyword!(rename_all);\n    syn::custom_keyword!(sequence);\n    syn::custom_keyword!(set);\n    syn::custom_keyword!(set_all);\n    syn::custom_keyword!(new);\n    syn::custom_keyword!(signature);\n    syn::custom_keyword!(str);\n    syn::custom_keyword!(subclass);\n    syn::custom_keyword!(submodule);\n    syn::custom_keyword!(text_signature);\n    syn::custom_keyword!(transparent);\n    syn::custom_keyword!(unsendable);\n    syn::custom_keyword!(weakref);\n    syn::custom_keyword!(generic);\n    syn::custom_keyword!(gil_used);\n    syn::custom_keyword!(warn);\n    syn::custom_keyword!(message);\n    syn::custom_keyword!(category);\n    syn::custom_keyword!(from_py_object);\n    syn::custom_keyword!(skip_from_py_object);\n}\n\nfn take_int(read: &mut &str, tracker: &mut usize) -> String {\n    let mut int = String::new();\n    for (i, ch) in read.char_indices() {\n        match ch {\n            '0'..='9' => {\n                *tracker += 1;\n                int.push(ch)\n            }\n            _ => {\n                *read = &read[i..];\n                break;\n            }\n        }\n    }\n    int\n}\n\nfn take_ident(read: &mut &str, tracker: &mut usize) -> Ident {\n    let mut ident = String::new();\n    if read.starts_with(\"r#\") {\n        ident.push_str(\"r#\");\n        *tracker += 2;\n        *read = &read[2..];\n    }\n    for (i, ch) in read.char_indices() {\n        match ch {\n            'a'..='z' | 'A'..='Z' | '0'..='9' | '_' => {\n                *tracker += 1;\n                ident.push(ch)\n            }\n            _ => {\n                *read = &read[i..];\n                break;\n            }\n        }\n    }\n    Ident::parse_any.parse_str(&ident).unwrap()\n}\n\n// shorthand parsing logic inspiration taken from https://github.com/dtolnay/thiserror/blob/master/impl/src/fmt.rs\nfn parse_shorthand_format(fmt: LitStr) -> Result<(LitStr, Vec<Member>)> {\n    let span = fmt.span();\n    let token = fmt.token();\n    let value = fmt.value();\n    let mut read = value.as_str();\n    let mut out = String::new();\n    let mut members = Vec::new();\n    let mut tracker = 1;\n    while let Some(brace) = read.find('{') {\n        tracker += brace;\n        out += &read[..brace + 1];\n        read = &read[brace + 1..];\n        if read.starts_with('{') {\n            out.push('{');\n            read = &read[1..];\n            tracker += 2;\n            continue;\n        }\n        let next = match read.chars().next() {\n            Some(next) => next,\n            None => break,\n        };\n        tracker += 1;\n        let member = match next {\n            '0'..='9' => {\n                let start = tracker;\n                let index = take_int(&mut read, &mut tracker).parse::<u32>().unwrap();\n                let end = tracker;\n                let subspan = token.subspan(start..end).unwrap_or(span);\n                let idx = Index {\n                    index,\n                    span: subspan,\n                };\n                Member::Unnamed(idx)\n            }\n            'a'..='z' | 'A'..='Z' | '_' => {\n                let start = tracker;\n                let mut ident = take_ident(&mut read, &mut tracker);\n                let end = tracker;\n                let subspan = token.subspan(start..end).unwrap_or(span);\n                ident.set_span(subspan);\n                Member::Named(ident)\n            }\n            '}' | ':' => {\n                let start = tracker;\n                tracker += 1;\n                let end = tracker;\n                let subspan = token.subspan(start..end).unwrap_or(span);\n                // we found a closing bracket or formatting ':' without finding a member, we assume the user wants the instance formatted here\n                bail_spanned!(subspan.span() => \"No member found, you must provide a named or positionally specified member.\")\n            }\n            _ => continue,\n        };\n        members.push(member);\n    }\n    out += read;\n    Ok((LitStr::new(&out, span), members))\n}\n\n#[derive(Clone, Debug)]\npub struct StringFormatter {\n    pub fmt: LitStr,\n    pub args: Vec<Member>,\n}\n\nimpl Parse for crate::attributes::StringFormatter {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let (fmt, args) = parse_shorthand_format(input.parse()?)?;\n        Ok(Self { fmt, args })\n    }\n}\n\nimpl ToTokens for crate::attributes::StringFormatter {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.fmt.to_tokens(tokens);\n        tokens.extend(quote! {self.args})\n    }\n}\n\n#[derive(Clone, Debug)]\npub struct KeywordAttribute<K, V> {\n    pub kw: K,\n    pub value: V,\n}\n\n#[derive(Clone, Debug)]\npub struct OptionalKeywordAttribute<K, V> {\n    pub kw: K,\n    pub value: Option<V>,\n}\n\n/// A helper type which parses the inner type via a literal string\n/// e.g. `LitStrValue<Path>` -> parses \"some::path\" in quotes.\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct LitStrValue<T>(pub T);\n\nimpl<T: Parse> Parse for LitStrValue<T> {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let lit_str: LitStr = input.parse()?;\n        lit_str.parse().map(LitStrValue)\n    }\n}\n\nimpl<T: ToTokens> ToTokens for LitStrValue<T> {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.0.to_tokens(tokens)\n    }\n}\n\n/// A helper type which parses a name via a literal string\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct NameLitStr(pub Ident);\n\nimpl Parse for NameLitStr {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let string_literal: LitStr = input.parse()?;\n        if let Ok(ident) = string_literal.parse_with(Ident::parse_any) {\n            Ok(NameLitStr(ident))\n        } else {\n            bail_spanned!(string_literal.span() => \"expected a single identifier in double quotes\")\n        }\n    }\n}\n\nimpl ToTokens for NameLitStr {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.0.to_tokens(tokens)\n    }\n}\n\n/// Available renaming rules\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub enum RenamingRule {\n    CamelCase,\n    KebabCase,\n    Lowercase,\n    PascalCase,\n    ScreamingKebabCase,\n    ScreamingSnakeCase,\n    SnakeCase,\n    Uppercase,\n}\n\n/// A helper type which parses a renaming rule via a literal string\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct RenamingRuleLitStr {\n    pub lit: LitStr,\n    pub rule: RenamingRule,\n}\n\nimpl Parse for RenamingRuleLitStr {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let string_literal: LitStr = input.parse()?;\n        let rule = match string_literal.value().as_ref() {\n            \"camelCase\" => RenamingRule::CamelCase,\n            \"kebab-case\" => RenamingRule::KebabCase,\n            \"lowercase\" => RenamingRule::Lowercase,\n            \"PascalCase\" => RenamingRule::PascalCase,\n            \"SCREAMING-KEBAB-CASE\" => RenamingRule::ScreamingKebabCase,\n            \"SCREAMING_SNAKE_CASE\" => RenamingRule::ScreamingSnakeCase,\n            \"snake_case\" => RenamingRule::SnakeCase,\n            \"UPPERCASE\" => RenamingRule::Uppercase,\n            _ => {\n                bail_spanned!(string_literal.span() => \"expected a valid renaming rule, possible values are: \\\"camelCase\\\", \\\"kebab-case\\\", \\\"lowercase\\\", \\\"PascalCase\\\", \\\"SCREAMING-KEBAB-CASE\\\", \\\"SCREAMING_SNAKE_CASE\\\", \\\"snake_case\\\", \\\"UPPERCASE\\\"\")\n            }\n        };\n        Ok(Self {\n            lit: string_literal,\n            rule,\n        })\n    }\n}\n\nimpl ToTokens for RenamingRuleLitStr {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.lit.to_tokens(tokens)\n    }\n}\n\n/// Text signature can be either a literal string or opt-in/out\n#[derive(Clone, Debug, PartialEq, Eq)]\npub enum TextSignatureAttributeValue {\n    Str(LitStr),\n    // `None` ident to disable automatic text signature generation\n    Disabled(Ident),\n}\n\nimpl Parse for TextSignatureAttributeValue {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        if let Ok(lit_str) = input.parse::<LitStr>() {\n            return Ok(TextSignatureAttributeValue::Str(lit_str));\n        }\n\n        let err_span = match input.parse::<Ident>() {\n            Ok(ident) if ident == \"None\" => {\n                return Ok(TextSignatureAttributeValue::Disabled(ident));\n            }\n            Ok(other_ident) => other_ident.span(),\n            Err(e) => e.span(),\n        };\n\n        Err(err_spanned!(err_span => \"expected a string literal or `None`\"))\n    }\n}\n\nimpl ToTokens for TextSignatureAttributeValue {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        match self {\n            TextSignatureAttributeValue::Str(s) => s.to_tokens(tokens),\n            TextSignatureAttributeValue::Disabled(b) => b.to_tokens(tokens),\n        }\n    }\n}\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub enum NewImplTypeAttributeValue {\n    FromFields,\n    // Future variant for 'default' should go here\n}\n\nimpl Parse for NewImplTypeAttributeValue {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let string_literal: LitStr = input.parse()?;\n        if string_literal.value().as_str() == \"from_fields\" {\n            Ok(NewImplTypeAttributeValue::FromFields)\n        } else {\n            bail_spanned!(string_literal.span() => \"expected \\\"from_fields\\\"\")\n        }\n    }\n}\n\nimpl ToTokens for NewImplTypeAttributeValue {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        match self {\n            NewImplTypeAttributeValue::FromFields => {\n                tokens.extend(quote! { \"from_fields\" });\n            }\n        }\n    }\n}\n\npub type ExtendsAttribute = KeywordAttribute<kw::extends, Path>;\npub type FreelistAttribute = KeywordAttribute<kw::freelist, Box<Expr>>;\npub type ModuleAttribute = KeywordAttribute<kw::module, LitStr>;\npub type NameAttribute = KeywordAttribute<kw::name, NameLitStr>;\npub type RenameAllAttribute = KeywordAttribute<kw::rename_all, RenamingRuleLitStr>;\npub type StrFormatterAttribute = OptionalKeywordAttribute<kw::str, StringFormatter>;\npub type TextSignatureAttribute = KeywordAttribute<kw::text_signature, TextSignatureAttributeValue>;\npub type NewImplTypeAttribute = KeywordAttribute<kw::new, NewImplTypeAttributeValue>;\npub type SubmoduleAttribute = kw::submodule;\npub type GILUsedAttribute = KeywordAttribute<kw::gil_used, LitBool>;\n\nimpl<K: Parse + std::fmt::Debug, V: Parse> Parse for KeywordAttribute<K, V> {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let kw: K = input.parse()?;\n        let _: Token![=] = input.parse()?;\n        let value = input.parse()?;\n        Ok(KeywordAttribute { kw, value })\n    }\n}\n\nimpl<K: ToTokens, V: ToTokens> ToTokens for KeywordAttribute<K, V> {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.kw.to_tokens(tokens);\n        Token![=](self.kw.span()).to_tokens(tokens);\n        self.value.to_tokens(tokens);\n    }\n}\n\nimpl<K: Parse + std::fmt::Debug, V: Parse> Parse for OptionalKeywordAttribute<K, V> {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let kw: K = input.parse()?;\n        let value = match input.parse::<Token![=]>() {\n            Ok(_) => Some(input.parse()?),\n            Err(_) => None,\n        };\n        Ok(OptionalKeywordAttribute { kw, value })\n    }\n}\n\nimpl<K: ToTokens, V: ToTokens> ToTokens for OptionalKeywordAttribute<K, V> {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.kw.to_tokens(tokens);\n        if self.value.is_some() {\n            Token![=](self.kw.span()).to_tokens(tokens);\n            self.value.to_tokens(tokens);\n        }\n    }\n}\n\npub type FromPyWithAttribute = KeywordAttribute<kw::from_py_with, ExprPath>;\npub type IntoPyWithAttribute = KeywordAttribute<kw::into_py_with, ExprPath>;\n\npub type DefaultAttribute = OptionalKeywordAttribute<Token![default], Expr>;\n\n/// For specifying the path to the pyo3 crate.\npub type CrateAttribute = KeywordAttribute<Token![crate], LitStrValue<Path>>;\n\npub fn get_pyo3_options<T: Parse>(attr: &syn::Attribute) -> Result<Option<Punctuated<T, Comma>>> {\n    if attr.path().is_ident(\"pyo3\") {\n        attr.parse_args_with(Punctuated::parse_terminated).map(Some)\n    } else {\n        Ok(None)\n    }\n}\n\n/// Takes attributes from an attribute vector.\n///\n/// For each attribute in `attrs`, `extractor` is called. If `extractor` returns `Ok(true)`, then\n/// the attribute will be removed from the vector.\n///\n/// This is similar to `Vec::retain` except the closure is fallible and the condition is reversed.\n/// (In `retain`, returning `true` keeps the element, here it removes it.)\npub fn take_attributes(\n    attrs: &mut Vec<Attribute>,\n    mut extractor: impl FnMut(&Attribute) -> Result<bool>,\n) -> Result<()> {\n    *attrs = attrs\n        .drain(..)\n        .filter_map(|attr| {\n            extractor(&attr)\n                .map(move |attribute_handled| if attribute_handled { None } else { Some(attr) })\n                .transpose()\n        })\n        .collect::<Result<_>>()?;\n    Ok(())\n}\n\npub fn take_pyo3_options<T: Parse>(attrs: &mut Vec<syn::Attribute>) -> Result<Vec<T>> {\n    let mut out = Vec::new();\n\n    take_attributes(attrs, |attr| match get_pyo3_options(attr) {\n        Ok(result) => {\n            if let Some(options) = result {\n                out.extend(options.into_iter().map(|a| Ok(a)));\n                Ok(true)\n            } else {\n                Ok(false)\n            }\n        }\n        Err(err) => {\n            out.push(Err(err));\n            Ok(true)\n        }\n    })?;\n\n    let out: Vec<T> = out.into_iter().try_combine_syn_errors()?;\n\n    Ok(out)\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/combine_errors.rs",
    "content": "pub(crate) trait CombineErrors: Iterator {\n    type Ok;\n    fn try_combine_syn_errors(self) -> syn::Result<Vec<Self::Ok>>;\n}\n\nimpl<I, T> CombineErrors for I\nwhere\n    I: Iterator<Item = syn::Result<T>>,\n{\n    type Ok = T;\n\n    fn try_combine_syn_errors(self) -> syn::Result<Vec<Self::Ok>> {\n        let mut oks: Vec<Self::Ok> = Vec::new();\n        let mut errors: Vec<syn::Error> = Vec::new();\n\n        for res in self {\n            match res {\n                Ok(val) => oks.push(val),\n                Err(e) => errors.push(e),\n            }\n        }\n\n        let mut err_iter = errors.into_iter();\n        let mut err = match err_iter.next() {\n            // There are no errors\n            None => return Ok(oks),\n            Some(e) => e,\n        };\n\n        for e in err_iter {\n            err.combine(e);\n        }\n\n        Err(err)\n    }\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/derive_attributes.rs",
    "content": "use crate::attributes::{\r\n    self, get_pyo3_options, CrateAttribute, DefaultAttribute, FromPyWithAttribute,\r\n    IntoPyWithAttribute, RenameAllAttribute,\r\n};\r\nuse proc_macro2::Span;\r\nuse syn::parse::{Parse, ParseStream};\r\nuse syn::spanned::Spanned;\r\nuse syn::{parenthesized, Attribute, LitStr, Result, Token};\r\n\r\n/// Attributes for deriving `FromPyObject`/`IntoPyObject` scoped on containers.\r\npub enum ContainerAttribute {\r\n    /// Treat the Container as a Wrapper, operate directly on its field\r\n    Transparent(attributes::kw::transparent),\r\n    /// Force every field to be extracted from item of source Python object.\r\n    ItemAll(attributes::kw::from_item_all),\r\n    /// Change the name of an enum variant in the generated error message.\r\n    ErrorAnnotation(LitStr),\r\n    /// Change the path for the pyo3 crate\r\n    Crate(CrateAttribute),\r\n    /// Converts the field idents according to the [RenamingRule](attributes::RenamingRule) before extraction\r\n    RenameAll(RenameAllAttribute),\r\n}\r\n\r\nimpl Parse for ContainerAttribute {\r\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\r\n        let lookahead = input.lookahead1();\r\n        if lookahead.peek(attributes::kw::transparent) {\r\n            let kw: attributes::kw::transparent = input.parse()?;\r\n            Ok(ContainerAttribute::Transparent(kw))\r\n        } else if lookahead.peek(attributes::kw::from_item_all) {\r\n            let kw: attributes::kw::from_item_all = input.parse()?;\r\n            Ok(ContainerAttribute::ItemAll(kw))\r\n        } else if lookahead.peek(attributes::kw::annotation) {\r\n            let _: attributes::kw::annotation = input.parse()?;\r\n            let _: Token![=] = input.parse()?;\r\n            input.parse().map(ContainerAttribute::ErrorAnnotation)\r\n        } else if lookahead.peek(Token![crate]) {\r\n            input.parse().map(ContainerAttribute::Crate)\r\n        } else if lookahead.peek(attributes::kw::rename_all) {\r\n            input.parse().map(ContainerAttribute::RenameAll)\r\n        } else {\r\n            Err(lookahead.error())\r\n        }\r\n    }\r\n}\r\n\r\n#[derive(Default, Clone)]\r\npub struct ContainerAttributes {\r\n    /// Treat the Container as a Wrapper, operate directly on its field\r\n    pub transparent: Option<attributes::kw::transparent>,\r\n    /// Force every field to be extracted from item of source Python object.\r\n    pub from_item_all: Option<attributes::kw::from_item_all>,\r\n    /// Change the name of an enum variant in the generated error message.\r\n    pub annotation: Option<syn::LitStr>,\r\n    /// Change the path for the pyo3 crate\r\n    pub krate: Option<CrateAttribute>,\r\n    /// Converts the field idents according to the [RenamingRule](attributes::RenamingRule) before extraction\r\n    pub rename_all: Option<RenameAllAttribute>,\r\n}\r\n\r\nimpl ContainerAttributes {\r\n    pub fn from_attrs(attrs: &[Attribute]) -> Result<Self> {\r\n        let mut options = ContainerAttributes::default();\r\n\r\n        for attr in attrs {\r\n            if let Some(pyo3_attrs) = get_pyo3_options(attr)? {\r\n                pyo3_attrs\r\n                    .into_iter()\r\n                    .try_for_each(|opt| options.set_option(opt))?;\r\n            }\r\n        }\r\n        Ok(options)\r\n    }\r\n\r\n    fn set_option(&mut self, option: ContainerAttribute) -> syn::Result<()> {\r\n        macro_rules! set_option {\r\n            ($key:ident) => {\r\n                {\r\n                    ensure_spanned!(\r\n                        self.$key.is_none(),\r\n                        $key.span() => concat!(\"`\", stringify!($key), \"` may only be specified once\")\r\n                    );\r\n                    self.$key = Some($key);\r\n                }\r\n            };\r\n        }\r\n\r\n        match option {\r\n            ContainerAttribute::Transparent(transparent) => set_option!(transparent),\r\n            ContainerAttribute::ItemAll(from_item_all) => set_option!(from_item_all),\r\n            ContainerAttribute::ErrorAnnotation(annotation) => set_option!(annotation),\r\n            ContainerAttribute::Crate(krate) => set_option!(krate),\r\n            ContainerAttribute::RenameAll(rename_all) => set_option!(rename_all),\r\n        }\r\n        Ok(())\r\n    }\r\n}\r\n\r\n#[derive(Clone, Debug)]\r\npub enum FieldGetter {\r\n    GetItem(attributes::kw::item, Option<syn::Lit>),\r\n    GetAttr(attributes::kw::attribute, Option<syn::LitStr>),\r\n}\r\n\r\nimpl FieldGetter {\r\n    pub fn span(&self) -> Span {\r\n        match self {\r\n            FieldGetter::GetItem(item, _) => item.span,\r\n            FieldGetter::GetAttr(attribute, _) => attribute.span,\r\n        }\r\n    }\r\n}\r\n\r\npub enum FieldAttribute {\r\n    Getter(FieldGetter),\r\n    FromPyWith(FromPyWithAttribute),\r\n    IntoPyWith(IntoPyWithAttribute),\r\n    Default(DefaultAttribute),\r\n}\r\n\r\nimpl Parse for FieldAttribute {\r\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\r\n        let lookahead = input.lookahead1();\r\n        if lookahead.peek(attributes::kw::attribute) {\r\n            let attr_kw: attributes::kw::attribute = input.parse()?;\r\n            if input.peek(syn::token::Paren) {\r\n                let content;\r\n                let _ = parenthesized!(content in input);\r\n                let attr_name: LitStr = content.parse()?;\r\n                if !content.is_empty() {\r\n                    return Err(content.error(\r\n                        \"expected at most one argument: `attribute` or `attribute(\\\"name\\\")`\",\r\n                    ));\r\n                }\r\n                ensure_spanned!(\r\n                    !attr_name.value().is_empty(),\r\n                    attr_name.span() => \"attribute name cannot be empty\"\r\n                );\r\n                Ok(Self::Getter(FieldGetter::GetAttr(attr_kw, Some(attr_name))))\r\n            } else {\r\n                Ok(Self::Getter(FieldGetter::GetAttr(attr_kw, None)))\r\n            }\r\n        } else if lookahead.peek(attributes::kw::item) {\r\n            let item_kw: attributes::kw::item = input.parse()?;\r\n            if input.peek(syn::token::Paren) {\r\n                let content;\r\n                let _ = parenthesized!(content in input);\r\n                let key = content.parse()?;\r\n                if !content.is_empty() {\r\n                    return Err(\r\n                        content.error(\"expected at most one argument: `item` or `item(key)`\")\r\n                    );\r\n                }\r\n                Ok(Self::Getter(FieldGetter::GetItem(item_kw, Some(key))))\r\n            } else {\r\n                Ok(Self::Getter(FieldGetter::GetItem(item_kw, None)))\r\n            }\r\n        } else if lookahead.peek(attributes::kw::from_py_with) {\r\n            input.parse().map(Self::FromPyWith)\r\n        } else if lookahead.peek(attributes::kw::into_py_with) {\r\n            input.parse().map(FieldAttribute::IntoPyWith)\r\n        } else if lookahead.peek(Token![default]) {\r\n            input.parse().map(Self::Default)\r\n        } else {\r\n            Err(lookahead.error())\r\n        }\r\n    }\r\n}\r\n\r\n#[derive(Clone, Debug, Default)]\r\npub struct FieldAttributes {\r\n    pub getter: Option<FieldGetter>,\r\n    pub from_py_with: Option<FromPyWithAttribute>,\r\n    pub into_py_with: Option<IntoPyWithAttribute>,\r\n    pub default: Option<DefaultAttribute>,\r\n}\r\n\r\nimpl FieldAttributes {\r\n    /// Extract the field attributes.\r\n    pub fn from_attrs(attrs: &[Attribute]) -> Result<Self> {\r\n        let mut options = FieldAttributes::default();\r\n\r\n        for attr in attrs {\r\n            if let Some(pyo3_attrs) = get_pyo3_options(attr)? {\r\n                pyo3_attrs\r\n                    .into_iter()\r\n                    .try_for_each(|opt| options.set_option(opt))?;\r\n            }\r\n        }\r\n        Ok(options)\r\n    }\r\n\r\n    fn set_option(&mut self, option: FieldAttribute) -> syn::Result<()> {\r\n        macro_rules! set_option {\r\n            ($key:ident) => {\r\n                set_option!($key, concat!(\"`\", stringify!($key), \"` may only be specified once\"))\r\n            };\r\n            ($key:ident, $msg: expr) => {{\r\n                ensure_spanned!(\r\n                    self.$key.is_none(),\r\n                    $key.span() => $msg\r\n                );\r\n                self.$key = Some($key);\r\n            }}\r\n        }\r\n\r\n        match option {\r\n            FieldAttribute::Getter(getter) => {\r\n                set_option!(getter, \"only one of `attribute` or `item` can be provided\")\r\n            }\r\n            FieldAttribute::FromPyWith(from_py_with) => set_option!(from_py_with),\r\n            FieldAttribute::IntoPyWith(into_py_with) => set_option!(into_py_with),\r\n            FieldAttribute::Default(default) => set_option!(default),\r\n        }\r\n        Ok(())\r\n    }\r\n}\r\n"
  },
  {
    "path": "pyo3-macros-backend/src/frompyobject.rs",
    "content": "use crate::attributes::{DefaultAttribute, FromPyWithAttribute, RenamingRule};\nuse crate::derive_attributes::{ContainerAttributes, FieldAttributes, FieldGetter};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::py_expr::PyExpr;\nuse crate::utils::{self, Ctx};\nuse proc_macro2::TokenStream;\nuse quote::{format_ident, quote, quote_spanned, ToTokens};\nuse syn::{\n    ext::IdentExt, parse_quote, punctuated::Punctuated, spanned::Spanned, DataEnum, DeriveInput,\n    Fields, Ident, Result, Token,\n};\n\n/// Describes derivation input of an enum.\nstruct Enum<'a> {\n    enum_ident: &'a Ident,\n    variants: Vec<Container<'a>>,\n}\n\nimpl<'a> Enum<'a> {\n    /// Construct a new enum representation.\n    ///\n    /// `data_enum` is the `syn` representation of the input enum, `ident` is the\n    /// `Identifier` of the enum.\n    fn new(\n        data_enum: &'a DataEnum,\n        ident: &'a Ident,\n        options: ContainerAttributes,\n    ) -> Result<Self> {\n        ensure_spanned!(\n            !data_enum.variants.is_empty(),\n            ident.span() => \"cannot derive FromPyObject for empty enum\"\n        );\n        let variants = data_enum\n            .variants\n            .iter()\n            .map(|variant| {\n                let mut variant_options = ContainerAttributes::from_attrs(&variant.attrs)?;\n                if let Some(rename_all) = &options.rename_all {\n                    ensure_spanned!(\n                        variant_options.rename_all.is_none(),\n                        variant_options.rename_all.span() => \"Useless variant `rename_all` - enum is already annotated with `rename_all\"\n                    );\n                    variant_options.rename_all = Some(rename_all.clone());\n\n                }\n                let var_ident = &variant.ident;\n                Container::new(\n                    &variant.fields,\n                    parse_quote!(#ident::#var_ident),\n                    variant_options,\n                )\n            })\n            .collect::<Result<Vec<_>>>()?;\n\n        Ok(Enum {\n            enum_ident: ident,\n            variants,\n        })\n    }\n\n    /// Build derivation body for enums.\n    fn build(&self, ctx: &Ctx) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        let mut var_extracts = Vec::new();\n        let mut variant_names = Vec::new();\n        let mut error_names = Vec::new();\n\n        for var in &self.variants {\n            let struct_derive = var.build(ctx);\n            let ext = quote!({\n                let maybe_ret = || -> #pyo3_path::PyResult<Self> {\n                    #struct_derive\n                }();\n\n                match maybe_ret {\n                    ok @ ::std::result::Result::Ok(_) => return ok,\n                    ::std::result::Result::Err(err) => err\n                }\n            });\n\n            var_extracts.push(ext);\n            variant_names.push(var.path.segments.last().unwrap().ident.to_string());\n            error_names.push(&var.err_name);\n        }\n        let ty_name = self.enum_ident.to_string();\n        quote!(\n            let errors = [\n                #(#var_extracts),*\n            ];\n            ::std::result::Result::Err(\n                #pyo3_path::impl_::frompyobject::failed_to_extract_enum(\n                    obj.py(),\n                    #ty_name,\n                    &[#(#variant_names),*],\n                    &[#(#error_names),*],\n                    &errors\n                )\n            )\n        )\n    }\n\n    #[cfg(feature = \"experimental-inspect\")]\n    fn input_type(&self) -> PyExpr {\n        self.variants\n            .iter()\n            .map(|var| var.input_type())\n            .reduce(PyExpr::union)\n            .expect(\"Empty enum\")\n    }\n}\n\nstruct NamedStructField<'a> {\n    ident: &'a syn::Ident,\n    getter: Option<FieldGetter>,\n    from_py_with: Option<FromPyWithAttribute>,\n    default: Option<DefaultAttribute>,\n    ty: &'a syn::Type,\n}\n\nstruct TupleStructField {\n    from_py_with: Option<FromPyWithAttribute>,\n    ty: syn::Type,\n}\n\n/// Container Style\n///\n/// Covers Structs, Tuplestructs and corresponding Newtypes.\nenum ContainerType<'a> {\n    /// Struct Container, e.g. `struct Foo { a: String }`\n    ///\n    /// Variant contains the list of field identifiers and the corresponding extraction call.\n    Struct(Vec<NamedStructField<'a>>),\n    /// Newtype struct container, e.g. `#[transparent] struct Foo { a: String }`\n    ///\n    /// The field specified by the identifier is extracted directly from the object.\n    #[cfg_attr(not(feature = \"experimental-inspect\"), allow(unused))]\n    StructNewtype(&'a syn::Ident, Option<FromPyWithAttribute>, &'a syn::Type),\n    /// Tuple struct, e.g. `struct Foo(String)`.\n    ///\n    /// Variant contains a list of conversion methods for each of the fields that are directly\n    ///  extracted from the tuple.\n    Tuple(Vec<TupleStructField>),\n    /// Tuple newtype, e.g. `#[transparent] struct Foo(String)`\n    ///\n    /// The wrapped field is directly extracted from the object.\n    #[cfg_attr(not(feature = \"experimental-inspect\"), allow(unused))]\n    TupleNewtype(Option<FromPyWithAttribute>, Box<syn::Type>),\n}\n\n/// Data container\n///\n/// Either describes a struct or an enum variant.\nstruct Container<'a> {\n    path: syn::Path,\n    ty: ContainerType<'a>,\n    err_name: String,\n    rename_rule: Option<RenamingRule>,\n}\n\nimpl<'a> Container<'a> {\n    /// Construct a container based on fields, identifier and attributes.\n    ///\n    /// Fails if the variant has no fields or incompatible attributes.\n    fn new(fields: &'a Fields, path: syn::Path, options: ContainerAttributes) -> Result<Self> {\n        let style = match fields {\n            Fields::Unnamed(unnamed) if !unnamed.unnamed.is_empty() => {\n                ensure_spanned!(\n                    options.rename_all.is_none(),\n                    options.rename_all.span() => \"`rename_all` is useless on tuple structs and variants.\"\n                );\n                let mut tuple_fields = unnamed\n                    .unnamed\n                    .iter()\n                    .map(|field| {\n                        let attrs = FieldAttributes::from_attrs(&field.attrs)?;\n                        ensure_spanned!(\n                            attrs.getter.is_none(),\n                            field.span() => \"`getter` is not permitted on tuple struct elements.\"\n                        );\n                        ensure_spanned!(\n                            attrs.default.is_none(),\n                            field.span() => \"`default` is not permitted on tuple struct elements.\"\n                        );\n                        Ok(TupleStructField {\n                            from_py_with: attrs.from_py_with,\n                            ty: field.ty.clone(),\n                        })\n                    })\n                    .collect::<Result<Vec<_>>>()?;\n\n                if tuple_fields.len() == 1 {\n                    // Always treat a 1-length tuple struct as \"transparent\", even without the\n                    // explicit annotation.\n                    let field = tuple_fields.pop().unwrap();\n                    ContainerType::TupleNewtype(field.from_py_with, Box::new(field.ty))\n                } else if options.transparent.is_some() {\n                    bail_spanned!(\n                        fields.span() => \"transparent structs and variants can only have 1 field\"\n                    );\n                } else {\n                    ContainerType::Tuple(tuple_fields)\n                }\n            }\n            Fields::Named(named) if !named.named.is_empty() => {\n                let mut struct_fields = named\n                    .named\n                    .iter()\n                    .map(|field| {\n                        let ident = field\n                            .ident\n                            .as_ref()\n                            .expect(\"Named fields should have identifiers\");\n                        let mut attrs = FieldAttributes::from_attrs(&field.attrs)?;\n\n                        if let Some(ref from_item_all) = options.from_item_all {\n                            if let Some(replaced) = attrs.getter.replace(FieldGetter::GetItem(parse_quote!(item), None))\n                            {\n                                match replaced {\n                                    FieldGetter::GetItem(item, Some(item_name)) => {\n                                        attrs.getter = Some(FieldGetter::GetItem(item, Some(item_name)));\n                                    }\n                                    FieldGetter::GetItem(_, None) => bail_spanned!(from_item_all.span() => \"Useless `item` - the struct is already annotated with `from_item_all`\"),\n                                    FieldGetter::GetAttr(_, _) => bail_spanned!(\n                                        from_item_all.span() => \"The struct is already annotated with `from_item_all`, `attribute` is not allowed\"\n                                    ),\n                                }\n                            }\n                        }\n\n                        Ok(NamedStructField {\n                            ident,\n                            getter: attrs.getter,\n                            from_py_with: attrs.from_py_with,\n                            default: attrs.default,\n                            ty: &field.ty,\n                        })\n                    })\n                    .collect::<Result<Vec<_>>>()?;\n                if struct_fields.iter().all(|field| field.default.is_some()) {\n                    bail_spanned!(\n                        fields.span() => \"cannot derive FromPyObject for structs and variants with only default values\"\n                    )\n                } else if options.transparent.is_some() {\n                    ensure_spanned!(\n                        struct_fields.len() == 1,\n                        fields.span() => \"transparent structs and variants can only have 1 field\"\n                    );\n                    ensure_spanned!(\n                        options.rename_all.is_none(),\n                        options.rename_all.span() => \"`rename_all` is not permitted on `transparent` structs and variants\"\n                    );\n                    let field = struct_fields.pop().unwrap();\n                    ensure_spanned!(\n                        field.getter.is_none(),\n                        field.ident.span() => \"`transparent` structs may not have a `getter` for the inner field\"\n                    );\n                    ContainerType::StructNewtype(field.ident, field.from_py_with, field.ty)\n                } else {\n                    ContainerType::Struct(struct_fields)\n                }\n            }\n            _ => bail_spanned!(\n                fields.span() => \"cannot derive FromPyObject for empty structs and variants\"\n            ),\n        };\n        let err_name = options.annotation.map_or_else(\n            || path.segments.last().unwrap().ident.to_string(),\n            |lit_str| lit_str.value(),\n        );\n\n        let v = Container {\n            path,\n            ty: style,\n            err_name,\n            rename_rule: options.rename_all.map(|v| v.value.rule),\n        };\n        Ok(v)\n    }\n\n    fn name(&self) -> String {\n        let mut value = String::new();\n        for segment in &self.path.segments {\n            if !value.is_empty() {\n                value.push_str(\"::\");\n            }\n            value.push_str(&segment.ident.to_string());\n        }\n        value\n    }\n\n    /// Build derivation body for a struct.\n    fn build(&self, ctx: &Ctx) -> TokenStream {\n        match &self.ty {\n            ContainerType::StructNewtype(ident, from_py_with, _) => {\n                self.build_newtype_struct(Some(ident), from_py_with, ctx)\n            }\n            ContainerType::TupleNewtype(from_py_with, _) => {\n                self.build_newtype_struct(None, from_py_with, ctx)\n            }\n            ContainerType::Tuple(tups) => self.build_tuple_struct(tups, ctx),\n            ContainerType::Struct(tups) => self.build_struct(tups, ctx),\n        }\n    }\n\n    fn build_newtype_struct(\n        &self,\n        field_ident: Option<&Ident>,\n        from_py_with: &Option<FromPyWithAttribute>,\n        ctx: &Ctx,\n    ) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        let self_ty = &self.path;\n        let struct_name = self.name();\n        if let Some(ident) = field_ident {\n            let field_name = ident.to_string();\n            if let Some(FromPyWithAttribute {\n                kw,\n                value: expr_path,\n            }) = from_py_with\n            {\n                let extractor = quote_spanned! { kw.span =>\n                    { let from_py_with: fn(_) -> _ = #expr_path; from_py_with }\n                };\n                quote! {\n                    Ok(#self_ty {\n                        #ident: #pyo3_path::impl_::frompyobject::extract_struct_field_with(#extractor, obj, #struct_name, #field_name)?\n                    })\n                }\n            } else {\n                quote! {\n                    Ok(#self_ty {\n                        #ident: #pyo3_path::impl_::frompyobject::extract_struct_field(obj, #struct_name, #field_name)?\n                    })\n                }\n            }\n        } else if let Some(FromPyWithAttribute {\n            kw,\n            value: expr_path,\n        }) = from_py_with\n        {\n            let extractor = quote_spanned! { kw.span =>\n                { let from_py_with: fn(_) -> _ = #expr_path; from_py_with }\n            };\n            quote! {\n                #pyo3_path::impl_::frompyobject::extract_tuple_struct_field_with(#extractor, obj, #struct_name, 0).map(#self_ty)\n            }\n        } else {\n            quote! {\n                #pyo3_path::impl_::frompyobject::extract_tuple_struct_field(obj, #struct_name, 0).map(#self_ty)\n            }\n        }\n    }\n\n    fn build_tuple_struct(&self, struct_fields: &[TupleStructField], ctx: &Ctx) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        let self_ty = &self.path;\n        let struct_name = &self.name();\n        let field_idents: Vec<_> = (0..struct_fields.len())\n            .map(|i| format_ident!(\"arg{}\", i))\n            .collect();\n        let fields = struct_fields.iter().zip(&field_idents).enumerate().map(|(index, (field, ident))| {\n            if let Some(FromPyWithAttribute {\n                kw,\n                value: expr_path, ..\n            }) = &field.from_py_with {\n                let extractor = quote_spanned! { kw.span =>\n                    { let from_py_with: fn(_) -> _ = #expr_path; from_py_with }\n                };\n               quote! {\n                    #pyo3_path::impl_::frompyobject::extract_tuple_struct_field_with(#extractor, &#ident, #struct_name, #index)?\n               }\n            } else {\n                quote!{\n                    #pyo3_path::impl_::frompyobject::extract_tuple_struct_field(&#ident, #struct_name, #index)?\n            }}\n        });\n\n        quote!(\n            match #pyo3_path::types::PyAnyMethods::extract(obj) {\n                ::std::result::Result::Ok((#(#field_idents),*)) => ::std::result::Result::Ok(#self_ty(#(#fields),*)),\n                ::std::result::Result::Err(err) => ::std::result::Result::Err(err),\n            }\n        )\n    }\n\n    fn build_struct(&self, struct_fields: &[NamedStructField<'_>], ctx: &Ctx) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        let self_ty = &self.path;\n        let struct_name = self.name();\n        let mut fields: Punctuated<TokenStream, Token![,]> = Punctuated::new();\n        for field in struct_fields {\n            let ident = field.ident;\n            let field_name = ident.unraw().to_string();\n            let getter = match field\n                .getter\n                .as_ref()\n                .unwrap_or(&FieldGetter::GetAttr(parse_quote!(attribute), None))\n            {\n                FieldGetter::GetAttr(_, Some(name)) => {\n                    quote!(#pyo3_path::types::PyAnyMethods::getattr(obj, #pyo3_path::intern!(obj.py(), #name)))\n                }\n                FieldGetter::GetAttr(_, None) => {\n                    let name = self\n                        .rename_rule\n                        .map(|rule| utils::apply_renaming_rule(rule, &field_name));\n                    let name = name.as_deref().unwrap_or(&field_name);\n                    quote!(#pyo3_path::types::PyAnyMethods::getattr(obj, #pyo3_path::intern!(obj.py(), #name)))\n                }\n                FieldGetter::GetItem(_, Some(syn::Lit::Str(key))) => {\n                    quote!(#pyo3_path::types::PyAnyMethods::get_item(obj, #pyo3_path::intern!(obj.py(), #key)))\n                }\n                FieldGetter::GetItem(_, Some(key)) => {\n                    quote!(#pyo3_path::types::PyAnyMethods::get_item(obj, #key))\n                }\n                FieldGetter::GetItem(_, None) => {\n                    let name = self\n                        .rename_rule\n                        .map(|rule| utils::apply_renaming_rule(rule, &field_name));\n                    let name = name.as_deref().unwrap_or(&field_name);\n                    quote!(#pyo3_path::types::PyAnyMethods::get_item(obj, #pyo3_path::intern!(obj.py(), #name)))\n                }\n            };\n            let extractor = if let Some(FromPyWithAttribute {\n                kw,\n                value: expr_path,\n            }) = &field.from_py_with\n            {\n                let extractor = quote_spanned! { kw.span =>\n                    { let from_py_with: fn(_) -> _ = #expr_path; from_py_with }\n                };\n                quote! (#pyo3_path::impl_::frompyobject::extract_struct_field_with(#extractor, &#getter?, #struct_name, #field_name)?)\n            } else {\n                quote!(#pyo3_path::impl_::frompyobject::extract_struct_field(&value, #struct_name, #field_name)?)\n            };\n            let extracted = if let Some(default) = &field.default {\n                let default_expr = if let Some(default_expr) = &default.value {\n                    default_expr.to_token_stream()\n                } else {\n                    quote!(::std::default::Default::default())\n                };\n                quote!(if let ::std::result::Result::Ok(value) = #getter {\n                    #extractor\n                } else {\n                    #default_expr\n                })\n            } else {\n                quote!({\n                    let value = #getter?;\n                    #extractor\n                })\n            };\n\n            fields.push(quote!(#ident: #extracted));\n        }\n\n        quote!(::std::result::Result::Ok(#self_ty{#fields}))\n    }\n\n    #[cfg(feature = \"experimental-inspect\")]\n    fn input_type(&self) -> PyExpr {\n        match &self.ty {\n            ContainerType::StructNewtype(_, from_py_with, ty) => {\n                Self::field_input_type(from_py_with, ty)\n            }\n            ContainerType::TupleNewtype(from_py_with, ty) => {\n                Self::field_input_type(from_py_with, ty)\n            }\n            ContainerType::Tuple(tups) => PyExpr::subscript(\n                PyExpr::builtin(\"tuple\"),\n                PyExpr::tuple(tups.iter().map(|TupleStructField { from_py_with, ty }| {\n                    Self::field_input_type(from_py_with, ty)\n                })),\n            ),\n            ContainerType::Struct(_) => {\n                // TODO: implement using a Protocol?\n                PyExpr::module_attr(\"_typeshed\", \"Incomplete\")\n            }\n        }\n    }\n\n    #[cfg(feature = \"experimental-inspect\")]\n    fn field_input_type(from_py_with: &Option<FromPyWithAttribute>, ty: &syn::Type) -> PyExpr {\n        if from_py_with.is_some() {\n            // We don't know what from_py_with is doing\n            PyExpr::module_attr(\"_typeshed\", \"Incomplete\")\n        } else {\n            PyExpr::from_from_py_object(ty.clone(), None)\n        }\n    }\n}\n\nfn verify_and_get_lifetime(generics: &syn::Generics) -> Result<Option<&syn::LifetimeParam>> {\n    let mut lifetimes = generics.lifetimes();\n    let lifetime = lifetimes.next();\n    ensure_spanned!(\n        lifetimes.next().is_none(),\n        generics.span() => \"FromPyObject can be derived with at most one lifetime parameter\"\n    );\n    Ok(lifetime)\n}\n\n/// Derive FromPyObject for enums and structs.\n///\n///   * Max 1 lifetime specifier, will be tied to `FromPyObject`'s specifier\n///   * At least one field, in case of `#[transparent]`, exactly one field\n///   * At least one variant for enums.\n///   * Fields of input structs and enums must implement `FromPyObject` or be annotated with `from_py_with`\n///   * Derivation for structs with generic fields like `struct<T> Foo(T)`\n///     adds `T: FromPyObject` on the derived implementation.\npub fn build_derive_from_pyobject(tokens: &DeriveInput) -> Result<TokenStream> {\n    let options = ContainerAttributes::from_attrs(&tokens.attrs)?;\n    let ctx = &Ctx::new(&options.krate, None);\n    let Ctx { pyo3_path, .. } = &ctx;\n\n    let (_, ty_generics, _) = tokens.generics.split_for_impl();\n    let mut trait_generics = tokens.generics.clone();\n    let lt_param = if let Some(lt) = verify_and_get_lifetime(&trait_generics)? {\n        lt.clone()\n    } else {\n        trait_generics.params.push(parse_quote!('py));\n        parse_quote!('py)\n    };\n    let (impl_generics, _, where_clause) = trait_generics.split_for_impl();\n\n    let mut where_clause = where_clause.cloned().unwrap_or_else(|| parse_quote!(where));\n    for param in trait_generics.type_params() {\n        let gen_ident = &param.ident;\n        where_clause\n            .predicates\n            .push(parse_quote!(#gen_ident: #pyo3_path::conversion::FromPyObjectOwned<#lt_param>))\n    }\n\n    let derives = match &tokens.data {\n        syn::Data::Enum(en) => {\n            if options.transparent.is_some() || options.annotation.is_some() {\n                bail_spanned!(tokens.span() => \"`transparent` or `annotation` is not supported \\\n                                                at top level for enums\");\n            }\n            let en = Enum::new(en, &tokens.ident, options.clone())?;\n            en.build(ctx)\n        }\n        syn::Data::Struct(st) => {\n            if let Some(lit_str) = &options.annotation {\n                bail_spanned!(lit_str.span() => \"`annotation` is unsupported for structs\");\n            }\n            let ident = &tokens.ident;\n            let st = Container::new(&st.fields, parse_quote!(#ident), options.clone())?;\n            st.build(ctx)\n        }\n        syn::Data::Union(_) => bail_spanned!(\n            tokens.span() => \"#[derive(FromPyObject)] is not supported for unions\"\n        ),\n    };\n\n    #[cfg(feature = \"experimental-inspect\")]\n    let input_type = {\n        let pyo3_crate_path = &ctx.pyo3_path;\n        let input_type = if tokens\n            .generics\n            .params\n            .iter()\n            .all(|p| matches!(p, syn::GenericParam::Lifetime(_)))\n        {\n            match &tokens.data {\n                syn::Data::Enum(en) => Enum::new(en, &tokens.ident, options)?.input_type(),\n                syn::Data::Struct(st) => {\n                    let ident = &tokens.ident;\n                    Container::new(&st.fields, parse_quote!(#ident), options.clone())?.input_type()\n                }\n                syn::Data::Union(_) => {\n                    // Not supported at this point\n                    PyExpr::module_attr(\"_typeshed\", \"Incomplete\")\n                }\n            }\n        } else {\n            // We don't know how to deal with generic parameters\n            // Blocked by https://github.com/rust-lang/rust/issues/76560\n            PyExpr::module_attr(\"_typeshed\", \"Incomplete\")\n        }\n        .to_introspection_token_stream(pyo3_crate_path);\n        quote! { const INPUT_TYPE: #pyo3_crate_path::inspect::PyStaticExpr = #input_type; }\n    };\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    let input_type = quote! {};\n\n    let ident = &tokens.ident;\n    Ok(quote!(\n        #[automatically_derived]\n        impl #impl_generics #pyo3_path::FromPyObject<'_, #lt_param> for #ident #ty_generics #where_clause {\n            type Error = #pyo3_path::PyErr;\n            fn extract(obj: #pyo3_path::Borrowed<'_, #lt_param, #pyo3_path::PyAny>) -> ::std::result::Result<Self, #pyo3_path::PyErr> {\n                let obj: &#pyo3_path::Bound<'_, _> = &*obj;\n                #derives\n            }\n            #input_type\n        }\n    ))\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/intopyobject.rs",
    "content": "use crate::attributes::{IntoPyWithAttribute, RenamingRule};\nuse crate::derive_attributes::{ContainerAttributes, FieldAttributes};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::py_expr::PyExpr;\nuse crate::utils::{self, Ctx};\nuse proc_macro2::{Span, TokenStream};\nuse quote::{format_ident, quote, quote_spanned, ToTokens};\nuse syn::ext::IdentExt;\nuse syn::spanned::Spanned as _;\nuse syn::{parse_quote, DataEnum, DeriveInput, Fields, Ident, Index, Result};\n\nstruct ItemOption(Option<syn::Lit>);\n\nenum IntoPyObjectTypes {\n    Transparent(syn::Type),\n    Opaque {\n        target: TokenStream,\n        output: TokenStream,\n        error: TokenStream,\n    },\n}\n\nstruct IntoPyObjectImpl {\n    types: IntoPyObjectTypes,\n    body: TokenStream,\n}\n\nstruct NamedStructField<'a> {\n    ident: &'a syn::Ident,\n    field: &'a syn::Field,\n    item: Option<ItemOption>,\n    into_py_with: Option<IntoPyWithAttribute>,\n}\n\nstruct TupleStructField<'a> {\n    field: &'a syn::Field,\n    into_py_with: Option<IntoPyWithAttribute>,\n}\n\n/// Container Style\n///\n/// Covers Structs, Tuplestructs and corresponding Newtypes.\nenum ContainerType<'a> {\n    /// Struct Container, e.g. `struct Foo { a: String }`\n    ///\n    /// Variant contains the list of field identifiers and the corresponding extraction call.\n    Struct(Vec<NamedStructField<'a>>),\n    /// Newtype struct container, e.g. `#[transparent] struct Foo { a: String }`\n    ///\n    /// The field specified by the identifier is extracted directly from the object.\n    StructNewtype(&'a syn::Field),\n    /// Tuple struct, e.g. `struct Foo(String)`.\n    ///\n    /// Variant contains a list of conversion methods for each of the fields that are directly\n    ///  extracted from the tuple.\n    Tuple(Vec<TupleStructField<'a>>),\n    /// Tuple newtype, e.g. `#[transparent] struct Foo(String)`\n    ///\n    /// The wrapped field is directly extracted from the object.\n    TupleNewtype(&'a syn::Field),\n}\n\n/// Data container\n///\n/// Either describes a struct or an enum variant.\nstruct Container<'a, const REF: bool> {\n    path: syn::Path,\n    receiver: Option<Ident>,\n    ty: ContainerType<'a>,\n    rename_rule: Option<RenamingRule>,\n}\n\n/// Construct a container based on fields, identifier and attributes.\nimpl<'a, const REF: bool> Container<'a, REF> {\n    ///\n    /// Fails if the variant has no fields or incompatible attributes.\n    fn new(\n        receiver: Option<Ident>,\n        fields: &'a Fields,\n        path: syn::Path,\n        options: ContainerAttributes,\n    ) -> Result<Self> {\n        let style = match fields {\n            Fields::Unnamed(unnamed) if !unnamed.unnamed.is_empty() => {\n                ensure_spanned!(\n                    options.rename_all.is_none(),\n                    options.rename_all.span() => \"`rename_all` is useless on tuple structs and variants.\"\n                );\n                let mut tuple_fields = unnamed\n                    .unnamed\n                    .iter()\n                    .map(|field| {\n                        let attrs = FieldAttributes::from_attrs(&field.attrs)?;\n                        ensure_spanned!(\n                            attrs.getter.is_none(),\n                            attrs.getter.unwrap().span() => \"`item` and `attribute` are not permitted on tuple struct elements.\"\n                        );\n                        Ok(TupleStructField {\n                            field,\n                            into_py_with: attrs.into_py_with,\n                        })\n                    })\n                    .collect::<Result<Vec<_>>>()?;\n                if tuple_fields.len() == 1 {\n                    // Always treat a 1-length tuple struct as \"transparent\", even without the\n                    // explicit annotation.\n                    let TupleStructField {\n                        field,\n                        into_py_with,\n                    } = tuple_fields.pop().unwrap();\n                    ensure_spanned!(\n                        into_py_with.is_none(),\n                        into_py_with.span() => \"`into_py_with` is not permitted on `transparent` structs\"\n                    );\n                    ContainerType::TupleNewtype(field)\n                } else if options.transparent.is_some() {\n                    bail_spanned!(\n                        fields.span() => \"transparent structs and variants can only have 1 field\"\n                    );\n                } else {\n                    ContainerType::Tuple(tuple_fields)\n                }\n            }\n            Fields::Named(named) if !named.named.is_empty() => {\n                if options.transparent.is_some() {\n                    ensure_spanned!(\n                        named.named.iter().count() == 1,\n                        fields.span() => \"transparent structs and variants can only have 1 field\"\n                    );\n\n                    let field = named.named.iter().next().unwrap();\n                    let attrs = FieldAttributes::from_attrs(&field.attrs)?;\n                    ensure_spanned!(\n                        attrs.getter.is_none(),\n                        attrs.getter.unwrap().span() => \"`transparent` structs may not have `item` nor `attribute` for the inner field\"\n                    );\n                    ensure_spanned!(\n                        options.rename_all.is_none(),\n                        options.rename_all.span() => \"`rename_all` is not permitted on `transparent` structs and variants\"\n                    );\n                    ensure_spanned!(\n                        attrs.into_py_with.is_none(),\n                        attrs.into_py_with.span() => \"`into_py_with` is not permitted on `transparent` structs or variants\"\n                    );\n                    ContainerType::StructNewtype(field)\n                } else {\n                    let struct_fields = named\n                        .named\n                        .iter()\n                        .map(|field| {\n                            let ident = field\n                                .ident\n                                .as_ref()\n                                .expect(\"Named fields should have identifiers\");\n\n                            let attrs = FieldAttributes::from_attrs(&field.attrs)?;\n\n                            Ok(NamedStructField {\n                                ident,\n                                field,\n                                item: attrs.getter.and_then(|getter| match getter {\n                                    crate::derive_attributes::FieldGetter::GetItem(_, lit) => {\n                                        Some(ItemOption(lit))\n                                    }\n                                    crate::derive_attributes::FieldGetter::GetAttr(_, _) => None,\n                                }),\n                                into_py_with: attrs.into_py_with,\n                            })\n                        })\n                        .collect::<Result<Vec<_>>>()?;\n                    ContainerType::Struct(struct_fields)\n                }\n            }\n            _ => bail_spanned!(\n                fields.span() => \"cannot derive `IntoPyObject` for empty structs\"\n            ),\n        };\n\n        let v = Container {\n            path,\n            receiver,\n            ty: style,\n            rename_rule: options.rename_all.map(|v| v.value.rule),\n        };\n        Ok(v)\n    }\n\n    fn match_pattern(&self) -> TokenStream {\n        let path = &self.path;\n        let pattern = match &self.ty {\n            ContainerType::Struct(fields) => fields\n                .iter()\n                .enumerate()\n                .map(|(i, f)| {\n                    let ident = f.ident;\n                    let new_ident = format_ident!(\"arg{i}\");\n                    quote! {#ident: #new_ident,}\n                })\n                .collect::<TokenStream>(),\n            ContainerType::StructNewtype(field) => {\n                let ident = field.ident.as_ref().unwrap();\n                quote!(#ident: arg0)\n            }\n            ContainerType::Tuple(fields) => {\n                let i = (0..fields.len()).map(Index::from);\n                let idents = (0..fields.len()).map(|i| format_ident!(\"arg{i}\"));\n                quote! { #(#i: #idents,)* }\n            }\n            ContainerType::TupleNewtype(_) => quote!(0: arg0),\n        };\n\n        quote! { #path{ #pattern } }\n    }\n\n    /// Build derivation body for a struct.\n    fn build(&self, ctx: &Ctx) -> IntoPyObjectImpl {\n        match &self.ty {\n            ContainerType::StructNewtype(field) | ContainerType::TupleNewtype(field) => {\n                self.build_newtype_struct(field, ctx)\n            }\n            ContainerType::Tuple(fields) => self.build_tuple_struct(fields, ctx),\n            ContainerType::Struct(fields) => self.build_struct(fields, ctx),\n        }\n    }\n\n    fn build_newtype_struct(&self, field: &syn::Field, ctx: &Ctx) -> IntoPyObjectImpl {\n        let Ctx { pyo3_path, .. } = ctx;\n        let ty = &field.ty;\n\n        let unpack = self\n            .receiver\n            .as_ref()\n            .map(|i| {\n                let pattern = self.match_pattern();\n                quote! { let #pattern = #i;}\n            })\n            .unwrap_or_default();\n\n        IntoPyObjectImpl {\n            types: IntoPyObjectTypes::Transparent(ty.clone()),\n            body: quote_spanned! { ty.span() =>\n                #unpack\n                #pyo3_path::conversion::IntoPyObject::into_pyobject(arg0, py)\n            },\n        }\n    }\n\n    fn build_struct(&self, fields: &[NamedStructField<'_>], ctx: &Ctx) -> IntoPyObjectImpl {\n        let Ctx { pyo3_path, .. } = ctx;\n\n        let unpack = self\n            .receiver\n            .as_ref()\n            .map(|i| {\n                let pattern = self.match_pattern();\n                quote! { let #pattern = #i;}\n            })\n            .unwrap_or_default();\n\n        let setter = fields\n            .iter()\n            .enumerate()\n            .map(|(i, f)| {\n                let key = f\n                    .item\n                    .as_ref()\n                    .and_then(|item| item.0.as_ref())\n                    .map(|item| item.into_token_stream())\n                    .unwrap_or_else(|| {\n                        let name = f.ident.unraw().to_string();\n                        self.rename_rule.map(|rule| utils::apply_renaming_rule(rule, &name)).unwrap_or(name).into_token_stream()\n                    });\n                let value = Ident::new(&format!(\"arg{i}\"), f.field.ty.span());\n\n                if let Some(expr_path) = f.into_py_with.as_ref().map(|i|&i.value) {\n                    let cow = if REF {\n                        quote!(::std::borrow::Cow::Borrowed(#value))\n                    } else {\n                        quote!(::std::borrow::Cow::Owned(#value))\n                    };\n                    quote! {\n                        let into_py_with: fn(::std::borrow::Cow<'_, _>, #pyo3_path::Python<'py>) -> #pyo3_path::PyResult<#pyo3_path::Bound<'py, #pyo3_path::PyAny>> = #expr_path;\n                        #pyo3_path::types::PyDictMethods::set_item(&dict, #key, into_py_with(#cow, py)?)?;\n                    }\n                } else {\n                    quote! {\n                        #pyo3_path::types::PyDictMethods::set_item(&dict, #key, #value)?;\n                    }\n                }\n            })\n            .collect::<TokenStream>();\n\n        IntoPyObjectImpl {\n            types: IntoPyObjectTypes::Opaque {\n                target: quote!(#pyo3_path::types::PyDict),\n                output: quote!(#pyo3_path::Bound<'py, Self::Target>),\n                error: quote!(#pyo3_path::PyErr),\n            },\n            body: quote! {\n                #unpack\n                let dict = #pyo3_path::types::PyDict::new(py);\n                #setter\n                ::std::result::Result::Ok::<_, Self::Error>(dict)\n            },\n        }\n    }\n\n    fn build_tuple_struct(&self, fields: &[TupleStructField<'_>], ctx: &Ctx) -> IntoPyObjectImpl {\n        let Ctx { pyo3_path, .. } = ctx;\n\n        let unpack = self\n            .receiver\n            .as_ref()\n            .map(|i| {\n                let pattern = self.match_pattern();\n                quote! { let #pattern = #i;}\n            })\n            .unwrap_or_default();\n\n        let setter = fields\n            .iter()\n            .enumerate()\n            .map(|(i, f)| {\n                let ty = &f.field.ty;\n                let value = Ident::new(&format!(\"arg{i}\"), f.field.ty.span());\n\n                if let Some(expr_path) = f.into_py_with.as_ref().map(|i|&i.value) {\n                    let cow = if REF {\n                        quote!(::std::borrow::Cow::Borrowed(#value))\n                    } else {\n                        quote!(::std::borrow::Cow::Owned(#value))\n                    };\n                    quote_spanned! { ty.span() =>\n                        {\n                            let into_py_with: fn(::std::borrow::Cow<'_, _>, #pyo3_path::Python<'py>) -> #pyo3_path::PyResult<#pyo3_path::Bound<'py, #pyo3_path::PyAny>> = #expr_path;\n                            into_py_with(#cow, py)?\n                        },\n                    }\n                } else {\n                    quote_spanned! { ty.span() =>\n                        #pyo3_path::conversion::IntoPyObject::into_pyobject(#value, py)\n                            .map(#pyo3_path::BoundObject::into_any)\n                            .map(#pyo3_path::BoundObject::into_bound)?,\n                    }\n                }\n            })\n            .collect::<TokenStream>();\n\n        IntoPyObjectImpl {\n            types: IntoPyObjectTypes::Opaque {\n                target: quote!(#pyo3_path::types::PyTuple),\n                output: quote!(#pyo3_path::Bound<'py, Self::Target>),\n                error: quote!(#pyo3_path::PyErr),\n            },\n            body: quote! {\n                #unpack\n                #pyo3_path::types::PyTuple::new(py, [#setter])\n            },\n        }\n    }\n\n    #[cfg(feature = \"experimental-inspect\")]\n    fn output_type(&self) -> PyExpr {\n        match &self.ty {\n            ContainerType::StructNewtype(field) | ContainerType::TupleNewtype(field) => {\n                Self::field_output_type(&None, &field.ty)\n            }\n            ContainerType::Tuple(tups) => PyExpr::subscript(\n                PyExpr::builtin(\"tuple\"),\n                PyExpr::tuple(tups.iter().map(\n                    |TupleStructField {\n                         into_py_with,\n                         field,\n                     }| { Self::field_output_type(into_py_with, &field.ty) },\n                )),\n            ),\n            ContainerType::Struct(_) => {\n                // TODO: implement using a Protocol?\n                PyExpr::module_attr(\"_typeshed\", \"Incomplete\")\n            }\n        }\n    }\n\n    #[cfg(feature = \"experimental-inspect\")]\n    fn field_output_type(into_py_with: &Option<IntoPyWithAttribute>, ty: &syn::Type) -> PyExpr {\n        if into_py_with.is_some() {\n            // We don't know what into_py_with is doing\n            PyExpr::module_attr(\"_typeshed\", \"Incomplete\")\n        } else {\n            PyExpr::from_into_py_object(ty.clone(), None)\n        }\n    }\n}\n\n/// Describes derivation input of an enum.\nstruct Enum<'a, const REF: bool> {\n    variants: Vec<Container<'a, REF>>,\n}\n\nimpl<'a, const REF: bool> Enum<'a, REF> {\n    /// Construct a new enum representation.\n    ///\n    /// `data_enum` is the `syn` representation of the input enum, `ident` is the\n    /// `Identifier` of the enum.\n    fn new(data_enum: &'a DataEnum, ident: &'a Ident) -> Result<Self> {\n        ensure_spanned!(\n            !data_enum.variants.is_empty(),\n            ident.span() => \"cannot derive `IntoPyObject` for empty enum\"\n        );\n        let variants = data_enum\n            .variants\n            .iter()\n            .map(|variant| {\n                let attrs = ContainerAttributes::from_attrs(&variant.attrs)?;\n                let var_ident = &variant.ident;\n\n                ensure_spanned!(\n                    !variant.fields.is_empty(),\n                    variant.ident.span() => \"cannot derive `IntoPyObject` for empty variants\"\n                );\n\n                Container::new(\n                    None,\n                    &variant.fields,\n                    parse_quote!(#ident::#var_ident),\n                    attrs,\n                )\n            })\n            .collect::<Result<Vec<_>>>()?;\n\n        Ok(Enum { variants })\n    }\n\n    /// Build derivation body for enums.\n    fn build(&self, ctx: &Ctx) -> IntoPyObjectImpl {\n        let Ctx { pyo3_path, .. } = ctx;\n\n        let variants = self\n            .variants\n            .iter()\n            .map(|v| {\n                let IntoPyObjectImpl { body, .. } = v.build(ctx);\n                let pattern = v.match_pattern();\n                quote! {\n                    #pattern => {\n                        {#body}\n                            .map(#pyo3_path::BoundObject::into_any)\n                            .map(#pyo3_path::BoundObject::into_bound)\n                            .map_err(::std::convert::Into::<#pyo3_path::PyErr>::into)\n                    }\n                }\n            })\n            .collect::<TokenStream>();\n\n        IntoPyObjectImpl {\n            types: IntoPyObjectTypes::Opaque {\n                target: quote!(#pyo3_path::types::PyAny),\n                output: quote!(#pyo3_path::Bound<'py, <Self as #pyo3_path::conversion::IntoPyObject<'py>>::Target>),\n                error: quote!(#pyo3_path::PyErr),\n            },\n            body: quote! {\n                match self {\n                    #variants\n                }\n            },\n        }\n    }\n\n    #[cfg(feature = \"experimental-inspect\")]\n    fn output_type(&self) -> PyExpr {\n        self.variants\n            .iter()\n            .map(|var| var.output_type())\n            .reduce(PyExpr::union)\n            .expect(\"Empty enum\")\n    }\n}\n\n// if there is a `'py` lifetime, we treat it as the `Python<'py>` lifetime\nfn verify_and_get_lifetime(generics: &syn::Generics) -> Option<&syn::LifetimeParam> {\n    let mut lifetimes = generics.lifetimes();\n    lifetimes.find(|l| l.lifetime.ident == \"py\")\n}\n\npub fn build_derive_into_pyobject<const REF: bool>(tokens: &DeriveInput) -> Result<TokenStream> {\n    let options = ContainerAttributes::from_attrs(&tokens.attrs)?;\n    let ctx = &Ctx::new(&options.krate, None);\n    let Ctx { pyo3_path, .. } = &ctx;\n\n    let (_, ty_generics, _) = tokens.generics.split_for_impl();\n    let mut trait_generics = tokens.generics.clone();\n    if REF {\n        trait_generics.params.push(parse_quote!('_a));\n    }\n    let lt_param = if let Some(lt) = verify_and_get_lifetime(&trait_generics) {\n        lt.clone()\n    } else {\n        trait_generics.params.push(parse_quote!('py));\n        parse_quote!('py)\n    };\n    let (impl_generics, _, where_clause) = trait_generics.split_for_impl();\n\n    let mut where_clause = where_clause.cloned().unwrap_or_else(|| parse_quote!(where));\n    for param in trait_generics.type_params() {\n        let gen_ident = &param.ident;\n        where_clause.predicates.push(if REF {\n            parse_quote!(&'_a #gen_ident: #pyo3_path::conversion::IntoPyObject<'py>)\n        } else {\n            parse_quote!(#gen_ident: #pyo3_path::conversion::IntoPyObject<'py>)\n        })\n    }\n\n    let IntoPyObjectImpl { types, body } = match &tokens.data {\n        syn::Data::Enum(en) => {\n            if options.transparent.is_some() {\n                bail_spanned!(tokens.span() => \"`transparent` is not supported at top level for enums\");\n            }\n            if let Some(rename_all) = options.rename_all {\n                bail_spanned!(rename_all.span() => \"`rename_all` is not supported at top level for enums\");\n            }\n            let en = Enum::<REF>::new(en, &tokens.ident)?;\n            en.build(ctx)\n        }\n        syn::Data::Struct(st) => {\n            let ident = &tokens.ident;\n            let st = Container::<REF>::new(\n                Some(Ident::new(\"self\", Span::call_site())),\n                &st.fields,\n                parse_quote!(#ident),\n                options.clone(),\n            )?;\n            st.build(ctx)\n        }\n        syn::Data::Union(_) => bail_spanned!(\n            tokens.span() => \"#[derive(`IntoPyObject`)] is not supported for unions\"\n        ),\n    };\n\n    let (target, output, error) = match types {\n        IntoPyObjectTypes::Transparent(ty) => {\n            if REF {\n                (\n                    quote! { <&'_a #ty as #pyo3_path::IntoPyObject<'py>>::Target },\n                    quote! { <&'_a #ty as #pyo3_path::IntoPyObject<'py>>::Output },\n                    quote! { <&'_a #ty as #pyo3_path::IntoPyObject<'py>>::Error },\n                )\n            } else {\n                (\n                    quote! { <#ty as #pyo3_path::IntoPyObject<'py>>::Target },\n                    quote! { <#ty as #pyo3_path::IntoPyObject<'py>>::Output },\n                    quote! { <#ty as #pyo3_path::IntoPyObject<'py>>::Error },\n                )\n            }\n        }\n        IntoPyObjectTypes::Opaque {\n            target,\n            output,\n            error,\n        } => (target, output, error),\n    };\n\n    let ident = &tokens.ident;\n    let ident = if REF {\n        quote! { &'_a #ident}\n    } else {\n        quote! { #ident }\n    };\n\n    #[cfg(feature = \"experimental-inspect\")]\n    let output_type = {\n        let pyo3_crate_path = &ctx.pyo3_path;\n        let output_type = if tokens\n            .generics\n            .params\n            .iter()\n            .all(|p| matches!(p, syn::GenericParam::Lifetime(_)))\n        {\n            match &tokens.data {\n                syn::Data::Enum(en) => Enum::<REF>::new(en, &tokens.ident)?.output_type(),\n                syn::Data::Struct(st) => {\n                    let ident = &tokens.ident;\n                    Container::<REF>::new(\n                        Some(Ident::new(\"self\", Span::call_site())),\n                        &st.fields,\n                        parse_quote!(#ident),\n                        options,\n                    )?\n                    .output_type()\n                }\n                syn::Data::Union(_) => {\n                    // Not supported at this point\n                    PyExpr::module_attr(\"_typeshed\", \"Incomplete\")\n                }\n            }\n        } else {\n            // We don't know how to deal with generic parameters\n            // Blocked by https://github.com/rust-lang/rust/issues/76560\n            PyExpr::module_attr(\"_typeshed\", \"Incomplete\")\n        }\n        .to_introspection_token_stream(pyo3_crate_path);\n        quote! { const OUTPUT_TYPE: #pyo3_path::inspect::PyStaticExpr = #output_type; }\n    };\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    let output_type = quote! {};\n\n    Ok(quote!(\n        #[automatically_derived]\n        impl #impl_generics #pyo3_path::conversion::IntoPyObject<#lt_param> for #ident #ty_generics #where_clause {\n            type Target = #target;\n            type Output = #output;\n            type Error = #error;\n            #output_type\n\n            fn into_pyobject(self, py: #pyo3_path::Python<#lt_param>) -> ::std::result::Result<\n                <Self as #pyo3_path::conversion::IntoPyObject<#lt_param>>::Output,\n                <Self as #pyo3_path::conversion::IntoPyObject<#lt_param>>::Error,\n            > {\n                #body\n            }\n        }\n    ))\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/introspection.rs",
    "content": "//! Generates introspection data i.e. JSON strings in the .pyo3i0 section.\n//!\n//! There is a JSON per PyO3 proc macro (pyclass, pymodule, pyfunction...).\n//!\n//! These JSON blobs can refer to each others via the _PYO3_INTROSPECTION_ID constants\n//! providing unique ids for each element.\n//!\n//! The JSON blobs format must be synchronized with the `pyo3_introspection::introspection.rs::Chunk`\n//! type that is used to parse them.\n\nuse crate::method::{FnArg, RegularArg};\nuse crate::py_expr::PyExpr;\nuse crate::pyfunction::FunctionSignature;\nuse crate::utils::{PyO3CratePath, PythonDoc, StrOrExpr};\nuse proc_macro2::{Span, TokenStream};\nuse quote::{format_ident, quote, ToTokens};\nuse std::borrow::Cow;\nuse std::collections::hash_map::DefaultHasher;\nuse std::collections::HashMap;\nuse std::fmt::Write;\nuse std::hash::{Hash, Hasher};\nuse std::mem::take;\nuse std::sync::atomic::{AtomicUsize, Ordering};\nuse syn::{Attribute, Ident, ReturnType, Type, TypePath};\n\nstatic GLOBAL_COUNTER_FOR_UNIQUE_NAMES: AtomicUsize = AtomicUsize::new(0);\n\npub fn module_introspection_code<'a>(\n    pyo3_crate_path: &PyO3CratePath,\n    name: &str,\n    members: impl IntoIterator<Item = &'a Ident>,\n    members_cfg_attrs: impl IntoIterator<Item = &'a Vec<Attribute>>,\n    doc: Option<&PythonDoc>,\n    incomplete: bool,\n) -> TokenStream {\n    let mut desc = HashMap::from([\n        (\"type\", IntrospectionNode::String(\"module\".into())),\n        (\"id\", IntrospectionNode::IntrospectionId(None)),\n        (\"name\", IntrospectionNode::String(name.into())),\n        (\n            \"members\",\n            IntrospectionNode::List(\n                members\n                    .into_iter()\n                    .zip(members_cfg_attrs)\n                    .map(|(member, attributes)| AttributedIntrospectionNode {\n                        node: IntrospectionNode::IntrospectionId(Some(ident_to_type(member))),\n                        attributes,\n                    })\n                    .collect(),\n            ),\n        ),\n        (\"incomplete\", IntrospectionNode::Bool(incomplete)),\n    ]);\n    if let Some(doc) = doc {\n        desc.insert(\"doc\", IntrospectionNode::Doc(doc));\n    }\n    IntrospectionNode::Map(desc).emit(pyo3_crate_path)\n}\n\npub fn class_introspection_code(\n    pyo3_crate_path: &PyO3CratePath,\n    ident: &Ident,\n    name: &str,\n    extends: Option<PyExpr>,\n    is_final: bool,\n    parent: Option<&Type>,\n    doc: Option<&PythonDoc>,\n) -> TokenStream {\n    let mut desc = HashMap::from([\n        (\"type\", IntrospectionNode::String(\"class\".into())),\n        (\n            \"id\",\n            IntrospectionNode::IntrospectionId(Some(ident_to_type(ident))),\n        ),\n        (\"name\", IntrospectionNode::String(name.into())),\n    ]);\n    if let Some(extends) = extends {\n        desc.insert(\"bases\", IntrospectionNode::List(vec![extends.into()]));\n    }\n    if is_final {\n        desc.insert(\n            \"decorators\",\n            IntrospectionNode::List(vec![PyExpr::module_attr(\"typing\", \"final\").into()]),\n        );\n    }\n    if let Some(parent) = parent {\n        desc.insert(\n            \"parent\",\n            IntrospectionNode::IntrospectionId(Some(Cow::Borrowed(parent))),\n        );\n    }\n    if let Some(doc) = &doc {\n        desc.insert(\"doc\", IntrospectionNode::Doc(doc));\n    }\n    IntrospectionNode::Map(desc).emit(pyo3_crate_path)\n}\n\n#[expect(clippy::too_many_arguments)]\npub fn function_introspection_code(\n    pyo3_crate_path: &PyO3CratePath,\n    ident: Option<&Ident>,\n    name: &str,\n    signature: &FunctionSignature<'_>,\n    first_argument: Option<&'static str>,\n    returns: ReturnType,\n    decorators: impl IntoIterator<Item = PyExpr>,\n    is_async: bool,\n    is_returning_not_implemented_on_extraction_error: bool,\n    doc: Option<&PythonDoc>,\n    parent: Option<&Type>,\n) -> TokenStream {\n    let mut desc = HashMap::from([\n        (\"type\", IntrospectionNode::String(\"function\".into())),\n        (\"name\", IntrospectionNode::String(name.into())),\n        (\n            \"arguments\",\n            arguments_introspection_data(\n                signature,\n                first_argument,\n                is_returning_not_implemented_on_extraction_error,\n                parent,\n            ),\n        ),\n        (\n            \"returns\",\n            if let Some((_, returns)) = signature\n                .attribute\n                .as_ref()\n                .and_then(|attribute| attribute.value.returns.as_ref())\n            {\n                returns.as_type_hint().into()\n            } else {\n                match returns {\n                    ReturnType::Default => PyExpr::builtin(\"None\"),\n                    ReturnType::Type(_, ty) => PyExpr::from_return_type(*ty, parent),\n                }\n                .into()\n            },\n        ),\n    ]);\n    if is_async {\n        desc.insert(\"async\", IntrospectionNode::Bool(true));\n    }\n    if let Some(ident) = ident {\n        desc.insert(\n            \"id\",\n            IntrospectionNode::IntrospectionId(Some(ident_to_type(ident))),\n        );\n    }\n    let decorators = decorators.into_iter().map(|d| d.into()).collect::<Vec<_>>();\n    if !decorators.is_empty() {\n        desc.insert(\"decorators\", IntrospectionNode::List(decorators));\n    }\n    if let Some(doc) = doc {\n        desc.insert(\"doc\", IntrospectionNode::Doc(doc));\n    }\n    if let Some(parent) = parent {\n        desc.insert(\n            \"parent\",\n            IntrospectionNode::IntrospectionId(Some(Cow::Borrowed(parent))),\n        );\n    }\n    IntrospectionNode::Map(desc).emit(pyo3_crate_path)\n}\n\npub fn attribute_introspection_code(\n    pyo3_crate_path: &PyO3CratePath,\n    parent: Option<&Type>,\n    name: String,\n    value: PyExpr,\n    rust_type: Type,\n    doc: Option<&PythonDoc>,\n    is_final: bool,\n) -> TokenStream {\n    let mut desc = HashMap::from([\n        (\"type\", IntrospectionNode::String(\"attribute\".into())),\n        (\"name\", IntrospectionNode::String(name.into())),\n        (\n            \"parent\",\n            IntrospectionNode::IntrospectionId(parent.map(Cow::Borrowed)),\n        ),\n    ]);\n    if value == PyExpr::ellipsis() {\n        // We need to set a type, but not need to set the value to ..., all attributes have a value\n        desc.insert(\n            \"annotation\",\n            if is_final {\n                PyExpr::subscript(\n                    PyExpr::module_attr(\"typing\", \"Final\"),\n                    PyExpr::from_return_type(rust_type, parent),\n                )\n                .into()\n            } else {\n                PyExpr::from_return_type(rust_type, parent).into()\n            },\n        );\n    } else {\n        desc.insert(\n            \"annotation\",\n            if is_final {\n                // Type checkers can infer the type from the value because it's typing.Literal[value]\n                // So, following stubs best practices, we only write typing.Final and not\n                // typing.Final[typing.literal[value]]\n                PyExpr::module_attr(\"typing\", \"Final\")\n            } else {\n                PyExpr::from_return_type(rust_type, parent)\n            }\n            .into(),\n        );\n        desc.insert(\"value\", value.into());\n    }\n    if let Some(doc) = doc {\n        desc.insert(\"doc\", IntrospectionNode::Doc(doc));\n    }\n    IntrospectionNode::Map(desc).emit(pyo3_crate_path)\n}\n\nfn arguments_introspection_data<'a>(\n    signature: &'a FunctionSignature<'a>,\n    first_argument: Option<&'a str>,\n    is_returning_not_implemented_on_extraction_error: bool,\n    class_type: Option<&Type>,\n) -> IntrospectionNode<'a> {\n    let mut argument_desc = signature.arguments.iter().filter(|arg| {\n        matches!(\n            arg,\n            FnArg::Regular(_) | FnArg::VarArgs(_) | FnArg::KwArgs(_)\n        )\n    });\n\n    let mut posonlyargs = Vec::new();\n    let mut args = Vec::new();\n    let mut vararg = None;\n    let mut kwonlyargs = Vec::new();\n    let mut kwarg = None;\n\n    if let Some(first_argument) = first_argument {\n        posonlyargs.push(\n            IntrospectionNode::Map(\n                [(\"name\", IntrospectionNode::String(first_argument.into()))].into(),\n            )\n            .into(),\n        );\n    }\n\n    for (i, param) in signature\n        .python_signature\n        .positional_parameters\n        .iter()\n        .enumerate()\n    {\n        let arg_desc = if let Some(FnArg::Regular(arg_desc)) = argument_desc.next() {\n            arg_desc\n        } else {\n            panic!(\"Less arguments than in python signature\");\n        };\n        let arg = argument_introspection_data(\n            param,\n            arg_desc,\n            is_returning_not_implemented_on_extraction_error,\n            class_type,\n        );\n        if i < signature.python_signature.positional_only_parameters {\n            posonlyargs.push(arg);\n        } else {\n            args.push(arg)\n        }\n    }\n\n    if let Some(param) = &signature.python_signature.varargs {\n        let Some(FnArg::VarArgs(arg_desc)) = argument_desc.next() else {\n            panic!(\"Fewer arguments than in python signature\");\n        };\n        let mut params = HashMap::from([(\"name\", IntrospectionNode::String(param.into()))]);\n        if let Some(annotation) = &arg_desc.annotation {\n            params.insert(\"annotation\", annotation.clone().into());\n        }\n        vararg = Some(IntrospectionNode::Map(params));\n    }\n\n    for (param, _) in &signature.python_signature.keyword_only_parameters {\n        let Some(FnArg::Regular(arg_desc)) = argument_desc.next() else {\n            panic!(\"Less arguments than in python signature\");\n        };\n        kwonlyargs.push(argument_introspection_data(\n            param,\n            arg_desc,\n            is_returning_not_implemented_on_extraction_error,\n            class_type,\n        ));\n    }\n\n    if let Some(param) = &signature.python_signature.kwargs {\n        let Some(FnArg::KwArgs(arg_desc)) = argument_desc.next() else {\n            panic!(\"Less arguments than in python signature\");\n        };\n        let mut params = HashMap::from([(\"name\", IntrospectionNode::String(param.into()))]);\n        if let Some(annotation) = &arg_desc.annotation {\n            params.insert(\"annotation\", annotation.clone().into());\n        }\n        kwarg = Some(IntrospectionNode::Map(params));\n    }\n\n    let mut map = HashMap::new();\n    if !posonlyargs.is_empty() {\n        map.insert(\"posonlyargs\", IntrospectionNode::List(posonlyargs));\n    }\n    if !args.is_empty() {\n        map.insert(\"args\", IntrospectionNode::List(args));\n    }\n    if let Some(vararg) = vararg {\n        map.insert(\"vararg\", vararg);\n    }\n    if !kwonlyargs.is_empty() {\n        map.insert(\"kwonlyargs\", IntrospectionNode::List(kwonlyargs));\n    }\n    if let Some(kwarg) = kwarg {\n        map.insert(\"kwarg\", kwarg);\n    }\n    IntrospectionNode::Map(map)\n}\n\nfn argument_introspection_data<'a>(\n    name: &'a str,\n    desc: &'a RegularArg<'_>,\n    is_returning_not_implemented_on_extraction_error: bool,\n    class_type: Option<&Type>,\n) -> AttributedIntrospectionNode<'a> {\n    let mut params: HashMap<_, _> = [(\"name\", IntrospectionNode::String(name.into()))].into();\n    if let Some(expr) = &desc.default_value {\n        params.insert(\"default\", PyExpr::constant_from_expression(expr).into());\n    }\n\n    if is_returning_not_implemented_on_extraction_error {\n        // all inputs are allowed, we use `object`\n        params.insert(\"annotation\", PyExpr::builtin(\"object\").into());\n    } else if let Some(annotation) = &desc.annotation {\n        params.insert(\"annotation\", annotation.clone().into());\n    } else if desc.from_py_with.is_none() {\n        // If from_py_with is set we don't know anything on the input type\n        params.insert(\n            \"annotation\",\n            PyExpr::from_argument_type(desc.ty.clone(), class_type).into(),\n        );\n    }\n    IntrospectionNode::Map(params).into()\n}\n\nenum IntrospectionNode<'a> {\n    String(Cow<'a, str>),\n    Bool(bool),\n    IntrospectionId(Option<Cow<'a, Type>>),\n    TypeHint(Cow<'a, PyExpr>),\n    Doc(&'a PythonDoc),\n    Map(HashMap<&'static str, IntrospectionNode<'a>>),\n    List(Vec<AttributedIntrospectionNode<'a>>),\n}\n\nimpl IntrospectionNode<'_> {\n    fn emit(self, pyo3_crate_path: &PyO3CratePath) -> TokenStream {\n        let mut content = ConcatenationBuilder::default();\n        self.add_to_serialization(&mut content, pyo3_crate_path);\n        content.into_static(\n            pyo3_crate_path,\n            format_ident!(\"PYO3_INTROSPECTION_1_{}\", unique_element_id()),\n        )\n    }\n\n    fn add_to_serialization(\n        self,\n        content: &mut ConcatenationBuilder,\n        pyo3_crate_path: &PyO3CratePath,\n    ) {\n        match self {\n            Self::String(string) => {\n                content.push_str_to_escape(&string);\n            }\n            Self::Bool(value) => content.push_str(if value { \"true\" } else { \"false\" }),\n            Self::IntrospectionId(ident) => {\n                content.push_str(\"\\\"\");\n                content.push_tokens(if let Some(ident) = ident {\n                    quote! { #ident::_PYO3_INTROSPECTION_ID.as_bytes() }\n                } else {\n                    quote! { _PYO3_INTROSPECTION_ID.as_bytes() }\n                });\n                content.push_str(\"\\\"\");\n            }\n            Self::TypeHint(hint) => {\n                content.push_tokens(serialize_type_hint(\n                    hint.to_introspection_token_stream(pyo3_crate_path),\n                    pyo3_crate_path,\n                ));\n            }\n            Self::Doc(doc) => {\n                content.push_str(\"\\\"\");\n                for part in &doc.parts {\n                    match part {\n                        StrOrExpr::Str {value, ..} => content.push_str(&escape_json_string(value)),\n                        StrOrExpr::Expr(value) => content.push_tokens(quote! {{\n                            const DOC: &str = #value;\n                            const DOC_LEN: usize = #pyo3_crate_path::impl_::introspection::escaped_json_string_len(&DOC);\n                            const DOC_SER: [u8; DOC_LEN] = {\n                                let mut result: [u8; DOC_LEN] = [0; DOC_LEN];\n                                #pyo3_crate_path::impl_::introspection::escape_json_string(&DOC, &mut result);\n                                result\n                            };\n                            &DOC_SER\n                        }}),\n                    }\n                }\n                content.push_str(\"\\\"\");\n            }\n            Self::Map(map) => {\n                content.push_str(\"{\");\n                for (i, (key, value)) in map.into_iter().enumerate() {\n                    if i > 0 {\n                        content.push_str(\",\");\n                    }\n                    content.push_str_to_escape(key);\n                    content.push_str(\":\");\n                    value.add_to_serialization(content, pyo3_crate_path);\n                }\n                content.push_str(\"}\");\n            }\n            Self::List(list) => {\n                content.push_str(\"[\");\n                for (i, AttributedIntrospectionNode { node, attributes }) in\n                    list.into_iter().enumerate()\n                {\n                    if attributes.is_empty() {\n                        if i > 0 {\n                            content.push_str(\",\");\n                        }\n                        node.add_to_serialization(content, pyo3_crate_path);\n                    } else {\n                        // We serialize the element to easily gate it behind the attributes\n                        let mut nested_builder = ConcatenationBuilder::default();\n                        if i > 0 {\n                            nested_builder.push_str(\",\");\n                        }\n                        node.add_to_serialization(&mut nested_builder, pyo3_crate_path);\n                        let nested_content = nested_builder.into_token_stream(pyo3_crate_path);\n                        content.push_tokens(quote! { #(#attributes)* #nested_content });\n                    }\n                }\n                content.push_str(\"]\");\n            }\n        }\n    }\n}\n\nimpl From<PyExpr> for IntrospectionNode<'static> {\n    fn from(element: PyExpr) -> Self {\n        Self::TypeHint(Cow::Owned(element))\n    }\n}\n\nfn serialize_type_hint(hint: TokenStream, pyo3_crate_path: &PyO3CratePath) -> TokenStream {\n    quote! {{\n        const TYPE_HINT: #pyo3_crate_path::inspect::PyStaticExpr = #hint;\n        const TYPE_HINT_LEN: usize = #pyo3_crate_path::inspect::serialized_len_for_introspection(&TYPE_HINT);\n        const TYPE_HINT_SER: [u8; TYPE_HINT_LEN] = {\n            let mut result: [u8; TYPE_HINT_LEN] = [0; TYPE_HINT_LEN];\n            #pyo3_crate_path::inspect::serialize_for_introspection(&TYPE_HINT, &mut result);\n            result\n        };\n        &TYPE_HINT_SER\n    }}\n}\n\nstruct AttributedIntrospectionNode<'a> {\n    node: IntrospectionNode<'a>,\n    attributes: &'a [Attribute],\n}\n\nimpl<'a> From<IntrospectionNode<'a>> for AttributedIntrospectionNode<'a> {\n    fn from(node: IntrospectionNode<'a>) -> Self {\n        Self {\n            node,\n            attributes: &[],\n        }\n    }\n}\n\nimpl<'a> From<PyExpr> for AttributedIntrospectionNode<'a> {\n    fn from(node: PyExpr) -> Self {\n        IntrospectionNode::from(node).into()\n    }\n}\n\n#[derive(Default)]\npub struct ConcatenationBuilder {\n    elements: Vec<ConcatenationBuilderElement>,\n    current_string: String,\n}\n\nimpl ConcatenationBuilder {\n    pub fn push_tokens(&mut self, token_stream: TokenStream) {\n        if !self.current_string.is_empty() {\n            self.elements.push(ConcatenationBuilderElement::String(take(\n                &mut self.current_string,\n            )));\n        }\n        self.elements\n            .push(ConcatenationBuilderElement::TokenStream(token_stream));\n    }\n\n    pub fn push_str(&mut self, value: &str) {\n        self.current_string.push_str(value);\n    }\n\n    fn push_str_to_escape(&mut self, value: &str) {\n        self.current_string.push('\"');\n        for c in value.chars() {\n            match c {\n                '\\\\' => self.current_string.push_str(\"\\\\\\\\\"),\n                '\"' => self.current_string.push_str(\"\\\\\\\"\"),\n                c => {\n                    if c < char::from(32) {\n                        panic!(\"ASCII chars below 32 are not allowed\")\n                    } else {\n                        self.current_string.push(c);\n                    }\n                }\n            }\n        }\n        self.current_string.push('\"');\n    }\n\n    pub fn into_token_stream(self, pyo3_crate_path: &PyO3CratePath) -> TokenStream {\n        let mut elements = self.elements;\n        if !self.current_string.is_empty() {\n            elements.push(ConcatenationBuilderElement::String(self.current_string));\n        }\n\n        if let [ConcatenationBuilderElement::String(string)] = elements.as_slice() {\n            // We avoid the const_concat! macro if there is only a single string\n            return quote! { #string.as_bytes() };\n        }\n\n        quote! {\n            {\n                const PIECES: &[&[u8]] = &[#(#elements , )*];\n                &#pyo3_crate_path::impl_::concat::combine_to_array::<{\n                    #pyo3_crate_path::impl_::concat::combined_len(PIECES)\n                }>(PIECES)\n            }\n        }\n    }\n\n    fn into_static(self, pyo3_crate_path: &PyO3CratePath, ident: Ident) -> TokenStream {\n        let mut elements = self.elements;\n        if !self.current_string.is_empty() {\n            elements.push(ConcatenationBuilderElement::String(self.current_string));\n        }\n\n        // #[no_mangle] is required to make sure some linkers like Linux ones do not mangle the section name too.\n        quote! {\n            const _: () = {\n                const PIECES: &[&[u8]] = &[#(#elements , )*];\n                const PIECES_LEN: usize = #pyo3_crate_path::impl_::concat::combined_len(PIECES);\n                #[used]\n                #[no_mangle]\n                static #ident: #pyo3_crate_path::impl_::introspection::SerializedIntrospectionFragment<PIECES_LEN> = #pyo3_crate_path::impl_::introspection::SerializedIntrospectionFragment {\n                    length: PIECES_LEN as u32,\n                    fragment: #pyo3_crate_path::impl_::concat::combine_to_array::<PIECES_LEN>(PIECES)\n                };\n            };\n        }\n    }\n}\n\nenum ConcatenationBuilderElement {\n    String(String),\n    TokenStream(TokenStream),\n}\n\nimpl ToTokens for ConcatenationBuilderElement {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        match self {\n            Self::String(s) => quote! { #s.as_bytes() }.to_tokens(tokens),\n            Self::TokenStream(ts) => ts.to_tokens(tokens),\n        }\n    }\n}\n\n/// Generates a new unique identifier for linking introspection objects together\npub fn introspection_id_const() -> TokenStream {\n    let id = unique_element_id().to_string();\n    quote! {\n        #[doc(hidden)]\n        pub const _PYO3_INTROSPECTION_ID: &'static str = #id;\n    }\n}\n\npub fn unique_element_id() -> u64 {\n    let mut hasher = DefaultHasher::new();\n    format!(\"{:?}\", Span::call_site()).hash(&mut hasher); // Distinguishes between call sites\n    GLOBAL_COUNTER_FOR_UNIQUE_NAMES\n        .fetch_add(1, Ordering::Relaxed)\n        .hash(&mut hasher); // If there are multiple elements in the same call site\n    hasher.finish()\n}\n\nfn ident_to_type(ident: &Ident) -> Cow<'static, Type> {\n    Cow::Owned(\n        TypePath {\n            path: ident.clone().into(),\n            qself: None,\n        }\n        .into(),\n    )\n}\n\nfn escape_json_string(value: &str) -> String {\n    let mut output = String::with_capacity(value.len());\n    for c in value.chars() {\n        match c {\n            '\\\\' => output.push_str(\"\\\\\\\\\"),\n            '\"' => output.push_str(\"\\\\\\\"\"),\n            '\\x08' => output.push_str(\"\\\\b\"),\n            '\\x0C' => output.push_str(\"\\\\f\"),\n            '\\n' => output.push_str(\"\\\\n\"),\n            '\\r' => output.push_str(\"\\\\r\"),\n            '\\t' => output.push_str(\"\\\\t\"),\n            c @ '\\0'..='\\x1F' => {\n                write!(output, \"\\\\u{:0>4x}\", u32::from(c)).unwrap();\n            }\n            c => output.push(c),\n        }\n    }\n    output\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/konst.rs",
    "content": "use std::borrow::Cow;\nuse std::ffi::CString;\n\nuse crate::attributes::{self, get_pyo3_options, take_attributes, NameAttribute};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::utils::PythonDoc;\nuse proc_macro2::{Ident, Span};\nuse syn::LitCStr;\nuse syn::{\n    ext::IdentExt,\n    parse::{Parse, ParseStream},\n    spanned::Spanned,\n    Result,\n};\n\npub struct ConstSpec {\n    pub rust_ident: Ident,\n    pub attributes: ConstAttributes,\n    #[cfg(feature = \"experimental-inspect\")]\n    pub expr: Option<syn::Expr>,\n    #[cfg(feature = \"experimental-inspect\")]\n    pub ty: syn::Type,\n    #[cfg(feature = \"experimental-inspect\")]\n    pub doc: Option<PythonDoc>,\n}\n\nimpl ConstSpec {\n    pub fn python_name(&self) -> Cow<'_, Ident> {\n        if let Some(name) = &self.attributes.name {\n            Cow::Borrowed(&name.value.0)\n        } else {\n            Cow::Owned(self.rust_ident.unraw())\n        }\n    }\n\n    /// Null-terminated Python name\n    pub fn null_terminated_python_name(&self) -> LitCStr {\n        let name = self.python_name().to_string();\n        LitCStr::new(&CString::new(name).unwrap(), Span::call_site())\n    }\n}\n\npub struct ConstAttributes {\n    pub is_class_attr: bool,\n    pub name: Option<NameAttribute>,\n}\n\npub enum PyO3ConstAttribute {\n    Name(NameAttribute),\n}\n\nimpl Parse for PyO3ConstAttribute {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let lookahead = input.lookahead1();\n        if lookahead.peek(attributes::kw::name) {\n            input.parse().map(PyO3ConstAttribute::Name)\n        } else {\n            Err(lookahead.error())\n        }\n    }\n}\n\nimpl ConstAttributes {\n    pub fn from_attrs(attrs: &mut Vec<syn::Attribute>) -> syn::Result<Self> {\n        let mut attributes = ConstAttributes {\n            is_class_attr: false,\n            name: None,\n        };\n\n        take_attributes(attrs, |attr| {\n            if attr.path().is_ident(\"classattr\") {\n                ensure_spanned!(\n                    matches!(attr.meta, syn::Meta::Path(..)),\n                    attr.span() => \"`#[classattr]` does not take any arguments\"\n                );\n                attributes.is_class_attr = true;\n                Ok(true)\n            } else if let Some(pyo3_attributes) = get_pyo3_options(attr)? {\n                for pyo3_attr in pyo3_attributes {\n                    match pyo3_attr {\n                        PyO3ConstAttribute::Name(name) => attributes.set_name(name)?,\n                    }\n                }\n                Ok(true)\n            } else {\n                Ok(false)\n            }\n        })?;\n\n        Ok(attributes)\n    }\n\n    fn set_name(&mut self, name: NameAttribute) -> Result<()> {\n        ensure_spanned!(\n            self.name.is_none(),\n            name.span() => \"`name` may only be specified once\"\n        );\n        self.name = Some(name);\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/lib.rs",
    "content": "//! This crate contains the implementation of the proc macro attributes\n\n#![warn(elided_lifetimes_in_paths, unused_lifetimes)]\n#![cfg_attr(docsrs, feature(doc_cfg))]\n#![recursion_limit = \"1024\"]\n\n// Listed first so that macros in this module are available in the rest of the crate.\n#[macro_use]\nmod utils;\n\nmod attributes;\nmod combine_errors;\nmod derive_attributes;\nmod frompyobject;\nmod intopyobject;\n#[cfg(feature = \"experimental-inspect\")]\nmod introspection;\nmod konst;\nmod method;\nmod module;\nmod params;\n#[cfg(feature = \"experimental-inspect\")]\nmod py_expr;\nmod pyclass;\nmod pyfunction;\nmod pyimpl;\nmod pymethod;\nmod quotes;\n\npub use frompyobject::build_derive_from_pyobject;\npub use intopyobject::build_derive_into_pyobject;\npub use module::{pymodule_function_impl, pymodule_module_impl, PyModuleOptions};\npub use pyclass::{build_py_class, build_py_enum, PyClassArgs};\npub use pyfunction::{build_py_function, PyFunctionOptions};\npub use pyimpl::{build_py_methods, PyClassMethodsType};\npub use utils::get_doc;\n"
  },
  {
    "path": "pyo3-macros-backend/src/method.rs",
    "content": "use std::borrow::Cow;\nuse std::ffi::CString;\nuse std::fmt::Display;\n\nuse proc_macro2::{Span, TokenStream};\nuse quote::{quote, quote_spanned, ToTokens};\nuse syn::LitCStr;\nuse syn::{ext::IdentExt, spanned::Spanned, Ident, Result};\n\nuse crate::params::is_forwarded_args;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::py_expr::PyExpr;\nuse crate::pyfunction::{PyFunctionWarning, WarningFactory};\nuse crate::utils::Ctx;\nuse crate::{\n    attributes::{FromPyWithAttribute, TextSignatureAttribute, TextSignatureAttributeValue},\n    params::{impl_arg_params, Holders},\n    pyfunction::{\n        FunctionSignature, PyFunctionArgPyO3Attributes, PyFunctionOptions, SignatureAttribute,\n    },\n    quotes,\n    utils::{self, PythonDoc},\n};\n\n#[derive(Clone, Debug)]\npub struct RegularArg<'a> {\n    pub name: Cow<'a, syn::Ident>,\n    pub ty: &'a syn::Type,\n    pub from_py_with: Option<Box<FromPyWithAttribute>>,\n    pub default_value: Option<Box<syn::Expr>>,\n    pub option_wrapped_type: Option<&'a syn::Type>,\n    #[cfg(feature = \"experimental-inspect\")]\n    pub annotation: Option<PyExpr>,\n}\n\n/// Pythons *args argument\n#[derive(Clone, Debug)]\npub struct VarargsArg<'a> {\n    pub name: Cow<'a, syn::Ident>,\n    pub ty: &'a syn::Type,\n    #[cfg(feature = \"experimental-inspect\")]\n    pub annotation: Option<PyExpr>,\n}\n\n/// Pythons **kwarg argument\n#[derive(Clone, Debug)]\npub struct KwargsArg<'a> {\n    pub name: Cow<'a, syn::Ident>,\n    pub ty: &'a syn::Type,\n    #[cfg(feature = \"experimental-inspect\")]\n    pub annotation: Option<PyExpr>,\n}\n\n#[derive(Clone, Debug)]\npub struct CancelHandleArg<'a> {\n    pub name: &'a syn::Ident,\n    pub ty: &'a syn::Type,\n}\n\n#[derive(Clone, Debug)]\npub struct PyArg<'a> {\n    pub name: &'a syn::Ident,\n    pub ty: &'a syn::Type,\n}\n\n#[derive(Clone, Debug)]\npub enum FnArg<'a> {\n    Regular(RegularArg<'a>),\n    VarArgs(VarargsArg<'a>),\n    KwArgs(KwargsArg<'a>),\n    Py(PyArg<'a>),\n    CancelHandle(CancelHandleArg<'a>),\n}\n\nimpl<'a> FnArg<'a> {\n    pub fn name(&self) -> &syn::Ident {\n        match self {\n            FnArg::Regular(RegularArg { name, .. }) => name,\n            FnArg::VarArgs(VarargsArg { name, .. }) => name,\n            FnArg::KwArgs(KwargsArg { name, .. }) => name,\n            FnArg::Py(PyArg { name, .. }) => name,\n            FnArg::CancelHandle(CancelHandleArg { name, .. }) => name,\n        }\n    }\n\n    pub fn ty(&self) -> &'a syn::Type {\n        match self {\n            FnArg::Regular(RegularArg { ty, .. }) => ty,\n            FnArg::VarArgs(VarargsArg { ty, .. }) => ty,\n            FnArg::KwArgs(KwargsArg { ty, .. }) => ty,\n            FnArg::Py(PyArg { ty, .. }) => ty,\n            FnArg::CancelHandle(CancelHandleArg { ty, .. }) => ty,\n        }\n    }\n\n    #[expect(\n        clippy::wrong_self_convention,\n        reason = \"called `from_` but not a constructor\"\n    )]\n    pub fn from_py_with(&self) -> Option<&FromPyWithAttribute> {\n        if let FnArg::Regular(RegularArg { from_py_with, .. }) = self {\n            from_py_with.as_deref()\n        } else {\n            None\n        }\n    }\n\n    pub fn to_varargs_mut(&mut self) -> Result<&mut Self> {\n        if let Self::Regular(RegularArg {\n            name,\n            ty,\n            option_wrapped_type: None,\n            #[cfg(feature = \"experimental-inspect\")]\n            annotation,\n            ..\n        }) = self\n        {\n            *self = Self::VarArgs(VarargsArg {\n                name: name.clone(),\n                ty,\n                #[cfg(feature = \"experimental-inspect\")]\n                annotation: annotation.clone(),\n            });\n            Ok(self)\n        } else {\n            bail_spanned!(self.name().span() => \"args cannot be optional\")\n        }\n    }\n\n    pub fn to_kwargs_mut(&mut self) -> Result<&mut Self> {\n        if let Self::Regular(RegularArg {\n            name,\n            ty,\n            option_wrapped_type: Some(..),\n            #[cfg(feature = \"experimental-inspect\")]\n            annotation,\n            ..\n        }) = self\n        {\n            *self = Self::KwArgs(KwargsArg {\n                name: name.clone(),\n                ty,\n                #[cfg(feature = \"experimental-inspect\")]\n                annotation: annotation.clone(),\n            });\n            Ok(self)\n        } else {\n            bail_spanned!(self.name().span() => \"kwargs must be Option<_>\")\n        }\n    }\n\n    /// Transforms a rust fn arg parsed with syn into a method::FnArg\n    pub fn parse(arg: &'a mut syn::FnArg) -> Result<Self> {\n        match arg {\n            syn::FnArg::Receiver(recv) => {\n                bail_spanned!(recv.span() => \"unexpected receiver\")\n            } // checked in parse_fn_type\n            syn::FnArg::Typed(cap) => {\n                if let syn::Type::ImplTrait(_) = &*cap.ty {\n                    bail_spanned!(cap.ty.span() => IMPL_TRAIT_ERR);\n                }\n\n                let PyFunctionArgPyO3Attributes {\n                    from_py_with,\n                    cancel_handle,\n                } = PyFunctionArgPyO3Attributes::from_attrs(&mut cap.attrs)?;\n                let ident = match &*cap.pat {\n                    syn::Pat::Ident(syn::PatIdent { ident, .. }) => ident,\n                    other => return Err(handle_argument_error(other)),\n                };\n\n                if utils::is_python(&cap.ty) {\n                    return Ok(Self::Py(PyArg {\n                        name: ident,\n                        ty: &cap.ty,\n                    }));\n                }\n\n                if cancel_handle.is_some() {\n                    // `PyFunctionArgPyO3Attributes::from_attrs` validates that\n                    // only compatible attributes are specified, either\n                    // `cancel_handle` or `from_py_with`, duplicates and any\n                    // combination of the two are already rejected.\n                    return Ok(Self::CancelHandle(CancelHandleArg {\n                        name: ident,\n                        ty: &cap.ty,\n                    }));\n                }\n\n                Ok(Self::Regular(RegularArg {\n                    name: Cow::Borrowed(ident),\n                    ty: &cap.ty,\n                    from_py_with: from_py_with.map(Box::new),\n                    default_value: None,\n                    option_wrapped_type: utils::option_type_argument(&cap.ty),\n                    #[cfg(feature = \"experimental-inspect\")]\n                    annotation: None,\n                }))\n            }\n        }\n    }\n}\n\nfn handle_argument_error(pat: &syn::Pat) -> syn::Error {\n    let span = pat.span();\n    let msg = match pat {\n        syn::Pat::Wild(_) => \"wildcard argument names are not supported\",\n        syn::Pat::Struct(_)\n        | syn::Pat::Tuple(_)\n        | syn::Pat::TupleStruct(_)\n        | syn::Pat::Slice(_) => \"destructuring in arguments is not supported\",\n        _ => \"unsupported argument\",\n    };\n    syn::Error::new(span, msg)\n}\n\n/// Represents what kind of a function a pyfunction or pymethod is\n#[derive(Clone, Debug)]\npub enum FnType {\n    /// Represents a pymethod annotated with `#[getter]`\n    Getter(SelfType),\n    /// Represents a pymethod annotated with `#[setter]`\n    Setter(SelfType),\n    /// Represents a pymethod annotated with `#[deleter]`\n    Deleter(SelfType),\n    /// Represents a regular pymethod\n    Fn(SelfType),\n    /// Represents a pymethod annotated with `#[classmethod]`, like a `@classmethod`\n    FnClass(Span),\n    /// Represents a pyfunction or a pymethod annotated with `#[staticmethod]`, like a `@staticmethod`\n    FnStatic,\n    /// Represents a pyfunction annotated with `#[pyo3(pass_module)]\n    FnModule(Span),\n    /// Represents a pymethod or associated constant annotated with `#[classattr]`\n    ClassAttribute,\n}\n\nimpl FnType {\n    pub fn skip_first_rust_argument_in_python_signature(&self) -> bool {\n        match self {\n            FnType::Getter(_)\n            | FnType::Setter(_)\n            | FnType::Deleter(_)\n            | FnType::Fn(_)\n            | FnType::FnClass(_)\n            | FnType::FnModule(_) => true,\n            FnType::FnStatic | FnType::ClassAttribute => false,\n        }\n    }\n\n    pub fn signature_attribute_allowed(&self) -> bool {\n        match self {\n            FnType::Fn(_) | FnType::FnStatic | FnType::FnClass(_) | FnType::FnModule(_) => true,\n            // Getter, Setter and Deleter and ClassAttribute all have fixed signatures (either take 0 or 1\n            // arguments) so cannot have a `signature = (...)` attribute.\n            FnType::Getter(_) | FnType::Setter(_) | FnType::Deleter(_) | FnType::ClassAttribute => {\n                false\n            }\n        }\n    }\n\n    pub fn self_arg(\n        &self,\n        cls: Option<&syn::Type>,\n        error_mode: ExtractErrorMode,\n        holders: &mut Holders,\n        ctx: &Ctx,\n    ) -> Option<TokenStream> {\n        let Ctx { pyo3_path, .. } = ctx;\n        match self {\n            FnType::Getter(st) | FnType::Setter(st) | FnType::Deleter(st) | FnType::Fn(st) => {\n                Some(st.receiver(\n                    cls.expect(\"no class given for Fn with a \\\"self\\\" receiver\"),\n                    error_mode,\n                    holders,\n                    ctx,\n                ))\n            }\n            FnType::FnClass(span) => {\n                let py = syn::Ident::new(\"py\", Span::call_site());\n                let slf: Ident = syn::Ident::new(\"_slf\", Span::call_site());\n                let pyo3_path = pyo3_path.to_tokens_spanned(*span);\n                let ret = quote_spanned! { *span =>\n                    #[allow(clippy::useless_conversion, reason = \"#[classmethod] accepts anything which implements `From<BoundRef<PyType>>`\")]\n                    ::std::convert::Into::into(\n                        #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &*(&#slf as *const _ as *const *mut _))\n                            .cast_unchecked::<#pyo3_path::types::PyType>()\n                    )\n                };\n                Some(quote! { unsafe { #ret } })\n            }\n            FnType::FnModule(span) => {\n                let py = syn::Ident::new(\"py\", Span::call_site());\n                let slf: Ident = syn::Ident::new(\"_slf\", Span::call_site());\n                let pyo3_path = pyo3_path.to_tokens_spanned(*span);\n                let ret = quote_spanned! { *span =>\n                    #[allow(clippy::useless_conversion, reason = \"`pass_module` accepts anything which implements `From<BoundRef<PyModule>>`\")]\n                    ::std::convert::Into::into(\n                        #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &*(&#slf as *const _ as *const *mut _))\n                            .cast_unchecked::<#pyo3_path::types::PyModule>()\n                    )\n                };\n                Some(quote! { unsafe { #ret } })\n            }\n            FnType::FnStatic | FnType::ClassAttribute => None,\n        }\n    }\n}\n\n#[derive(Clone, Debug)]\npub enum SelfType {\n    Receiver {\n        mutable: bool,\n        non_null: bool,\n        span: Span,\n    },\n    TryFromBoundRef {\n        span: Span,\n        non_null: bool,\n    },\n}\n\n#[derive(Clone, Copy)]\npub enum ExtractErrorMode {\n    NotImplemented,\n    Raise,\n}\n\nimpl ExtractErrorMode {\n    pub fn handle_error(self, extract: TokenStream, ctx: &Ctx) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        match self {\n            ExtractErrorMode::Raise => quote! { #extract? },\n            ExtractErrorMode::NotImplemented => quote! {\n                match #extract {\n                    ::std::result::Result::Ok(value) => value,\n                    ::std::result::Result::Err(_) => { return #pyo3_path::impl_::callback::convert(py, py.NotImplemented()); },\n                }\n            },\n        }\n    }\n}\n\nimpl SelfType {\n    pub fn receiver(\n        &self,\n        cls: &syn::Type,\n        error_mode: ExtractErrorMode,\n        holders: &mut Holders,\n        ctx: &Ctx,\n    ) -> TokenStream {\n        // Due to use of quote_spanned in this function, need to bind these idents to the\n        // main macro callsite.\n        let py = syn::Ident::new(\"py\", Span::call_site());\n        let slf = syn::Ident::new(\"_slf\", Span::call_site());\n        let Ctx { pyo3_path, .. } = ctx;\n        match self {\n            SelfType::Receiver {\n                span,\n                mutable,\n                non_null,\n            } => {\n                let cast_fn = if *non_null {\n                    quote!(cast_non_null_function_argument)\n                } else {\n                    quote!(cast_function_argument)\n                };\n                let arg =\n                    quote! { unsafe { #pyo3_path::impl_::extract_argument::#cast_fn(#py, #slf) } };\n                let method = if *mutable {\n                    syn::Ident::new(\"extract_pyclass_ref_mut\", *span)\n                } else {\n                    syn::Ident::new(\"extract_pyclass_ref\", *span)\n                };\n                let holder = holders.push_holder(*span);\n                let pyo3_path = pyo3_path.to_tokens_spanned(*span);\n                error_mode.handle_error(\n                    quote_spanned! { *span =>\n                        #pyo3_path::impl_::extract_argument::#method::<#cls>(\n                            #arg,\n                            &mut #holder,\n                        )\n                    },\n                    ctx,\n                )\n            }\n            SelfType::TryFromBoundRef { span, non_null } => {\n                let bound_ref = if *non_null {\n                    quote! { unsafe { #pyo3_path::impl_::pymethods::BoundRef::ref_from_non_null(#py, &#slf) } }\n                } else {\n                    quote! { unsafe { #pyo3_path::impl_::pymethods::BoundRef::ref_from_ptr(#py, &#slf) } }\n                };\n                let pyo3_path = pyo3_path.to_tokens_spanned(*span);\n                error_mode.handle_error(\n                    quote_spanned! { *span =>\n                        #bound_ref.cast::<#cls>()\n                            .map_err(::std::convert::Into::<#pyo3_path::PyErr>::into)\n                            .and_then(\n                                #[allow(clippy::unnecessary_fallible_conversions, reason = \"anything implementing `TryFrom<BoundRef>` is permitted\")]\n                                |bound| ::std::convert::TryFrom::try_from(bound).map_err(::std::convert::Into::into)\n                            )\n\n                    },\n                    ctx\n                )\n            }\n        }\n    }\n}\n\n/// Determines which CPython calling convention a given FnSpec uses.\n#[derive(Clone, Debug, Copy)]\npub enum CallingConvention {\n    Noargs,   // METH_NOARGS\n    Varargs,  // METH_VARARGS | METH_KEYWORDS\n    Fastcall, // METH_FASTCALL | METH_KEYWORDS\n}\n\nimpl CallingConvention {\n    /// Determine default calling convention from an argument signature.\n    ///\n    /// Different other slots (tp_call, tp_new) can have other requirements\n    /// and are set manually (see `parse_fn_type` below).\n    pub fn from_signature(signature: &FunctionSignature<'_>) -> Self {\n        if signature.python_signature.has_no_args() {\n            Self::Noargs\n        } else if signature.python_signature.kwargs.is_none() {\n            Self::Fastcall\n        } else {\n            Self::Varargs\n        }\n    }\n}\n\n#[derive(Clone)]\npub struct FnSpec<'a> {\n    pub tp: FnType,\n    // Rust function name\n    pub name: &'a syn::Ident,\n    // Wrapped python name. This should not have any leading r#.\n    // r# can be removed by syn::ext::IdentExt::unraw()\n    pub python_name: syn::Ident,\n    pub signature: FunctionSignature<'a>,\n    pub text_signature: Option<TextSignatureAttribute>,\n    pub asyncness: Option<syn::Token![async]>,\n    pub unsafety: Option<syn::Token![unsafe]>,\n    pub warnings: Vec<PyFunctionWarning>,\n    pub output: syn::ReturnType,\n}\n\npub fn parse_method_receiver(arg: &syn::FnArg, non_null: bool) -> Result<SelfType> {\n    match arg {\n        syn::FnArg::Receiver(\n            recv @ syn::Receiver {\n                reference: None, ..\n            },\n        ) => {\n            bail_spanned!(recv.span() => RECEIVER_BY_VALUE_ERR);\n        }\n        syn::FnArg::Receiver(recv @ syn::Receiver { mutability, .. }) => Ok(SelfType::Receiver {\n            mutable: mutability.is_some(),\n            span: recv.span(),\n            non_null,\n        }),\n        syn::FnArg::Typed(syn::PatType { ty, .. }) => {\n            if let syn::Type::ImplTrait(_) = &**ty {\n                bail_spanned!(ty.span() => IMPL_TRAIT_ERR);\n            }\n            Ok(SelfType::TryFromBoundRef {\n                span: ty.span(),\n                non_null,\n            })\n        }\n    }\n}\n\nimpl<'a> FnSpec<'a> {\n    /// Parser function signature and function attributes\n    pub fn parse(\n        // Signature is mutable to remove the `Python` argument.\n        sig: &'a mut syn::Signature,\n        meth_attrs: &mut Vec<syn::Attribute>,\n        options: PyFunctionOptions,\n    ) -> Result<FnSpec<'a>> {\n        let PyFunctionOptions {\n            text_signature,\n            name,\n            signature,\n            warnings,\n            ..\n        } = options;\n\n        let mut python_name = name.map(|name| name.value.0);\n\n        let fn_type = Self::parse_fn_type(sig, meth_attrs, &mut python_name)?;\n        ensure_signatures_on_valid_method(&fn_type, signature.as_ref(), text_signature.as_ref())?;\n\n        let name = &sig.ident;\n        let python_name = python_name.as_ref().unwrap_or(name).unraw();\n\n        let arguments: Vec<_> = sig\n            .inputs\n            .iter_mut()\n            .skip(if fn_type.skip_first_rust_argument_in_python_signature() {\n                1\n            } else {\n                0\n            })\n            .map(FnArg::parse)\n            .collect::<Result<_>>()?;\n\n        let signature = if let Some(signature) = signature {\n            FunctionSignature::from_arguments_and_attribute(arguments, signature)?\n        } else {\n            FunctionSignature::from_arguments(arguments)\n        };\n\n        Ok(FnSpec {\n            tp: fn_type,\n            name,\n            python_name,\n            signature,\n            text_signature,\n            asyncness: sig.asyncness,\n            unsafety: sig.unsafety,\n            warnings,\n            output: sig.output.clone(),\n        })\n    }\n\n    pub fn null_terminated_python_name(&self) -> LitCStr {\n        let name = self.python_name.to_string();\n        let name = CString::new(name).unwrap();\n        LitCStr::new(&name, self.python_name.span())\n    }\n\n    fn parse_fn_type(\n        sig: &syn::Signature,\n        meth_attrs: &mut Vec<syn::Attribute>,\n        python_name: &mut Option<syn::Ident>,\n    ) -> Result<FnType> {\n        let mut method_attributes = parse_method_attributes(meth_attrs)?;\n        let receiver_non_null = method_attributes.iter().any(|attr| {\n            matches!(\n                attr,\n                MethodTypeAttribute::Getter(_, _)\n                    | MethodTypeAttribute::Setter(_, _)\n                    | MethodTypeAttribute::Deleter(_, _)\n            )\n        });\n\n        let name = &sig.ident;\n        let parse_receiver = |msg: &'static str| {\n            let first_arg = sig\n                .inputs\n                .first()\n                .ok_or_else(|| err_spanned!(sig.span() => msg))?;\n            parse_method_receiver(first_arg, receiver_non_null)\n        };\n\n        // strip get_ or set_\n        let strip_fn_name = |prefix: &'static str| {\n            name.unraw()\n                .to_string()\n                .strip_prefix(prefix)\n                .map(|stripped| syn::Ident::new(stripped, name.span()))\n        };\n\n        let mut set_name_to_new = || {\n            if let Some(name) = &python_name {\n                bail_spanned!(name.span() => \"`name` not allowed with `#[new]`\");\n            }\n            *python_name = Some(syn::Ident::new(\"__new__\", Span::call_site()));\n            Ok(())\n        };\n\n        let fn_type = match method_attributes.as_mut_slice() {\n            [] => FnType::Fn(parse_receiver(\n                \"static method needs #[staticmethod] attribute\",\n            )?),\n            [MethodTypeAttribute::StaticMethod(_)] => FnType::FnStatic,\n            [MethodTypeAttribute::ClassAttribute(_)] => FnType::ClassAttribute,\n            [MethodTypeAttribute::New(_)] => {\n                set_name_to_new()?;\n                FnType::FnStatic\n            }\n            [MethodTypeAttribute::New(_), MethodTypeAttribute::ClassMethod(span)]\n            | [MethodTypeAttribute::ClassMethod(span), MethodTypeAttribute::New(_)] => {\n                set_name_to_new()?;\n                FnType::FnClass(*span)\n            }\n            [MethodTypeAttribute::ClassMethod(_)] => {\n                // Add a helpful hint if the classmethod doesn't look like a classmethod\n                let span = match sig.inputs.first() {\n                    // Don't actually bother checking the type of the first argument, the compiler\n                    // will error on incorrect type.\n                    Some(syn::FnArg::Typed(first_arg)) => first_arg.ty.span(),\n                    Some(syn::FnArg::Receiver(_)) | None => bail_spanned!(\n                        sig.paren_token.span.join() => \"Expected `&Bound<PyType>` or `Py<PyType>` as the first argument to `#[classmethod]`\"\n                    ),\n                };\n                FnType::FnClass(span)\n            }\n            [MethodTypeAttribute::Getter(_, name)] => {\n                if let Some(name) = name.take() {\n                    ensure_spanned!(\n                        python_name.replace(name).is_none(),\n                        python_name.span() => \"`name` may only be specified once\"\n                    );\n                } else if python_name.is_none() {\n                    // Strip off \"get_\" prefix if needed\n                    *python_name = strip_fn_name(\"get_\");\n                }\n\n                FnType::Getter(parse_receiver(\"expected receiver for `#[getter]`\")?)\n            }\n            [MethodTypeAttribute::Setter(_, name)] => {\n                if let Some(name) = name.take() {\n                    ensure_spanned!(\n                        python_name.replace(name).is_none(),\n                        python_name.span() => \"`name` may only be specified once\"\n                    );\n                } else if python_name.is_none() {\n                    // Strip off \"set_\" prefix if needed\n                    *python_name = strip_fn_name(\"set_\");\n                }\n\n                FnType::Setter(parse_receiver(\"expected receiver for `#[setter]`\")?)\n            }\n            [MethodTypeAttribute::Deleter(_, name)] => {\n                if let Some(name) = name.take() {\n                    ensure_spanned!(\n                        python_name.replace(name).is_none(),\n                        python_name.span() => \"`name` may only be specified once\"\n                    );\n                } else if python_name.is_none() {\n                    // Strip off \"delete_\" prefix if needed\n                    *python_name = strip_fn_name(\"delete_\");\n                }\n\n                FnType::Deleter(parse_receiver(\"expected receiver for `#[deleter]`\")?)\n            }\n            [first, rest @ .., last] => {\n                // Join as many of the spans together as possible\n                let span = rest\n                    .iter()\n                    .fold(first.span(), |s, next| s.join(next.span()).unwrap_or(s));\n                let span = span.join(last.span()).unwrap_or(span);\n                // List all the attributes in the error message\n                let mut msg = format!(\"`{first}` may not be combined with\");\n                let mut is_first = true;\n                for attr in &*rest {\n                    msg.push_str(&format!(\" `{attr}`\"));\n                    if is_first {\n                        is_first = false;\n                    } else {\n                        msg.push(',');\n                    }\n                }\n                if !rest.is_empty() {\n                    msg.push_str(\" and\");\n                }\n                msg.push_str(&format!(\" `{last}`\"));\n                bail_spanned!(span => msg)\n            }\n        };\n        Ok(fn_type)\n    }\n\n    /// Return a C wrapper function for this signature.\n    pub fn get_wrapper_function(\n        &self,\n        ident: &proc_macro2::Ident,\n        cls: Option<&syn::Type>,\n        convention: CallingConvention,\n        ctx: &Ctx,\n    ) -> Result<TokenStream> {\n        let Ctx {\n            pyo3_path,\n            output_span,\n        } = ctx;\n        let mut cancel_handle_iter = self\n            .signature\n            .arguments\n            .iter()\n            .filter(|arg| matches!(arg, FnArg::CancelHandle(..)));\n        let cancel_handle = cancel_handle_iter.next();\n        if let Some(FnArg::CancelHandle(CancelHandleArg { name, .. })) = cancel_handle {\n            ensure_spanned!(self.asyncness.is_some(), name.span() => \"`cancel_handle` attribute can only be used with `async fn`\");\n            if let Some(FnArg::CancelHandle(CancelHandleArg { name, .. })) =\n                cancel_handle_iter.next()\n            {\n                bail_spanned!(name.span() => \"`cancel_handle` may only be specified once\");\n            }\n        }\n\n        let rust_call = |args: Vec<TokenStream>, mut holders: Holders| {\n            let self_arg = self\n                .tp\n                .self_arg(cls, ExtractErrorMode::Raise, &mut holders, ctx);\n            let init_holders = holders.init_holders(ctx);\n\n            // We must assign the output_span to the return value of the call,\n            // but *not* of the call itself otherwise the spans get really weird\n            let ret_ident = Ident::new(\"ret\", *output_span);\n\n            if self.asyncness.is_some() {\n                // For async functions, we need to build up a coroutine object to return from the initial function call.\n                //\n                // Extraction of the call signature (positional & keyword arguments) happens as part of the initial function\n                // call. The Python objects are then moved into the Rust future that will be executed when the coroutine is\n                // awaited.\n                //\n                // The argument extraction from Python objects to Rust values then happens inside the future, this allows\n                // things like extraction to `&MyClass` which needs a holder (for the class guard) to work properly inside\n                // async code.\n                //\n                // It *might* be possible in the future to do the extraction before the coroutine is created, but that would require\n                // changing argument extraction code to first create holders and then read the values from them later.\n                let (throw_callback, init_throw_callback) = if cancel_handle.is_some() {\n                    (\n                        quote! { Some(__throw_callback) },\n                        Some(\n                            quote! { let __cancel_handle = #pyo3_path::coroutine::CancelHandle::new();\n                            let __throw_callback = __cancel_handle.throw_callback(); },\n                        ),\n                    )\n                } else {\n                    (quote! { None }, None)\n                };\n                let python_name = &self.python_name;\n                let qualname_prefix = match cls {\n                    Some(cls) => quote!(Some(<#cls as #pyo3_path::PyClass>::NAME)),\n                    None => quote!(None),\n                };\n                // copy self arg into async block\n                // slf_py will create the owned value to store in the future\n                // slf_ptr recreates the raw pointer temporarily when building the future\n                let (slf_py, slf_ptr) = if self_arg.is_some() {\n                    (\n                        Some(\n                            quote! { let _slf = #pyo3_path::Borrowed::from_ptr(py, _slf).to_owned().unbind(); },\n                        ),\n                        Some(quote! { let _slf = _slf.as_ptr(); }),\n                    )\n                } else {\n                    (None, None)\n                };\n                // copy extracted arguments into async block\n                // output_py will create the owned arguments to store in the future\n                // output_args recreates the borrowed objects temporarily when building the future\n                let (output_py, output_args) = if !matches!(convention, CallingConvention::Noargs)\n                    && !is_forwarded_args(&self.signature)\n                {\n                    (\n                        Some(quote! {\n                            let output = output.map(|o| o.map(Py::from));\n                        }),\n                        Some(quote! {\n                            let output = output.each_ref().map(|o| o.as_ref().map(|obj| obj.bind_borrowed(assume_attached.py())));\n                        }),\n                    )\n                } else {\n                    (None, None)\n                };\n                // if *args / **kwargs are present, treat the `Bound<'_, PyTuple>` / `Option<Bound<'_, PyDict>>` similarly\n                let (varargs_py, varargs_ptr) = if self.signature.python_signature.varargs.is_some()\n                {\n                    (\n                        Some(quote! {\n                            let _args = _args.to_owned().unbind();\n                        }),\n                        Some(quote! {\n                            let _args = _args.bind_borrowed(assume_attached.py());\n                        }),\n                    )\n                } else {\n                    (None, None)\n                };\n                let (kwargs_py, kwargs_ptr) = if self.signature.python_signature.kwargs.is_some() {\n                    (\n                        Some(quote! {\n                            let _kwargs = _kwargs.map(|k| k.to_owned().unbind());\n                        }),\n                        Some(quote! {\n                            let _kwargs = _kwargs.as_ref().map(|k| k.bind_borrowed(assume_attached.py()));\n                        }),\n                    )\n                } else {\n                    (None, None)\n                };\n                let args = self_arg.into_iter().chain(args);\n                let ok_wrap = quotes::ok_wrap(ret_ident.to_token_stream(), ctx);\n                quote! {\n                    {\n                        let coroutine = {\n                            #slf_py\n                            #output_py\n                            #varargs_py\n                            #kwargs_py\n                            #init_throw_callback\n                            #pyo3_path::impl_::coroutine::new_coroutine(\n                                #pyo3_path::intern!(py, stringify!(#python_name)),\n                                #qualname_prefix,\n                                #throw_callback,\n                                async move {\n                                    // SAFETY: attached when future is polled (see `Coroutine::poll`)\n                                    let assume_attached = unsafe { #pyo3_path::impl_::coroutine::AssumeAttachedInCoroutine::new() };\n                                    #init_holders\n                                    let future = {\n                                        let py = assume_attached.py();\n                                        #slf_ptr\n                                        #output_args\n                                        #varargs_ptr\n                                        #kwargs_ptr\n                                        function(#(#args),*)\n                                    };\n                                    let #ret_ident = future.await;\n                                    let #ret_ident = #ok_wrap;\n                                    #pyo3_path::impl_::wrap::converter(&#ret_ident).map_into_pyobject(assume_attached.py(), #ret_ident)\n                                },\n                            )\n                        };\n                        #pyo3_path::Py::new(py, coroutine).map(#pyo3_path::Py::into_ptr)\n                    }\n                }\n            } else {\n                let args = self_arg.into_iter().chain(args);\n                let return_conversion = quotes::map_result_into_ptr(\n                    quotes::ok_wrap(ret_ident.to_token_stream(), ctx),\n                    ctx,\n                );\n                quote! {\n                    {\n                        #init_holders\n                        let #ret_ident = function(#(#args),*);\n                        #return_conversion\n                    }\n                }\n            }\n        };\n\n        let func_name = &self.name;\n        let rust_name = if let Some(cls) = cls {\n            quote!(#cls::#func_name)\n        } else {\n            quote!(#func_name)\n        };\n\n        let warnings = self.warnings.build_py_warning(ctx);\n        let mut holders = Holders::new();\n\n        Ok(match convention {\n            CallingConvention::Noargs => {\n                let args = self\n                    .signature\n                    .arguments\n                    .iter()\n                    .map(|arg| match arg {\n                        FnArg::Py(..) => quote!(py),\n                        FnArg::CancelHandle(..) => quote!(__cancel_handle),\n                        _ => unreachable!(\"`CallingConvention::Noargs` should not contain any arguments (reaching Python) except for `self`, which is handled below.\"),\n                    })\n                    .collect();\n                let call = rust_call(args, holders);\n                quote! {\n                    unsafe fn #ident<'py>(\n                        py: #pyo3_path::Python<'py>,\n                        _slf: *mut #pyo3_path::ffi::PyObject,\n                    ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {\n                        let function = #rust_name; // Shadow the function name to avoid #3017\n                        #warnings\n                        let result = #call;\n                        result\n                    }\n                }\n            }\n            CallingConvention::Fastcall => {\n                let (arg_convert, args) = impl_arg_params(self, cls, true, &mut holders, ctx);\n                let call = rust_call(args, holders);\n\n                quote! {\n                    #pyo3_path::impl_::pymethods::maybe_define_fastcall_function_with_keywords!(\n                        #ident, py, _slf, _args, _nargs, _kwargs, {\n                            let function = #rust_name; // Shadow the function name to avoid #3017\n                            #arg_convert\n                            #warnings\n                            let result = #call;\n                            result\n                        }\n                    );\n                }\n            }\n            CallingConvention::Varargs => {\n                let (arg_convert, args) = impl_arg_params(self, cls, false, &mut holders, ctx);\n                let call = rust_call(args, holders);\n\n                quote! {\n                    unsafe fn #ident<'py>(\n                        py: #pyo3_path::Python<'py>,\n                        _slf: *mut #pyo3_path::ffi::PyObject,\n                        _args: *mut #pyo3_path::ffi::PyObject,\n                        _kwargs: *mut #pyo3_path::ffi::PyObject\n                    ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {\n                        let function = #rust_name; // Shadow the function name to avoid #3017\n                        #arg_convert\n                        #warnings\n                        let result = #call;\n                        result\n                    }\n                }\n            }\n        })\n    }\n\n    /// Return a `PyMethodDef` constructor for this function, matching the selected\n    /// calling convention.\n    pub fn get_methoddef(\n        &self,\n        wrapper: impl ToTokens,\n        doc: Option<&PythonDoc>,\n        convention: CallingConvention,\n        ctx: &Ctx,\n    ) -> Result<TokenStream> {\n        let Ctx { pyo3_path, .. } = ctx;\n        let python_name = self.null_terminated_python_name();\n        let flags = match self.tp {\n            FnType::FnClass(_) => quote! { .flags(#pyo3_path::ffi::METH_CLASS) },\n            FnType::FnStatic => quote! { .flags(#pyo3_path::ffi::METH_STATIC) },\n            _ => quote! {},\n        };\n        let trampoline = match convention {\n            CallingConvention::Noargs => Ident::new(\"noargs\", Span::call_site()),\n            CallingConvention::Fastcall => {\n                Ident::new(\"maybe_fastcall_cfunction_with_keywords\", Span::call_site())\n            }\n            CallingConvention::Varargs => Ident::new(\"cfunction_with_keywords\", Span::call_site()),\n        };\n        let doc = if let Some(doc) = doc {\n            doc.to_cstr_stream(ctx)?\n        } else {\n            c\"\".to_token_stream()\n        };\n        Ok(quote! {\n            #pyo3_path::impl_::pymethods::PyMethodDef::#trampoline(\n                #python_name,\n                #pyo3_path::impl_::trampoline::get_trampoline_function!(#trampoline, #wrapper),\n                #doc,\n            ) #flags\n        })\n    }\n\n    /// Forwards to [utils::get_doc] with the text signature of this spec.\n    pub fn get_doc(&self, attrs: &[syn::Attribute]) -> Option<PythonDoc> {\n        let text_signature = self\n            .text_signature_call_signature()\n            .map(|sig| format!(\"{}{}\", self.python_name, sig));\n        utils::get_doc(attrs, text_signature)\n    }\n\n    /// Creates the parenthesised arguments list for `__text_signature__` snippet based on this spec's signature\n    /// and/or attributes. Prepend the callable name to make a complete `__text_signature__`.\n    pub fn text_signature_call_signature(&self) -> Option<String> {\n        let self_argument = match &self.tp {\n            // Getters / Setters / deleter / ClassAttribute are not callables on the Python side\n            FnType::Getter(_) | FnType::Setter(_) | FnType::Deleter(_) | FnType::ClassAttribute => {\n                return None\n            }\n            FnType::Fn(_) => Some(\"self\"),\n            FnType::FnModule(_) => Some(\"module\"),\n            FnType::FnClass(_) => Some(\"cls\"),\n            FnType::FnStatic => None,\n        };\n\n        match self.text_signature.as_ref().map(|attr| &attr.value) {\n            Some(TextSignatureAttributeValue::Str(s)) => Some(s.value()),\n            None => Some(self.signature.text_signature(self_argument)),\n            Some(TextSignatureAttributeValue::Disabled(_)) => None,\n        }\n    }\n}\n\nenum MethodTypeAttribute {\n    New(Span),\n    ClassMethod(Span),\n    StaticMethod(Span),\n    Getter(Span, Option<Ident>),\n    Setter(Span, Option<Ident>),\n    Deleter(Span, Option<Ident>),\n    ClassAttribute(Span),\n}\n\nimpl MethodTypeAttribute {\n    fn span(&self) -> Span {\n        match self {\n            MethodTypeAttribute::New(span)\n            | MethodTypeAttribute::ClassMethod(span)\n            | MethodTypeAttribute::StaticMethod(span)\n            | MethodTypeAttribute::Getter(span, _)\n            | MethodTypeAttribute::Setter(span, _)\n            | MethodTypeAttribute::Deleter(span, _)\n            | MethodTypeAttribute::ClassAttribute(span) => *span,\n        }\n    }\n\n    /// Attempts to parse a method type attribute.\n    ///\n    /// If the attribute does not match one of the attribute names, returns `Ok(None)`.\n    ///\n    /// Otherwise will either return a parse error or the attribute.\n    fn parse_if_matching_attribute(attr: &syn::Attribute) -> Result<Option<Self>> {\n        fn ensure_no_arguments(meta: &syn::Meta, ident: &str) -> syn::Result<()> {\n            match meta {\n                syn::Meta::Path(_) => Ok(()),\n                syn::Meta::List(l) => bail_spanned!(\n                    l.span() => format!(\n                        \"`#[{ident}]` does not take any arguments\\n= help: did you mean `#[{ident}] #[pyo3({meta})]`?\",\n                        ident = ident,\n                        meta = l.tokens,\n                    )\n                ),\n                syn::Meta::NameValue(nv) => {\n                    bail_spanned!(nv.eq_token.span() => format!(\n                        \"`#[{}]` does not take any arguments\\n= note: this was previously accepted and ignored\",\n                        ident\n                    ))\n                }\n            }\n        }\n\n        fn extract_name(meta: &syn::Meta, ident: &str) -> Result<Option<Ident>> {\n            match meta {\n                syn::Meta::Path(_) => Ok(None),\n                syn::Meta::NameValue(nv) => bail_spanned!(\n                    nv.eq_token.span() => format!(\"expected `#[{}(name)]` to set the name\", ident)\n                ),\n                syn::Meta::List(l) => {\n                    if let Ok(name) = l.parse_args::<syn::Ident>() {\n                        Ok(Some(name))\n                    } else if let Ok(name) = l.parse_args::<syn::LitStr>() {\n                        name.parse().map(Some)\n                    } else {\n                        bail_spanned!(l.tokens.span() => \"expected ident or string literal for property name\");\n                    }\n                }\n            }\n        }\n\n        let meta = &attr.meta;\n        let path = meta.path();\n\n        if path.is_ident(\"new\") {\n            ensure_no_arguments(meta, \"new\")?;\n            Ok(Some(MethodTypeAttribute::New(path.span())))\n        } else if path.is_ident(\"classmethod\") {\n            ensure_no_arguments(meta, \"classmethod\")?;\n            Ok(Some(MethodTypeAttribute::ClassMethod(path.span())))\n        } else if path.is_ident(\"staticmethod\") {\n            ensure_no_arguments(meta, \"staticmethod\")?;\n            Ok(Some(MethodTypeAttribute::StaticMethod(path.span())))\n        } else if path.is_ident(\"classattr\") {\n            ensure_no_arguments(meta, \"classattr\")?;\n            Ok(Some(MethodTypeAttribute::ClassAttribute(path.span())))\n        } else if path.is_ident(\"getter\") {\n            let name = extract_name(meta, \"getter\")?;\n            Ok(Some(MethodTypeAttribute::Getter(path.span(), name)))\n        } else if path.is_ident(\"setter\") {\n            let name = extract_name(meta, \"setter\")?;\n            Ok(Some(MethodTypeAttribute::Setter(path.span(), name)))\n        } else if path.is_ident(\"deleter\") {\n            let name = extract_name(meta, \"deleter\")?;\n            Ok(Some(MethodTypeAttribute::Deleter(path.span(), name)))\n        } else {\n            Ok(None)\n        }\n    }\n}\n\nimpl Display for MethodTypeAttribute {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.write_str(match self {\n            MethodTypeAttribute::New(_) => \"#[new]\",\n            MethodTypeAttribute::ClassMethod(_) => \"#[classmethod]\",\n            MethodTypeAttribute::StaticMethod(_) => \"#[staticmethod]\",\n            MethodTypeAttribute::Getter(_, _) => \"#[getter]\",\n            MethodTypeAttribute::Setter(_, _) => \"#[setter]\",\n            MethodTypeAttribute::Deleter(_, _) => \"#[deleter]\",\n            MethodTypeAttribute::ClassAttribute(_) => \"#[classattr]\",\n        })\n    }\n}\n\nfn parse_method_attributes(attrs: &mut Vec<syn::Attribute>) -> Result<Vec<MethodTypeAttribute>> {\n    let mut new_attrs = Vec::new();\n    let mut found_attrs = Vec::new();\n\n    for attr in attrs.drain(..) {\n        match MethodTypeAttribute::parse_if_matching_attribute(&attr)? {\n            Some(attr) => found_attrs.push(attr),\n            None => new_attrs.push(attr),\n        }\n    }\n\n    *attrs = new_attrs;\n\n    Ok(found_attrs)\n}\n\nconst IMPL_TRAIT_ERR: &str = \"Python functions cannot have `impl Trait` arguments\";\nconst RECEIVER_BY_VALUE_ERR: &str =\n    \"Python objects are shared, so 'self' cannot be moved out of the Python interpreter.\nTry `&self`, `&mut self, `slf: PyClassGuard<'_, Self>` or `slf: PyClassGuardMut<'_, Self>`.\";\n\nfn ensure_signatures_on_valid_method(\n    fn_type: &FnType,\n    signature: Option<&SignatureAttribute>,\n    text_signature: Option<&TextSignatureAttribute>,\n) -> syn::Result<()> {\n    if let Some(signature) = signature {\n        match fn_type {\n            FnType::Getter(_) => {\n                debug_assert!(!fn_type.signature_attribute_allowed());\n                bail_spanned!(signature.kw.span() => \"`signature` not allowed with `getter`\")\n            }\n            FnType::Setter(_) => {\n                debug_assert!(!fn_type.signature_attribute_allowed());\n                bail_spanned!(signature.kw.span() => \"`signature` not allowed with `setter`\")\n            }\n            FnType::Deleter(_) => {\n                debug_assert!(!fn_type.signature_attribute_allowed());\n                bail_spanned!(signature.kw.span() => \"`signature` not allowed with `deleter`\")\n            }\n            FnType::ClassAttribute => {\n                debug_assert!(!fn_type.signature_attribute_allowed());\n                bail_spanned!(signature.kw.span() => \"`signature` not allowed with `classattr`\")\n            }\n            _ => debug_assert!(fn_type.signature_attribute_allowed()),\n        }\n    }\n    if let Some(text_signature) = text_signature {\n        match fn_type {\n            FnType::Getter(_) => {\n                bail_spanned!(text_signature.kw.span() => \"`text_signature` not allowed with `getter`\")\n            }\n            FnType::Setter(_) => {\n                bail_spanned!(text_signature.kw.span() => \"`text_signature` not allowed with `setter`\")\n            }\n            FnType::Deleter(_) => {\n                bail_spanned!(text_signature.kw.span() => \"`text_signature` not allowed with `deleter`\")\n            }\n            FnType::ClassAttribute => {\n                bail_spanned!(text_signature.kw.span() => \"`text_signature` not allowed with `classattr`\")\n            }\n            _ => {}\n        }\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/module.rs",
    "content": "//! Code generation for the function that initializes a python module and adds classes and function.\n\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::introspection::{\n    attribute_introspection_code, introspection_id_const, module_introspection_code,\n};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::py_expr::PyExpr;\nuse crate::{\n    attributes::{\n        self, kw, take_attributes, take_pyo3_options, CrateAttribute, GILUsedAttribute,\n        ModuleAttribute, NameAttribute, SubmoduleAttribute,\n    },\n    combine_errors::CombineErrors,\n    get_doc,\n    pyclass::PyClassPyO3Option,\n    pyfunction::{impl_wrap_pyfunction, PyFunctionOptions},\n    utils::{has_attribute, has_attribute_with_namespace, Ctx, IdentOrStr, PythonDoc},\n};\nuse proc_macro2::{Span, TokenStream};\nuse quote::{quote, ToTokens};\nuse std::ffi::CString;\nuse syn::LitCStr;\nuse syn::{\n    ext::IdentExt,\n    parse::{Parse, ParseStream},\n    parse_quote, parse_quote_spanned,\n    punctuated::Punctuated,\n    spanned::Spanned,\n    token::Comma,\n    Item, Meta, Path, Result,\n};\n\n#[derive(Default)]\npub struct PyModuleOptions {\n    krate: Option<CrateAttribute>,\n    name: Option<NameAttribute>,\n    module: Option<ModuleAttribute>,\n    submodule: Option<kw::submodule>,\n    gil_used: Option<GILUsedAttribute>,\n}\n\nimpl Parse for PyModuleOptions {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        let mut options: PyModuleOptions = Default::default();\n\n        options.add_attributes(\n            Punctuated::<PyModulePyO3Option, syn::Token![,]>::parse_terminated(input)?,\n        )?;\n\n        Ok(options)\n    }\n}\n\nimpl PyModuleOptions {\n    fn take_pyo3_options(&mut self, attrs: &mut Vec<syn::Attribute>) -> Result<()> {\n        self.add_attributes(take_pyo3_options(attrs)?)\n    }\n\n    fn add_attributes(\n        &mut self,\n        attrs: impl IntoIterator<Item = PyModulePyO3Option>,\n    ) -> Result<()> {\n        macro_rules! set_option {\n            ($key:ident $(, $extra:literal)?) => {\n                {\n                    ensure_spanned!(\n                        self.$key.is_none(),\n                        $key.span() => concat!(\"`\", stringify!($key), \"` may only be specified once\" $(, $extra)?)\n                    );\n                    self.$key = Some($key);\n                }\n            };\n        }\n        attrs\n            .into_iter()\n            .map(|attr| {\n                match attr {\n                    PyModulePyO3Option::Crate(krate) => set_option!(krate),\n                    PyModulePyO3Option::Name(name) => set_option!(name),\n                    PyModulePyO3Option::Module(module) => set_option!(module),\n                    PyModulePyO3Option::Submodule(submodule) => set_option!(\n                        submodule,\n                        \" (it is implicitly always specified for nested modules)\"\n                    ),\n                    PyModulePyO3Option::GILUsed(gil_used) => {\n                        set_option!(gil_used)\n                    }\n                }\n\n                Ok(())\n            })\n            .try_combine_syn_errors()?;\n        Ok(())\n    }\n}\n\npub fn pymodule_module_impl(\n    module: &mut syn::ItemMod,\n    mut options: PyModuleOptions,\n) -> Result<TokenStream> {\n    let syn::ItemMod {\n        attrs,\n        vis,\n        unsafety: _,\n        ident,\n        mod_token,\n        content,\n        semi: _,\n    } = module;\n    let items = if let Some((_, items)) = content {\n        items\n    } else {\n        bail_spanned!(mod_token.span() => \"`#[pymodule]` can only be used on inline modules\")\n    };\n    options.take_pyo3_options(attrs)?;\n    let ctx = &Ctx::new(&options.krate, None);\n    let Ctx { pyo3_path, .. } = ctx;\n    let doc = get_doc(attrs, None);\n    let name = options\n        .name\n        .map_or_else(|| ident.unraw(), |name| name.value.0);\n    let full_name = if let Some(module) = &options.module {\n        format!(\"{}.{}\", module.value.value(), name)\n    } else {\n        name.to_string()\n    };\n\n    let mut module_items = Vec::new();\n    let mut module_items_cfg_attrs = Vec::new();\n    #[cfg(feature = \"experimental-inspect\")]\n    let mut introspection_chunks = Vec::new();\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    let introspection_chunks = Vec::<TokenStream>::new();\n\n    fn extract_use_items(\n        source: &syn::UseTree,\n        cfg_attrs: &[syn::Attribute],\n        target_items: &mut Vec<syn::Ident>,\n        target_cfg_attrs: &mut Vec<Vec<syn::Attribute>>,\n    ) -> Result<()> {\n        match source {\n            syn::UseTree::Name(name) => {\n                target_items.push(name.ident.clone());\n                target_cfg_attrs.push(cfg_attrs.to_vec());\n            }\n            syn::UseTree::Path(path) => {\n                extract_use_items(&path.tree, cfg_attrs, target_items, target_cfg_attrs)?\n            }\n            syn::UseTree::Group(group) => {\n                for tree in &group.items {\n                    extract_use_items(tree, cfg_attrs, target_items, target_cfg_attrs)?\n                }\n            }\n            syn::UseTree::Glob(glob) => {\n                bail_spanned!(glob.span() => \"#[pymodule] cannot import glob statements\")\n            }\n            syn::UseTree::Rename(rename) => {\n                target_items.push(rename.rename.clone());\n                target_cfg_attrs.push(cfg_attrs.to_vec());\n            }\n        }\n        Ok(())\n    }\n\n    let mut pymodule_init = None;\n    let mut module_consts = Vec::new();\n    let mut module_consts_cfg_attrs = Vec::new();\n\n    let _: Vec<()> = (*items).iter_mut().map(|item|{\n        match item {\n            Item::Use(item_use) => {\n                let is_pymodule_export =\n                    find_and_remove_attribute(&mut item_use.attrs, \"pymodule_export\");\n                if is_pymodule_export {\n                    let cfg_attrs = get_cfg_attributes(&item_use.attrs);\n                    extract_use_items(\n                        &item_use.tree,\n                        &cfg_attrs,\n                        &mut module_items,\n                        &mut module_items_cfg_attrs,\n                    )?;\n                }\n            }\n            Item::Fn(item_fn) => {\n                ensure_spanned!(\n                    !has_attribute(&item_fn.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n                let is_pymodule_init =\n                    find_and_remove_attribute(&mut item_fn.attrs, \"pymodule_init\");\n                let ident = &item_fn.sig.ident;\n                if is_pymodule_init {\n                    ensure_spanned!(\n                        !has_attribute(&item_fn.attrs, \"pyfunction\"),\n                        item_fn.span() => \"`#[pyfunction]` cannot be used alongside `#[pymodule_init]`\"\n                    );\n                    ensure_spanned!(pymodule_init.is_none(), item_fn.span() => \"only one `#[pymodule_init]` may be specified\");\n                    pymodule_init = Some(quote! { #ident(module)?; });\n                } else if has_attribute(&item_fn.attrs, \"pyfunction\")\n                    || has_attribute_with_namespace(\n                        &item_fn.attrs,\n                        Some(pyo3_path),\n                        &[\"pyfunction\"],\n                    )\n                    || has_attribute_with_namespace(\n                        &item_fn.attrs,\n                        Some(pyo3_path),\n                        &[\"prelude\", \"pyfunction\"],\n                    )\n                {\n                    module_items.push(ident.clone());\n                    module_items_cfg_attrs.push(get_cfg_attributes(&item_fn.attrs));\n                }\n            }\n            Item::Struct(item_struct) => {\n                ensure_spanned!(\n                    !has_attribute(&item_struct.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n                if has_attribute(&item_struct.attrs, \"pyclass\")\n                    || has_attribute_with_namespace(\n                        &item_struct.attrs,\n                        Some(pyo3_path),\n                        &[\"pyclass\"],\n                    )\n                    || has_attribute_with_namespace(\n                        &item_struct.attrs,\n                        Some(pyo3_path),\n                        &[\"prelude\", \"pyclass\"],\n                    )\n                {\n                    module_items.push(item_struct.ident.clone());\n                    module_items_cfg_attrs.push(get_cfg_attributes(&item_struct.attrs));\n                    if !has_pyo3_module_declared::<PyClassPyO3Option>(\n                        &item_struct.attrs,\n                        \"pyclass\",\n                        |option| matches!(option, PyClassPyO3Option::Module(_)),\n                    )? {\n                        set_module_attribute(&mut item_struct.attrs, &full_name);\n                    }\n                }\n            }\n            Item::Enum(item_enum) => {\n                ensure_spanned!(\n                    !has_attribute(&item_enum.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n                if has_attribute(&item_enum.attrs, \"pyclass\")\n                    || has_attribute_with_namespace(&item_enum.attrs, Some(pyo3_path), &[\"pyclass\"])\n                    || has_attribute_with_namespace(\n                        &item_enum.attrs,\n                        Some(pyo3_path),\n                        &[\"prelude\", \"pyclass\"],\n                    )\n                {\n                    module_items.push(item_enum.ident.clone());\n                    module_items_cfg_attrs.push(get_cfg_attributes(&item_enum.attrs));\n                    if !has_pyo3_module_declared::<PyClassPyO3Option>(\n                        &item_enum.attrs,\n                        \"pyclass\",\n                        |option| matches!(option, PyClassPyO3Option::Module(_)),\n                    )? {\n                        set_module_attribute(&mut item_enum.attrs, &full_name);\n                    }\n                }\n            }\n            Item::Mod(item_mod) => {\n                ensure_spanned!(\n                    !has_attribute(&item_mod.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n                if has_attribute(&item_mod.attrs, \"pymodule\")\n                    || has_attribute_with_namespace(&item_mod.attrs, Some(pyo3_path), &[\"pymodule\"])\n                    || has_attribute_with_namespace(\n                        &item_mod.attrs,\n                        Some(pyo3_path),\n                        &[\"prelude\", \"pymodule\"],\n                    )\n                {\n                    module_items.push(item_mod.ident.clone());\n                    module_items_cfg_attrs.push(get_cfg_attributes(&item_mod.attrs));\n                    if !has_pyo3_module_declared::<PyModulePyO3Option>(\n                        &item_mod.attrs,\n                        \"pymodule\",\n                        |option| matches!(option, PyModulePyO3Option::Module(_)),\n                    )? {\n                        set_module_attribute(&mut item_mod.attrs, &full_name);\n                    }\n                    item_mod\n                        .attrs\n                        .push(parse_quote_spanned!(item_mod.mod_token.span()=> #[pyo3(submodule)]));\n                }\n            }\n            Item::ForeignMod(item) => {\n                ensure_spanned!(\n                    !has_attribute(&item.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n            }\n            Item::Trait(item) => {\n                ensure_spanned!(\n                    !has_attribute(&item.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n            }\n            Item::Const(item) => {\n                if !find_and_remove_attribute(&mut item.attrs, \"pymodule_export\") {\n                    return Ok(());\n                }\n                module_consts.push(item.ident.clone());\n                module_consts_cfg_attrs.push(get_cfg_attributes(&item.attrs));\n                #[cfg(feature = \"experimental-inspect\")]\n                {\n                    let cfg_attrs = get_cfg_attributes(&item.attrs);\n                    let chunk = attribute_introspection_code(\n                        pyo3_path,\n                        None,\n                        item.ident.unraw().to_string(),\n                        PyExpr::constant_from_expression(&item.expr),\n                        (*item.ty).clone(),\n                        get_doc(&item.attrs, None).as_ref(),\n                        true,\n                    );\n                    introspection_chunks.push(quote! {\n                        #(#cfg_attrs)*\n                        #chunk\n                    });\n                }\n            }\n            Item::Static(item) => {\n                ensure_spanned!(\n                    !has_attribute(&item.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n            }\n            Item::Macro(item) => {\n                ensure_spanned!(\n                    !has_attribute(&item.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n            }\n            Item::ExternCrate(item) => {\n                ensure_spanned!(\n                    !has_attribute(&item.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n            }\n            Item::Impl(item) => {\n                ensure_spanned!(\n                    !has_attribute(&item.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n            }\n            Item::TraitAlias(item) => {\n                ensure_spanned!(\n                    !has_attribute(&item.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n            }\n            Item::Type(item) => {\n                ensure_spanned!(\n                    !has_attribute(&item.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n            }\n            Item::Union(item) => {\n                ensure_spanned!(\n                    !has_attribute(&item.attrs, \"pymodule_export\"),\n                    item.span() => \"`#[pymodule_export]` may only be used on `use` or `const` statements\"\n                );\n            }\n            _ => (),\n        }\n        Ok(())\n    }).try_combine_syn_errors()?;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    let introspection = module_introspection_code(\n        pyo3_path,\n        &name.to_string(),\n        &module_items,\n        &module_items_cfg_attrs,\n        doc.as_ref(),\n        pymodule_init.is_some(),\n    );\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    let introspection = quote! {};\n    #[cfg(feature = \"experimental-inspect\")]\n    let introspection_id = introspection_id_const();\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    let introspection_id = quote! {};\n\n    let gil_used = options.gil_used.is_some_and(|op| op.value.value);\n\n    let initialization = module_initialization(\n        &full_name,\n        &name,\n        ctx,\n        quote! { __pyo3_pymodule },\n        options.submodule.is_some(),\n        gil_used,\n        doc.as_ref(),\n    )?;\n\n    let module_consts_names = module_consts.iter().map(|i| i.unraw().to_string());\n\n    Ok(quote!(\n        #(#attrs)*\n        #vis #mod_token #ident {\n            #(#items)*\n\n            #initialization\n            #introspection\n            #introspection_id\n            #(#introspection_chunks)*\n\n            fn __pyo3_pymodule(module: &#pyo3_path::Bound<'_, #pyo3_path::types::PyModule>) -> #pyo3_path::PyResult<()> {\n                use #pyo3_path::impl_::pymodule::PyAddToModule;\n                #(\n                    #(#module_items_cfg_attrs)*\n                    #module_items::_PYO3_DEF.add_to_module(module)?;\n                )*\n\n                #(\n                    #(#module_consts_cfg_attrs)*\n                    #pyo3_path::types::PyModuleMethods::add(module, #module_consts_names, #module_consts)?;\n                )*\n\n                #pymodule_init\n                ::std::result::Result::Ok(())\n            }\n        }\n    ))\n}\n\n/// Generates the function that is called by the python interpreter to initialize the native\n/// module\npub fn pymodule_function_impl(\n    function: &mut syn::ItemFn,\n    mut options: PyModuleOptions,\n) -> Result<TokenStream> {\n    options.take_pyo3_options(&mut function.attrs)?;\n    process_functions_in_module(&options, function)?;\n    let ctx = &Ctx::new(&options.krate, None);\n    let Ctx { pyo3_path, .. } = ctx;\n    let ident = &function.sig.ident;\n    let name = options\n        .name\n        .map_or_else(|| ident.unraw(), |name| name.value.0);\n    let vis = &function.vis;\n    let doc = get_doc(&function.attrs, None);\n\n    let gil_used = options.gil_used.is_some_and(|op| op.value.value);\n\n    let initialization = module_initialization(\n        &name.to_string(),\n        &name,\n        ctx,\n        quote! { ModuleExec::__pyo3_module_exec },\n        false,\n        gil_used,\n        doc.as_ref(),\n    )?;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    let introspection = module_introspection_code(\n        pyo3_path,\n        &name.unraw().to_string(),\n        &[],\n        &[],\n        doc.as_ref(),\n        true,\n    );\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    let introspection = quote! {};\n    #[cfg(feature = \"experimental-inspect\")]\n    let introspection_id = introspection_id_const();\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    let introspection_id = quote! {};\n\n    // Module function called with optional Python<'_> marker as first arg, followed by the module.\n    let mut module_args = Vec::new();\n    if function.sig.inputs.len() == 2 {\n        module_args.push(quote!(module.py()));\n    }\n    module_args\n        .push(quote!(::std::convert::Into::into(#pyo3_path::impl_::pymethods::BoundRef(module))));\n\n    Ok(quote! {\n        #[doc(hidden)]\n        #vis mod #ident {\n            #initialization\n            #introspection\n            #introspection_id\n        }\n\n        // Generate the definition inside an anonymous function in the same scope as the original function -\n        // this avoids complications around the fact that the generated module has a different scope\n        // (and `super` doesn't always refer to the outer scope, e.g. if the `#[pymodule] is\n        // inside a function body)\n        #[allow(unknown_lints, non_local_definitions)]\n        impl #ident::ModuleExec {\n            fn __pyo3_module_exec(module: &#pyo3_path::Bound<'_, #pyo3_path::types::PyModule>) -> #pyo3_path::PyResult<()> {\n                #ident(#(#module_args),*)\n            }\n        }\n    })\n}\n\nfn module_initialization(\n    full_name: &str,\n    name: &syn::Ident,\n    ctx: &Ctx,\n    module_exec: TokenStream,\n    is_submodule: bool,\n    gil_used: bool,\n    doc: Option<&PythonDoc>,\n) -> Result<TokenStream> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let pyinit_symbol = format!(\"PyInit_{name}\");\n    let pymodexport_symbol = format!(\"PyModExport_{name}\");\n    let pyo3_name = LitCStr::new(&CString::new(full_name).unwrap(), Span::call_site());\n    let doc = if let Some(doc) = doc {\n        doc.to_cstr_stream(ctx)?\n    } else {\n        c\"\".into_token_stream()\n    };\n\n    let mut result = quote! {\n        #[doc(hidden)]\n        pub const __PYO3_NAME: &'static ::std::ffi::CStr = #pyo3_name;\n\n        // This structure exists for `fn` modules declared within `fn` bodies, where due to the hidden\n        // module (used for importing) the `fn` to initialize the module cannot be seen from the #module_def\n        // declaration just below.\n        #[doc(hidden)]\n        pub(super) struct ModuleExec;\n\n        #[doc(hidden)]\n        pub static _PYO3_DEF: #pyo3_path::impl_::pymodule::ModuleDef = {\n            use #pyo3_path::impl_::pymodule as impl_;\n\n            unsafe extern \"C\" fn __pyo3_module_exec(module: *mut #pyo3_path::ffi::PyObject) -> ::std::os::raw::c_int {\n                #pyo3_path::impl_::trampoline::module_exec(module, #module_exec)\n            }\n\n            // The full slots, used for the PyModExport initializaiton\n            static SLOTS: impl_::PyModuleSlots = impl_::PyModuleSlotsBuilder::new()\n                .with_mod_exec(__pyo3_module_exec)\n                .with_abi_info()\n                .with_gil_used(#gil_used)\n                .with_name(__PYO3_NAME)\n                .with_doc(#doc)\n                .build();\n\n            // Since the macros need to be written agnostic to the Python version\n            // we need to explicitly pass the name and docstring for PyModuleDef\n            // initializaiton.\n            impl_::ModuleDef::new(__PYO3_NAME, #doc, &SLOTS)\n        };\n    };\n    if !is_submodule {\n        result.extend(quote! {\n            /// This autogenerated function is called by the python interpreter when importing\n            /// the module on Python 3.14 and older.\n            #[doc(hidden)]\n            #[export_name = #pyinit_symbol]\n            pub unsafe extern \"C\" fn __pyo3_init() -> *mut #pyo3_path::ffi::PyObject {\n                _PYO3_DEF.init_multi_phase()\n            }\n\n            /// This autogenerated function is called by the python interpreter when importing\n            /// the module on Python 3.15 and newer.\n            #[doc(hidden)]\n            #[export_name = #pymodexport_symbol]\n            pub unsafe extern \"C\" fn __pyo3_export() -> *mut #pyo3_path::ffi::PyModuleDef_Slot {\n                _PYO3_DEF.get_slots()\n            }\n        });\n    }\n    Ok(result)\n}\n\n/// Finds and takes care of the #[pyfn(...)] in `#[pymodule]`\nfn process_functions_in_module(options: &PyModuleOptions, func: &mut syn::ItemFn) -> Result<()> {\n    let ctx = &Ctx::new(&options.krate, None);\n    let Ctx { pyo3_path, .. } = ctx;\n    let mut stmts: Vec<syn::Stmt> = Vec::new();\n\n    for mut stmt in func.block.stmts.drain(..) {\n        if let syn::Stmt::Item(Item::Fn(func)) = &mut stmt {\n            if let Some((pyfn_span, pyfn_args)) = get_pyfn_attr(&mut func.attrs)? {\n                let module_name = pyfn_args.modname;\n                let wrapped_function = impl_wrap_pyfunction(func, pyfn_args.options)?;\n                let name = &func.sig.ident;\n                let statements: Vec<syn::Stmt> = syn::parse_quote_spanned! {\n                    pyfn_span =>\n                    #wrapped_function\n                    {\n                        use #pyo3_path::types::PyModuleMethods;\n                        #module_name.add_function(#pyo3_path::wrap_pyfunction!(#name, #module_name.as_borrowed())?)?;\n                        #[deprecated(note = \"`pyfn` will be removed in a future PyO3 version, use declarative `#[pymodule]` with `mod` instead\")]\n                        #[allow(dead_code)]\n                        const PYFN_ATTRIBUTE: () = ();\n                        const _: () = PYFN_ATTRIBUTE;\n                    }\n                };\n                stmts.extend(statements);\n            }\n        };\n        stmts.push(stmt);\n    }\n\n    func.block.stmts = stmts;\n    Ok(())\n}\n\npub struct PyFnArgs {\n    modname: Path,\n    options: PyFunctionOptions,\n}\n\nimpl Parse for PyFnArgs {\n    fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {\n        let modname = input.parse().map_err(\n            |e| err_spanned!(e.span() => \"expected module as first argument to #[pyfn()]\"),\n        )?;\n\n        if input.is_empty() {\n            return Ok(Self {\n                modname,\n                options: Default::default(),\n            });\n        }\n\n        let _: Comma = input.parse()?;\n\n        Ok(Self {\n            modname,\n            options: input.parse()?,\n        })\n    }\n}\n\n/// Extracts the data from the #[pyfn(...)] attribute of a function\nfn get_pyfn_attr(attrs: &mut Vec<syn::Attribute>) -> syn::Result<Option<(Span, PyFnArgs)>> {\n    let mut pyfn_args: Option<(Span, PyFnArgs)> = None;\n\n    take_attributes(attrs, |attr| {\n        if attr.path().is_ident(\"pyfn\") {\n            ensure_spanned!(\n                pyfn_args.is_none(),\n                attr.span() => \"`#[pyfn] may only be specified once\"\n            );\n            pyfn_args = Some((attr.path().span(), attr.parse_args()?));\n            Ok(true)\n        } else {\n            Ok(false)\n        }\n    })?;\n\n    if let Some((_, pyfn_args)) = &mut pyfn_args {\n        pyfn_args\n            .options\n            .add_attributes(take_pyo3_options(attrs)?)?;\n    }\n\n    Ok(pyfn_args)\n}\n\nfn get_cfg_attributes(attrs: &[syn::Attribute]) -> Vec<syn::Attribute> {\n    attrs\n        .iter()\n        .filter(|attr| attr.path().is_ident(\"cfg\"))\n        .cloned()\n        .collect()\n}\n\nfn find_and_remove_attribute(attrs: &mut Vec<syn::Attribute>, ident: &str) -> bool {\n    let mut found = false;\n    attrs.retain(|attr| {\n        if attr.path().is_ident(ident) {\n            found = true;\n            false\n        } else {\n            true\n        }\n    });\n    found\n}\n\nimpl PartialEq<syn::Ident> for IdentOrStr<'_> {\n    fn eq(&self, other: &syn::Ident) -> bool {\n        match self {\n            IdentOrStr::Str(s) => other == s,\n            IdentOrStr::Ident(i) => other == i,\n        }\n    }\n}\n\nfn set_module_attribute(attrs: &mut Vec<syn::Attribute>, module_name: &str) {\n    attrs.push(parse_quote!(#[pyo3(module = #module_name)]));\n}\n\nfn has_pyo3_module_declared<T: Parse>(\n    attrs: &[syn::Attribute],\n    root_attribute_name: &str,\n    is_module_option: impl Fn(&T) -> bool + Copy,\n) -> Result<bool> {\n    for attr in attrs {\n        if (attr.path().is_ident(\"pyo3\") || attr.path().is_ident(root_attribute_name))\n            && matches!(attr.meta, Meta::List(_))\n        {\n            for option in &attr.parse_args_with(Punctuated::<T, Comma>::parse_terminated)? {\n                if is_module_option(option) {\n                    return Ok(true);\n                }\n            }\n        }\n    }\n    Ok(false)\n}\n\nenum PyModulePyO3Option {\n    Submodule(SubmoduleAttribute),\n    Crate(CrateAttribute),\n    Name(NameAttribute),\n    Module(ModuleAttribute),\n    GILUsed(GILUsedAttribute),\n}\n\nimpl Parse for PyModulePyO3Option {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let lookahead = input.lookahead1();\n        if lookahead.peek(attributes::kw::name) {\n            input.parse().map(PyModulePyO3Option::Name)\n        } else if lookahead.peek(syn::Token![crate]) {\n            input.parse().map(PyModulePyO3Option::Crate)\n        } else if lookahead.peek(attributes::kw::module) {\n            input.parse().map(PyModulePyO3Option::Module)\n        } else if lookahead.peek(attributes::kw::submodule) {\n            input.parse().map(PyModulePyO3Option::Submodule)\n        } else if lookahead.peek(attributes::kw::gil_used) {\n            input.parse().map(PyModulePyO3Option::GILUsed)\n        } else {\n            Err(lookahead.error())\n        }\n    }\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/params.rs",
    "content": "use crate::utils::Ctx;\nuse crate::{\n    attributes::FromPyWithAttribute,\n    method::{FnArg, FnSpec, RegularArg},\n    pyfunction::FunctionSignature,\n    quotes::some_wrap,\n};\nuse proc_macro2::{Span, TokenStream};\nuse quote::{format_ident, quote, quote_spanned};\nuse syn::spanned::Spanned;\n\npub struct Holders {\n    holders: Vec<syn::Ident>,\n}\n\nimpl Holders {\n    pub fn new() -> Self {\n        Holders {\n            holders: Vec::new(),\n        }\n    }\n\n    pub fn push_holder(&mut self, span: Span) -> syn::Ident {\n        let holder = syn::Ident::new(&format!(\"holder_{}\", self.holders.len()), span);\n        self.holders.push(holder.clone());\n        holder\n    }\n\n    pub fn init_holders(&self, ctx: &Ctx) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        let holders = &self.holders;\n        quote! {\n            #[allow(clippy::let_unit_value, reason = \"many holders are just `()`\")]\n            #(let mut #holders = #pyo3_path::impl_::extract_argument::FunctionArgumentHolder::INIT;)*\n        }\n    }\n}\n\n/// Return true if the argument list is simply (*args, **kwds).\npub fn is_forwarded_args(signature: &FunctionSignature<'_>) -> bool {\n    matches!(\n        signature.arguments.as_slice(),\n        [FnArg::VarArgs(..), FnArg::KwArgs(..),]\n    )\n}\n\npub fn impl_arg_params(\n    spec: &FnSpec<'_>,\n    self_: Option<&syn::Type>,\n    fastcall: bool,\n    holders: &mut Holders,\n    ctx: &Ctx,\n) -> (TokenStream, Vec<TokenStream>) {\n    let args_array = syn::Ident::new(\"output\", Span::call_site());\n    let Ctx { pyo3_path, .. } = ctx;\n\n    let from_py_with = spec\n        .signature\n        .arguments\n        .iter()\n        .enumerate()\n        .filter_map(|(i, arg)| {\n            let from_py_with = &arg.from_py_with()?.value;\n            let from_py_with_holder = format_ident!(\"from_py_with_{}\", i);\n            Some(quote_spanned! { from_py_with.span() =>\n                let #from_py_with_holder = #from_py_with;\n            })\n        })\n        .collect::<TokenStream>();\n\n    if !fastcall && is_forwarded_args(&spec.signature) {\n        // In the varargs convention, we can just pass though if the signature\n        // is (*args, **kwds).\n        let arg_convert = spec\n            .signature\n            .arguments\n            .iter()\n            .enumerate()\n            .map(|(i, arg)| impl_arg_param(arg, i, &mut 0, holders, ctx))\n            .collect();\n        return (\n            quote! {\n                let _args = unsafe { #pyo3_path::impl_::extract_argument::cast_function_argument(py, _args) };\n                let _kwargs = unsafe { #pyo3_path::impl_::extract_argument::cast_optional_function_argument(py, _kwargs) };\n                #from_py_with\n            },\n            arg_convert,\n        );\n    };\n\n    let positional_parameter_names = &spec.signature.python_signature.positional_parameters;\n    let positional_only_parameters = &spec.signature.python_signature.positional_only_parameters;\n    let required_positional_parameters = spec\n        .signature\n        .python_signature\n        .required_positional_parameters();\n    let keyword_only_parameters = spec\n        .signature\n        .python_signature\n        .keyword_only_parameters\n        .iter()\n        .map(|(name, default_value)| {\n            let required = default_value.is_none();\n            quote! {\n                #pyo3_path::impl_::extract_argument::KeywordOnlyParameterDescription {\n                    name: #name,\n                    required: #required,\n                }\n            }\n        });\n\n    let num_params = positional_parameter_names.len() + keyword_only_parameters.len();\n\n    let mut option_pos = 0usize;\n    let param_conversion = spec\n        .signature\n        .arguments\n        .iter()\n        .enumerate()\n        .map(|(i, arg)| impl_arg_param(arg, i, &mut option_pos, holders, ctx))\n        .collect();\n\n    let args_handler = if spec.signature.python_signature.varargs.is_some() {\n        quote! { #pyo3_path::impl_::extract_argument::TupleVarargs }\n    } else {\n        quote! { #pyo3_path::impl_::extract_argument::NoVarargs }\n    };\n    let kwargs_handler = if spec.signature.python_signature.kwargs.is_some() {\n        quote! { #pyo3_path::impl_::extract_argument::DictVarkeywords }\n    } else {\n        quote! { #pyo3_path::impl_::extract_argument::NoVarkeywords }\n    };\n\n    let cls_name = if let Some(cls) = self_ {\n        quote! { ::std::option::Option::Some(<#cls as #pyo3_path::PyClass>::NAME) }\n    } else {\n        quote! { ::std::option::Option::None }\n    };\n    let python_name = &spec.python_name;\n\n    let extract_expression = if fastcall {\n        quote! {\n            #pyo3_path::impl_::pymethods::maybe_extract_arguments_fastcall!(\n                DESCRIPTION,\n                py,\n                _args,\n                _nargs,\n                _kwargs,\n                #args_array,\n                #args_handler,\n                #kwargs_handler\n            )?\n        }\n    } else {\n        quote! {\n            DESCRIPTION.extract_arguments_tuple_dict::<#args_handler, #kwargs_handler>(\n                py,\n                _args,\n                _kwargs,\n                &mut #args_array\n            )?\n        }\n    };\n\n    // create array of arguments, and then parse\n    (\n        quote! {\n                const DESCRIPTION: #pyo3_path::impl_::extract_argument::FunctionDescription = #pyo3_path::impl_::extract_argument::FunctionDescription {\n                    cls_name: #cls_name,\n                    func_name: stringify!(#python_name),\n                    positional_parameter_names: &[#(#positional_parameter_names),*],\n                    positional_only_parameters: #positional_only_parameters,\n                    required_positional_parameters: #required_positional_parameters,\n                    keyword_only_parameters: &[#(#keyword_only_parameters),*],\n                };\n                let mut #args_array = [::std::option::Option::None; #num_params];\n                let (_args, _kwargs) = #extract_expression;\n                #from_py_with\n        },\n        param_conversion,\n    )\n}\n\nfn impl_arg_param(\n    arg: &FnArg<'_>,\n    pos: usize,\n    option_pos: &mut usize,\n    holders: &mut Holders,\n    ctx: &Ctx,\n) -> TokenStream {\n    let Ctx { pyo3_path, .. } = ctx;\n    let args_array = syn::Ident::new(\"output\", Span::call_site());\n\n    match arg {\n        FnArg::Regular(arg) => {\n            let from_py_with = format_ident!(\"from_py_with_{}\", pos);\n            let arg_value = quote!(#args_array[#option_pos]);\n            *option_pos += 1;\n            impl_regular_arg_param(arg, from_py_with, arg_value, holders, ctx)\n        }\n        FnArg::VarArgs(arg) => {\n            let span = Span::call_site().located_at(arg.ty.span());\n            let holder = holders.push_holder(span);\n            let name_str = arg.name.to_string();\n            quote_spanned! { span =>\n                #pyo3_path::impl_::extract_argument::extract_argument(\n                    _args.as_any().as_borrowed(),\n                    &mut #holder,\n                    #name_str\n                )?\n            }\n        }\n        FnArg::KwArgs(arg) => {\n            let span = Span::call_site().located_at(arg.ty.span());\n            let holder = holders.push_holder(span);\n            let name_str = arg.name.to_string();\n            quote_spanned! { span =>\n                #pyo3_path::impl_::extract_argument::extract_argument_with_default(\n                    _kwargs.as_ref().map(|d| d.as_any().as_borrowed()),\n                    &mut #holder,\n                    #name_str,\n                    || ::std::option::Option::None\n                )?\n            }\n        }\n        FnArg::Py(..) => quote! { py },\n        FnArg::CancelHandle(..) => quote! { __cancel_handle },\n    }\n}\n\n/// Re option_pos: The option slice doesn't contain the py: Python argument, so the argument\n/// index and the index in option diverge when using py: Python\npub(crate) fn impl_regular_arg_param(\n    arg: &RegularArg<'_>,\n    from_py_with: syn::Ident,\n    arg_value: TokenStream, // expected type: Option<&'a Bound<'py, PyAny>>\n    holders: &mut Holders,\n    ctx: &Ctx,\n) -> TokenStream {\n    let Ctx { pyo3_path, .. } = ctx;\n    let pyo3_path = pyo3_path.to_tokens_spanned(arg.ty.span());\n\n    // Use this macro inside this function, to ensure that all code generated here is associated\n    // with the function argument\n    let use_probe = quote! {\n        #[allow(unused_imports, reason = \"`Probe` trait used on negative case only\")]\n        use #pyo3_path::impl_::pyclass::Probe as _;\n    };\n    macro_rules! quote_arg_span {\n        ($($tokens:tt)*) => { quote_spanned!(arg.ty.span() => { #use_probe $($tokens)* }) }\n    }\n\n    let name_str = arg.name.to_string();\n    let mut default = arg.default_value.as_ref().map(|expr| quote!(#expr));\n\n    // Option<T> arguments have special treatment: the default should be specified _without_ the\n    // Some() wrapper. Maybe this should be changed in future?!\n    if arg.option_wrapped_type.is_some() {\n        default = default.map(|tokens| some_wrap(tokens, ctx));\n    }\n\n    if let Some(FromPyWithAttribute { kw, .. }) = &arg.from_py_with.as_deref() {\n        let extractor = quote_spanned! { kw.span =>\n            { let from_py_with: fn(_) -> _ = #from_py_with; from_py_with }\n        };\n        if let Some(default) = default {\n            quote_arg_span! {\n                #pyo3_path::impl_::extract_argument::from_py_with_with_default(\n                    #arg_value.as_deref(),\n                    #name_str,\n                    #extractor,\n                    #[allow(clippy::redundant_closure, reason = \"wrapping user-provided default expression\")]\n                    {\n                        || #default\n                    }\n                )?\n            }\n        } else {\n            let unwrap = quote! {unsafe { #pyo3_path::impl_::extract_argument::unwrap_required_argument_bound(#arg_value.as_deref()) }};\n            quote_arg_span! {\n                #pyo3_path::impl_::extract_argument::from_py_with(\n                    #unwrap,\n                    #name_str,\n                    #extractor,\n                )?\n            }\n        }\n    } else if let Some(default) = default {\n        let holder = holders.push_holder(arg.name.span());\n        quote_arg_span! {\n            #pyo3_path::impl_::extract_argument::extract_argument_with_default(\n                #arg_value,\n                &mut #holder,\n                #name_str,\n                #[allow(clippy::redundant_closure, reason = \"wrapping user-provided default expression\")]\n                {\n                    || #default\n                }\n            )?\n        }\n    } else {\n        let holder = holders.push_holder(arg.name.span());\n        let unwrap = quote! {unsafe { #pyo3_path::impl_::extract_argument::unwrap_required_argument(#arg_value) }};\n        quote_arg_span! {\n            #pyo3_path::impl_::extract_argument::extract_argument(\n                #unwrap,\n                &mut #holder,\n                #name_str\n            )?\n        }\n    }\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/py_expr.rs",
    "content": "//! Define a data structure for Python type hints, mixing static data from macros and call to Pyo3 constants.\n\nuse crate::utils::PyO3CratePath;\nuse proc_macro2::TokenStream;\nuse quote::quote;\nuse std::borrow::Cow;\nuse syn::visit_mut::{visit_type_mut, VisitMut};\nuse syn::{Expr, ExprLit, ExprPath, Lifetime, Lit, Type};\n\n/// A Python expression\n///\n/// Please do not construct directly but use the constructor methods that normalize the expression\n#[derive(Clone, Debug, PartialEq, Eq)]\npub enum PyExpr {\n    /// The Python type hint of a FromPyObject implementation\n    FromPyObjectType(Type),\n    /// The Python type hint of a IntoPyObject implementation\n    IntoPyObjectType(Type),\n    /// The Python type matching the given Rust type given as a function argument\n    ArgumentType(Type),\n    /// The Python type matching the given Rust type given as a function returned value\n    ReturnType(Type),\n    /// The Python type matching the given Rust type\n    Type(Type),\n    /// A name\n    Name { id: Cow<'static, str> },\n    /// An attribute `value.attr`\n    Attribute {\n        value: Box<Self>,\n        attr: Cow<'static, str>,\n    },\n    /// A binary operator\n    BinOp {\n        left: Box<Self>,\n        op: PyOperator,\n        right: Box<Self>,\n    },\n    /// A tuple\n    Tuple { elts: Vec<Self> },\n    /// A subscript `value[slice]`\n    Subscript { value: Box<Self>, slice: Box<Self> },\n    /// A constant\n    Constant(PyConstant),\n}\n\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub enum PyOperator {\n    /// `|` operator\n    BitOr,\n}\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub enum PyConstant {\n    /// None\n    None,\n    /// The `True` and `False` booleans\n    Bool(bool),\n    /// `int` value written in base 10 ([+-]?[0-9]+)\n    Int(String),\n    /// `float` value written in base-10 ([+-]?[0-9]*(.[0-9]*)*([eE])[0-9]*), not including Inf and NaN\n    Float(String),\n    /// `str` value unescaped and without quotes\n    Str(String),\n    /// `...`\n    Ellipsis,\n}\n\nimpl PyExpr {\n    /// Build from a builtins name like `None`\n    pub fn builtin(name: impl Into<Cow<'static, str>>) -> Self {\n        Self::Name { id: name.into() }\n    }\n\n    /// Build from a module and a name like `collections.abc` and `Sequence`\n    pub fn module_attr(\n        module: impl Into<Cow<'static, str>>,\n        name: impl Into<Cow<'static, str>>,\n    ) -> Self {\n        Self::attribute(Self::Name { id: module.into() }, name)\n    }\n\n    /// The type hint of a `FromPyObject` implementation as a function argument\n    ///\n    /// If self_type is set, self_type will replace Self in the given type\n    pub fn from_from_py_object(t: Type, self_type: Option<&Type>) -> Self {\n        Self::FromPyObjectType(clean_type(t, self_type))\n    }\n\n    /// The type hint of a `IntoPyObject` implementation as a function argument\n    ///\n    /// If self_type is set, self_type will replace Self in the given type\n    pub fn from_into_py_object(t: Type, self_type: Option<&Type>) -> Self {\n        Self::IntoPyObjectType(clean_type(t, self_type))\n    }\n\n    /// The type hint of the Rust type used as a function argument\n    ///\n    /// If self_type is set, self_type will replace Self in the given type\n    pub fn from_argument_type(t: Type, self_type: Option<&Type>) -> Self {\n        Self::ArgumentType(clean_type(t, self_type))\n    }\n\n    /// The type hint of the Rust type used as a function output type\n    ///\n    /// If self_type is set, self_type will replace Self in the given type\n    pub fn from_return_type(t: Type, self_type: Option<&Type>) -> Self {\n        Self::ReturnType(clean_type(t, self_type))\n    }\n\n    /// The type hint of the Rust type `PyTypeCheck` trait.\n    ///\n    /// If self_type is set, self_type will replace Self in the given type\n    pub fn from_type(t: Type, self_type: Option<&Type>) -> Self {\n        Self::Type(clean_type(t, self_type))\n    }\n\n    /// An attribute of a given value: `value.attr`\n    pub fn attribute(value: Self, attr: impl Into<Cow<'static, str>>) -> Self {\n        Self::Attribute {\n            value: Box::new(value),\n            attr: attr.into(),\n        }\n    }\n\n    /// Build the union of the different element\n    pub fn union(left: Self, right: Self) -> Self {\n        Self::BinOp {\n            left: Box::new(left),\n            op: PyOperator::BitOr,\n            right: Box::new(right),\n        }\n    }\n\n    /// Build the subscripted type value[slice]\n    pub fn subscript(value: Self, slice: Self) -> Self {\n        Self::Subscript {\n            value: Box::new(value),\n            slice: Box::new(slice),\n        }\n    }\n\n    /// Build a tuple\n    pub fn tuple(elts: impl IntoIterator<Item = Self>) -> Self {\n        Self::Tuple {\n            elts: elts.into_iter().collect(),\n        }\n    }\n\n    pub fn constant_from_expression(expr: &Expr) -> Self {\n        Self::Constant(match expr {\n            Expr::Lit(ExprLit { lit, .. }) => match lit {\n                Lit::Str(s) => PyConstant::Str(s.value()),\n                Lit::Char(c) => PyConstant::Str(c.value().into()),\n                Lit::Int(i) => PyConstant::Int(i.base10_digits().into()),\n                Lit::Float(f) => PyConstant::Float(f.base10_digits().into()),\n                Lit::Bool(b) => PyConstant::Bool(b.value()),\n                _ => PyConstant::Ellipsis, // TODO: implement ByteStr and CStr\n            },\n            Expr::Path(ExprPath { qself, path, .. })\n                if qself.is_none() && path.is_ident(\"None\") =>\n            {\n                PyConstant::None\n            }\n            _ => PyConstant::Ellipsis,\n        })\n    }\n\n    pub fn str_constant(value: impl Into<String>) -> Self {\n        Self::Constant(PyConstant::Str(value.into()))\n    }\n\n    /// `...`\n    pub fn ellipsis() -> Self {\n        Self::Constant(PyConstant::Ellipsis)\n    }\n\n    pub fn to_introspection_token_stream(&self, pyo3_crate_path: &PyO3CratePath) -> TokenStream {\n        match self {\n            Self::FromPyObjectType(t) => {\n                quote! { <#t as #pyo3_crate_path::FromPyObject<'_, '_>>::INPUT_TYPE }\n            }\n            Self::IntoPyObjectType(t) => {\n                quote! { <#t as #pyo3_crate_path::IntoPyObject<'_>>::OUTPUT_TYPE }\n            }\n            Self::ArgumentType(t) => {\n                quote! {\n                    <#t as #pyo3_crate_path::impl_::extract_argument::PyFunctionArgument<\n                        {\n                            #[allow(unused_imports, reason = \"`Probe` trait used on negative case only\")]\n                            use #pyo3_crate_path::impl_::pyclass::Probe as _;\n                            #pyo3_crate_path::impl_::pyclass::IsFromPyObject::<#t>::VALUE\n                        }\n                    >>::INPUT_TYPE\n                }\n            }\n            Self::ReturnType(t) => {\n                quote! {{\n                    #[allow(unused_imports)]\n                    use #pyo3_crate_path::impl_::pyclass::Probe as _;\n                    const TYPE: #pyo3_crate_path::inspect::PyStaticExpr = if #pyo3_crate_path::impl_::pyclass::IsReturningEmptyTuple::<#t>::VALUE {\n                        <#pyo3_crate_path::types::PyNone as #pyo3_crate_path::type_object::PyTypeInfo>::TYPE_HINT\n                    } else {\n                        <#t as #pyo3_crate_path::impl_::introspection::PyReturnType>::OUTPUT_TYPE\n                    };\n                    TYPE\n                }}\n            }\n            Self::Type(t) => {\n                quote! { <#t as #pyo3_crate_path::type_object::PyTypeCheck>::TYPE_HINT }\n            }\n            Self::Name { id } => {\n                quote! { #pyo3_crate_path::inspect::PyStaticExpr::Name { id: #id } }\n            }\n            Self::Attribute { value, attr } => {\n                let value = value.to_introspection_token_stream(pyo3_crate_path);\n                quote! { #pyo3_crate_path::inspect::PyStaticExpr::Attribute { value: &#value, attr: #attr } }\n            }\n            Self::BinOp { left, op, right } => {\n                let left = left.to_introspection_token_stream(pyo3_crate_path);\n                let op = match op {\n                    PyOperator::BitOr => quote!(#pyo3_crate_path::inspect::PyStaticOperator::BitOr),\n                };\n                let right = right.to_introspection_token_stream(pyo3_crate_path);\n                quote! {\n                    #pyo3_crate_path::inspect::PyStaticExpr::BinOp {\n                        left: &#left,\n                        op: #op,\n                        right: &#right,\n                    }\n                }\n            }\n            Self::Subscript { value, slice } => {\n                let value = value.to_introspection_token_stream(pyo3_crate_path);\n                let slice = slice.to_introspection_token_stream(pyo3_crate_path);\n                quote! { #pyo3_crate_path::inspect::PyStaticExpr::Subscript { value: &#value, slice: &#slice } }\n            }\n            Self::Tuple { elts } => {\n                let elts = elts\n                    .iter()\n                    .map(|e| e.to_introspection_token_stream(pyo3_crate_path));\n                quote! { #pyo3_crate_path::inspect::PyStaticExpr::Tuple { elts: &[#(#elts),*] } }\n            }\n            Self::Constant(c) => match c {\n                PyConstant::None => {\n                    quote! { #pyo3_crate_path::inspect::PyStaticExpr::Constant { value: #pyo3_crate_path::inspect::PyStaticConstant::None } }\n                }\n                PyConstant::Bool(v) => {\n                    quote! { #pyo3_crate_path::inspect::PyStaticExpr::Constant { value: #pyo3_crate_path::inspect::PyStaticConstant::Bool(#v) } }\n                }\n                PyConstant::Int(v) => {\n                    quote! { #pyo3_crate_path::inspect::PyStaticExpr::Constant { value: #pyo3_crate_path::inspect::PyStaticConstant::Int(#v) } }\n                }\n                PyConstant::Float(v) => {\n                    quote! { #pyo3_crate_path::inspect::PyStaticExpr::Constant { value: #pyo3_crate_path::inspect::PyStaticConstant::Float(#v) } }\n                }\n                PyConstant::Str(v) => {\n                    quote! { #pyo3_crate_path::inspect::PyStaticExpr::Constant { value: #pyo3_crate_path::inspect::PyStaticConstant::Str(#v) } }\n                }\n                PyConstant::Ellipsis => {\n                    quote! { #pyo3_crate_path::inspect::PyStaticExpr::Constant { value: #pyo3_crate_path::inspect::PyStaticConstant::Ellipsis } }\n                }\n            },\n        }\n    }\n}\n\nfn clean_type(mut t: Type, self_type: Option<&Type>) -> Type {\n    if let Some(self_type) = self_type {\n        replace_self(&mut t, self_type);\n    }\n    elide_lifetimes(&mut t);\n    t\n}\n\n/// Replaces all explicit lifetimes in `self` with elided (`'_`) lifetimes\n///\n/// This is useful if `Self` is used in `const` context, where explicit\n/// lifetimes are not allowed (yet).\nfn elide_lifetimes(ty: &mut Type) {\n    struct ElideLifetimesVisitor;\n\n    impl VisitMut for ElideLifetimesVisitor {\n        fn visit_lifetime_mut(&mut self, l: &mut Lifetime) {\n            *l = Lifetime::new(\"'_\", l.span());\n        }\n    }\n\n    ElideLifetimesVisitor.visit_type_mut(ty);\n}\n\n// Replace Self in types with the given type\nfn replace_self(ty: &mut Type, self_target: &Type) {\n    struct SelfReplacementVisitor<'a> {\n        self_target: &'a Type,\n    }\n\n    impl VisitMut for SelfReplacementVisitor<'_> {\n        fn visit_type_mut(&mut self, ty: &mut Type) {\n            if let Type::Path(type_path) = ty {\n                if type_path.qself.is_none()\n                    && type_path.path.segments.len() == 1\n                    && type_path.path.segments[0].ident == \"Self\"\n                    && type_path.path.segments[0].arguments.is_empty()\n                {\n                    // It is Self\n                    *ty = self.self_target.clone();\n                    return;\n                }\n            }\n            visit_type_mut(self, ty);\n        }\n    }\n\n    SelfReplacementVisitor { self_target }.visit_type_mut(ty);\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/pyclass.rs",
    "content": "use std::borrow::Cow;\nuse std::fmt::Debug;\n\nuse proc_macro2::{Ident, Span, TokenStream};\nuse quote::{format_ident, quote, quote_spanned, ToTokens};\nuse syn::ext::IdentExt;\nuse syn::parse::{Parse, ParseStream};\nuse syn::punctuated::Punctuated;\nuse syn::{parse_quote, parse_quote_spanned, spanned::Spanned, ImplItemFn, Result, Token};\n\nuse crate::attributes::kw::frozen;\nuse crate::attributes::{\n    self, kw, take_pyo3_options, CrateAttribute, ExtendsAttribute, FreelistAttribute,\n    ModuleAttribute, NameAttribute, NameLitStr, NewImplTypeAttribute, NewImplTypeAttributeValue,\n    RenameAllAttribute, StrFormatterAttribute,\n};\nuse crate::combine_errors::CombineErrors;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::introspection::{\n    attribute_introspection_code, class_introspection_code, function_introspection_code,\n    introspection_id_const,\n};\nuse crate::konst::{ConstAttributes, ConstSpec};\nuse crate::method::{FnArg, FnSpec, PyArg, RegularArg};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::py_expr::PyExpr;\nuse crate::pyfunction::{ConstructorAttribute, FunctionSignature};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::pyimpl::method_introspection_code;\nuse crate::pyimpl::{gen_py_const, get_cfg_attributes, PyClassMethodsType};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::pymethod::field_python_name;\nuse crate::pymethod::{\n    impl_py_class_attribute, impl_py_getter_def, impl_py_setter_def, MethodAndMethodDef,\n    MethodAndSlotDef, PropertyType, SlotDef, __GETITEM__, __HASH__, __INT__, __LEN__, __NEW__,\n    __REPR__, __RICHCMP__, __STR__,\n};\nuse crate::utils::{self, apply_renaming_rule, get_doc, locate_tokens_at, Ctx, PythonDoc};\nuse crate::PyFunctionOptions;\n\n/// If the class is derived from a Rust `struct` or `enum`.\n#[derive(Copy, Clone, Debug, PartialEq, Eq)]\npub enum PyClassKind {\n    Struct,\n    Enum,\n}\n\n/// The parsed arguments of the pyclass macro\n#[derive(Clone)]\npub struct PyClassArgs {\n    pub class_kind: PyClassKind,\n    pub options: PyClassPyO3Options,\n}\n\nimpl PyClassArgs {\n    fn parse(input: ParseStream<'_>, kind: PyClassKind) -> Result<Self> {\n        Ok(PyClassArgs {\n            class_kind: kind,\n            options: PyClassPyO3Options::parse(input)?,\n        })\n    }\n\n    pub fn parse_struct_args(input: ParseStream<'_>) -> syn::Result<Self> {\n        Self::parse(input, PyClassKind::Struct)\n    }\n\n    pub fn parse_enum_args(input: ParseStream<'_>) -> syn::Result<Self> {\n        Self::parse(input, PyClassKind::Enum)\n    }\n}\n\n#[derive(Clone, Default)]\npub struct PyClassPyO3Options {\n    pub krate: Option<CrateAttribute>,\n    pub dict: Option<kw::dict>,\n    pub eq: Option<kw::eq>,\n    pub eq_int: Option<kw::eq_int>,\n    pub extends: Option<ExtendsAttribute>,\n    pub get_all: Option<kw::get_all>,\n    pub freelist: Option<FreelistAttribute>,\n    pub frozen: Option<kw::frozen>,\n    pub hash: Option<kw::hash>,\n    pub immutable_type: Option<kw::immutable_type>,\n    pub mapping: Option<kw::mapping>,\n    pub module: Option<ModuleAttribute>,\n    pub name: Option<NameAttribute>,\n    pub ord: Option<kw::ord>,\n    pub rename_all: Option<RenameAllAttribute>,\n    pub sequence: Option<kw::sequence>,\n    pub set_all: Option<kw::set_all>,\n    pub new: Option<NewImplTypeAttribute>,\n    pub str: Option<StrFormatterAttribute>,\n    pub subclass: Option<kw::subclass>,\n    pub unsendable: Option<kw::unsendable>,\n    pub weakref: Option<kw::weakref>,\n    pub generic: Option<kw::generic>,\n    pub from_py_object: Option<kw::from_py_object>,\n    pub skip_from_py_object: Option<kw::skip_from_py_object>,\n}\n\npub enum PyClassPyO3Option {\n    Crate(CrateAttribute),\n    Dict(kw::dict),\n    Eq(kw::eq),\n    EqInt(kw::eq_int),\n    Extends(ExtendsAttribute),\n    Freelist(FreelistAttribute),\n    Frozen(kw::frozen),\n    GetAll(kw::get_all),\n    Hash(kw::hash),\n    ImmutableType(kw::immutable_type),\n    Mapping(kw::mapping),\n    Module(ModuleAttribute),\n    Name(NameAttribute),\n    Ord(kw::ord),\n    RenameAll(RenameAllAttribute),\n    Sequence(kw::sequence),\n    SetAll(kw::set_all),\n    New(NewImplTypeAttribute),\n    Str(StrFormatterAttribute),\n    Subclass(kw::subclass),\n    Unsendable(kw::unsendable),\n    Weakref(kw::weakref),\n    Generic(kw::generic),\n    FromPyObject(kw::from_py_object),\n    SkipFromPyObject(kw::skip_from_py_object),\n}\n\nimpl Parse for PyClassPyO3Option {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let lookahead = input.lookahead1();\n        if lookahead.peek(Token![crate]) {\n            input.parse().map(PyClassPyO3Option::Crate)\n        } else if lookahead.peek(kw::dict) {\n            input.parse().map(PyClassPyO3Option::Dict)\n        } else if lookahead.peek(kw::eq) {\n            input.parse().map(PyClassPyO3Option::Eq)\n        } else if lookahead.peek(kw::eq_int) {\n            input.parse().map(PyClassPyO3Option::EqInt)\n        } else if lookahead.peek(kw::extends) {\n            input.parse().map(PyClassPyO3Option::Extends)\n        } else if lookahead.peek(attributes::kw::freelist) {\n            input.parse().map(PyClassPyO3Option::Freelist)\n        } else if lookahead.peek(attributes::kw::frozen) {\n            input.parse().map(PyClassPyO3Option::Frozen)\n        } else if lookahead.peek(attributes::kw::get_all) {\n            input.parse().map(PyClassPyO3Option::GetAll)\n        } else if lookahead.peek(attributes::kw::hash) {\n            input.parse().map(PyClassPyO3Option::Hash)\n        } else if lookahead.peek(attributes::kw::immutable_type) {\n            input.parse().map(PyClassPyO3Option::ImmutableType)\n        } else if lookahead.peek(attributes::kw::mapping) {\n            input.parse().map(PyClassPyO3Option::Mapping)\n        } else if lookahead.peek(attributes::kw::module) {\n            input.parse().map(PyClassPyO3Option::Module)\n        } else if lookahead.peek(kw::name) {\n            input.parse().map(PyClassPyO3Option::Name)\n        } else if lookahead.peek(attributes::kw::ord) {\n            input.parse().map(PyClassPyO3Option::Ord)\n        } else if lookahead.peek(kw::rename_all) {\n            input.parse().map(PyClassPyO3Option::RenameAll)\n        } else if lookahead.peek(attributes::kw::sequence) {\n            input.parse().map(PyClassPyO3Option::Sequence)\n        } else if lookahead.peek(attributes::kw::set_all) {\n            input.parse().map(PyClassPyO3Option::SetAll)\n        } else if lookahead.peek(attributes::kw::new) {\n            input.parse().map(PyClassPyO3Option::New)\n        } else if lookahead.peek(attributes::kw::str) {\n            input.parse().map(PyClassPyO3Option::Str)\n        } else if lookahead.peek(attributes::kw::subclass) {\n            input.parse().map(PyClassPyO3Option::Subclass)\n        } else if lookahead.peek(attributes::kw::unsendable) {\n            input.parse().map(PyClassPyO3Option::Unsendable)\n        } else if lookahead.peek(attributes::kw::weakref) {\n            input.parse().map(PyClassPyO3Option::Weakref)\n        } else if lookahead.peek(attributes::kw::generic) {\n            input.parse().map(PyClassPyO3Option::Generic)\n        } else if lookahead.peek(attributes::kw::from_py_object) {\n            input.parse().map(PyClassPyO3Option::FromPyObject)\n        } else if lookahead.peek(attributes::kw::skip_from_py_object) {\n            input.parse().map(PyClassPyO3Option::SkipFromPyObject)\n        } else {\n            Err(lookahead.error())\n        }\n    }\n}\n\nimpl Parse for PyClassPyO3Options {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        let mut options: PyClassPyO3Options = Default::default();\n\n        for option in Punctuated::<PyClassPyO3Option, syn::Token![,]>::parse_terminated(input)? {\n            options.set_option(option)?;\n        }\n\n        Ok(options)\n    }\n}\n\nimpl PyClassPyO3Options {\n    pub fn take_pyo3_options(&mut self, attrs: &mut Vec<syn::Attribute>) -> syn::Result<()> {\n        take_pyo3_options(attrs)?\n            .into_iter()\n            .try_for_each(|option| self.set_option(option))\n    }\n\n    fn set_option(&mut self, option: PyClassPyO3Option) -> syn::Result<()> {\n        macro_rules! set_option {\n            ($key:ident) => {\n                {\n                    ensure_spanned!(\n                        self.$key.is_none(),\n                        $key.span() => concat!(\"`\", stringify!($key), \"` may only be specified once\")\n                    );\n                    self.$key = Some($key);\n                }\n            };\n        }\n\n        match option {\n            PyClassPyO3Option::Crate(krate) => set_option!(krate),\n            PyClassPyO3Option::Dict(dict) => set_option!(dict),\n            PyClassPyO3Option::Eq(eq) => set_option!(eq),\n            PyClassPyO3Option::EqInt(eq_int) => set_option!(eq_int),\n            PyClassPyO3Option::Extends(extends) => set_option!(extends),\n            PyClassPyO3Option::Freelist(freelist) => set_option!(freelist),\n            PyClassPyO3Option::Frozen(frozen) => set_option!(frozen),\n            PyClassPyO3Option::GetAll(get_all) => set_option!(get_all),\n            PyClassPyO3Option::ImmutableType(immutable_type) => {\n                set_option!(immutable_type)\n            }\n            PyClassPyO3Option::Hash(hash) => set_option!(hash),\n            PyClassPyO3Option::Mapping(mapping) => set_option!(mapping),\n            PyClassPyO3Option::Module(module) => set_option!(module),\n            PyClassPyO3Option::Name(name) => set_option!(name),\n            PyClassPyO3Option::Ord(ord) => set_option!(ord),\n            PyClassPyO3Option::RenameAll(rename_all) => set_option!(rename_all),\n            PyClassPyO3Option::Sequence(sequence) => set_option!(sequence),\n            PyClassPyO3Option::SetAll(set_all) => set_option!(set_all),\n            PyClassPyO3Option::New(new) => set_option!(new),\n            PyClassPyO3Option::Str(str) => set_option!(str),\n            PyClassPyO3Option::Subclass(subclass) => set_option!(subclass),\n            PyClassPyO3Option::Unsendable(unsendable) => set_option!(unsendable),\n            PyClassPyO3Option::Weakref(weakref) => set_option!(weakref),\n            PyClassPyO3Option::Generic(generic) => set_option!(generic),\n            PyClassPyO3Option::SkipFromPyObject(skip_from_py_object) => {\n                ensure_spanned!(\n                    self.from_py_object.is_none(),\n                    skip_from_py_object.span() => \"`skip_from_py_object` and `from_py_object` are mutually exclusive\"\n                );\n                set_option!(skip_from_py_object)\n            }\n            PyClassPyO3Option::FromPyObject(from_py_object) => {\n                ensure_spanned!(\n                    self.skip_from_py_object.is_none(),\n                    from_py_object.span() => \"`skip_from_py_object` and `from_py_object` are mutually exclusive\"\n                );\n                set_option!(from_py_object)\n            }\n        }\n        Ok(())\n    }\n}\n\npub fn build_py_class(\n    class: &mut syn::ItemStruct,\n    mut args: PyClassArgs,\n    methods_type: PyClassMethodsType,\n) -> syn::Result<TokenStream> {\n    args.options.take_pyo3_options(&mut class.attrs)?;\n\n    let ctx = &Ctx::new(&args.options.krate, None);\n    let doc = utils::get_doc(&class.attrs, None);\n\n    if let Some(lt) = class.generics.lifetimes().next() {\n        bail_spanned!(\n            lt.span() => concat!(\n                \"#[pyclass] cannot have lifetime parameters. For an explanation, see \\\n                https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#no-lifetime-parameters\"\n            )\n        );\n    }\n\n    ensure_spanned!(\n        class.generics.params.is_empty(),\n        class.generics.span() => concat!(\n            \"#[pyclass] cannot have generic parameters. For an explanation, see \\\n            https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#no-generic-parameters\"\n        )\n    );\n\n    let mut field_options: Vec<(&syn::Field, FieldPyO3Options)> = match &mut class.fields {\n        syn::Fields::Named(fields) => fields\n            .named\n            .iter_mut()\n            .map(\n                |field| match FieldPyO3Options::take_pyo3_options(&mut field.attrs) {\n                    Ok(options) => Ok((&*field, options)),\n                    Err(e) => Err(e),\n                },\n            )\n            .collect::<Vec<_>>(),\n        syn::Fields::Unnamed(fields) => fields\n            .unnamed\n            .iter_mut()\n            .map(\n                |field| match FieldPyO3Options::take_pyo3_options(&mut field.attrs) {\n                    Ok(options) => Ok((&*field, options)),\n                    Err(e) => Err(e),\n                },\n            )\n            .collect::<Vec<_>>(),\n        syn::Fields::Unit => {\n            let mut results = Vec::new();\n\n            if let Some(attr) = args.options.set_all {\n                results.push(Err(syn::Error::new_spanned(attr, UNIT_SET)));\n            };\n            if let Some(attr) = args.options.get_all {\n                results.push(Err(syn::Error::new_spanned(attr, UNIT_GET)));\n            };\n\n            results\n        }\n    }\n    .into_iter()\n    .try_combine_syn_errors()?;\n\n    if let Some(attr) = args.options.get_all {\n        for (_, FieldPyO3Options { get, .. }) in &mut field_options {\n            if let Some(old_get) = get.replace(Annotated::Struct(attr)) {\n                return Err(syn::Error::new(old_get.span(), DUPE_GET));\n            }\n        }\n    }\n\n    if let Some(attr) = args.options.set_all {\n        for (_, FieldPyO3Options { set, .. }) in &mut field_options {\n            if let Some(old_set) = set.replace(Annotated::Struct(attr)) {\n                return Err(syn::Error::new(old_set.span(), DUPE_SET));\n            }\n        }\n    }\n\n    impl_class(&class.ident, &args, doc, field_options, methods_type, ctx)\n}\n\nenum Annotated<X, Y> {\n    Field(X),\n    Struct(Y),\n}\n\nimpl<X: Spanned, Y: Spanned> Annotated<X, Y> {\n    fn span(&self) -> Span {\n        match self {\n            Self::Field(x) => x.span(),\n            Self::Struct(y) => y.span(),\n        }\n    }\n}\n\n/// `#[pyo3()]` options for pyclass fields\nstruct FieldPyO3Options {\n    get: Option<Annotated<kw::get, kw::get_all>>,\n    set: Option<Annotated<kw::set, kw::set_all>>,\n    name: Option<NameAttribute>,\n}\n\nenum FieldPyO3Option {\n    Get(attributes::kw::get),\n    Set(attributes::kw::set),\n    Name(NameAttribute),\n}\n\nimpl Parse for FieldPyO3Option {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let lookahead = input.lookahead1();\n        if lookahead.peek(attributes::kw::get) {\n            input.parse().map(FieldPyO3Option::Get)\n        } else if lookahead.peek(attributes::kw::set) {\n            input.parse().map(FieldPyO3Option::Set)\n        } else if lookahead.peek(attributes::kw::name) {\n            input.parse().map(FieldPyO3Option::Name)\n        } else {\n            Err(lookahead.error())\n        }\n    }\n}\n\nimpl FieldPyO3Options {\n    fn take_pyo3_options(attrs: &mut Vec<syn::Attribute>) -> Result<Self> {\n        let mut options = FieldPyO3Options {\n            get: None,\n            set: None,\n            name: None,\n        };\n\n        for option in take_pyo3_options(attrs)? {\n            match option {\n                FieldPyO3Option::Get(kw) => {\n                    if options.get.replace(Annotated::Field(kw)).is_some() {\n                        return Err(syn::Error::new(kw.span(), UNIQUE_GET));\n                    }\n                }\n                FieldPyO3Option::Set(kw) => {\n                    if options.set.replace(Annotated::Field(kw)).is_some() {\n                        return Err(syn::Error::new(kw.span(), UNIQUE_SET));\n                    }\n                }\n                FieldPyO3Option::Name(name) => {\n                    if options.name.replace(name).is_some() {\n                        return Err(syn::Error::new(options.name.span(), UNIQUE_NAME));\n                    }\n                }\n            }\n        }\n\n        Ok(options)\n    }\n}\n\nfn get_class_python_name<'a>(cls: &'a Ident, args: &'a PyClassArgs) -> Cow<'a, Ident> {\n    args.options\n        .name\n        .as_ref()\n        .map(|name_attr| Cow::Borrowed(&name_attr.value.0))\n        .unwrap_or_else(|| Cow::Owned(cls.unraw()))\n}\n\n#[cfg(feature = \"experimental-inspect\")]\nfn get_class_type_hint(cls: &Ident, args: &PyClassArgs, ctx: &Ctx) -> TokenStream {\n    let pyo3_path = &ctx.pyo3_path;\n    let name = get_class_python_name(cls, args).to_string();\n    if let Some(module) = &args.options.module {\n        let module = module.value.value();\n        quote! {\n            #pyo3_path::inspect::PyStaticExpr::PyClass(#pyo3_path::inspect::PyClassNameStaticExpr::new(\n                &#pyo3_path::inspect::PyStaticExpr::Attribute {\n                    value: &#pyo3_path::inspect::PyStaticExpr::Name {\n                        id: #module\n                    },\n                    attr: #name\n                },\n                Self::_PYO3_INTROSPECTION_ID\n            ))\n        }\n    } else {\n        quote! {\n            #pyo3_path::inspect::PyStaticExpr::PyClass(#pyo3_path::inspect::PyClassNameStaticExpr::new(\n                &#pyo3_path::inspect::PyStaticExpr::Name {\n                    id: #name\n                },\n                Self::_PYO3_INTROSPECTION_ID\n            ))\n        }\n    }\n}\n\nfn impl_class(\n    cls: &Ident,\n    args: &PyClassArgs,\n    doc: Option<PythonDoc>,\n    field_options: Vec<(&syn::Field, FieldPyO3Options)>,\n    methods_type: PyClassMethodsType,\n    ctx: &Ctx,\n) -> Result<TokenStream> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let pytypeinfo_impl = impl_pytypeinfo(cls, args, ctx);\n\n    if let Some(str) = &args.options.str {\n        if str.value.is_some() {\n            // check if any renaming is present\n            let no_naming_conflict = field_options.iter().all(|x| x.1.name.is_none())\n                & args.options.name.is_none()\n                & args.options.rename_all.is_none();\n            ensure_spanned!(no_naming_conflict, str.value.span() => \"The format string syntax is incompatible with any renaming via `name` or `rename_all`\");\n        }\n    }\n\n    let (default_new, default_new_slot) = pyclass_new_impl(\n        &args.options,\n        &syn::parse_quote!(#cls),\n        field_options.iter().map(|(f, _)| f),\n        ctx,\n    )?;\n\n    let mut default_methods = descriptors_to_items(\n        cls,\n        args.options.rename_all.as_ref(),\n        args.options.frozen,\n        field_options,\n        ctx,\n    )?;\n\n    let (default_class_getitem, default_class_getitem_method) =\n        pyclass_class_getitem(&args.options, &syn::parse_quote!(#cls), ctx)?;\n\n    if let Some(default_class_getitem_method) = default_class_getitem_method {\n        default_methods.push(default_class_getitem_method);\n    }\n\n    let (default_str, default_str_slot) =\n        implement_pyclass_str(&args.options, &syn::parse_quote!(#cls), ctx);\n\n    let (default_richcmp, default_richcmp_slot) =\n        pyclass_richcmp(&args.options, &syn::parse_quote!(#cls), ctx)?;\n\n    let (default_hash, default_hash_slot) =\n        pyclass_hash(&args.options, &syn::parse_quote!(#cls), ctx)?;\n\n    let mut slots = Vec::new();\n    slots.extend(default_richcmp_slot);\n    slots.extend(default_hash_slot);\n    slots.extend(default_str_slot);\n    slots.extend(default_new_slot);\n\n    let mut impl_builder =\n        PyClassImplsBuilder::new(cls, cls, args, methods_type, default_methods, slots);\n    if let Some(doc) = doc {\n        impl_builder = impl_builder.doc(doc);\n    }\n    let py_class_impl: TokenStream = [\n        impl_builder.impl_pyclass(ctx),\n        impl_builder.impl_into_py(ctx),\n        impl_builder.impl_pyclassimpl(ctx)?,\n        impl_builder.impl_add_to_module(ctx),\n        impl_builder.impl_freelist(ctx),\n        impl_builder.impl_introspection(ctx, None),\n    ]\n    .into_iter()\n    .collect();\n\n    Ok(quote! {\n        impl #pyo3_path::types::DerefToPyAny for #cls {}\n\n        #pytypeinfo_impl\n\n        #py_class_impl\n\n        #[doc(hidden)]\n        #[allow(non_snake_case)]\n        impl #cls {\n            #default_richcmp\n            #default_hash\n            #default_str\n            #default_new\n            #default_class_getitem\n        }\n    })\n}\n\nenum PyClassEnum<'a> {\n    Simple(PyClassSimpleEnum<'a>),\n    Complex(PyClassComplexEnum<'a>),\n}\n\nimpl<'a> PyClassEnum<'a> {\n    fn new(enum_: &'a mut syn::ItemEnum) -> syn::Result<Self> {\n        let has_only_unit_variants = enum_\n            .variants\n            .iter()\n            .all(|variant| matches!(variant.fields, syn::Fields::Unit));\n\n        Ok(if has_only_unit_variants {\n            let simple_enum = PyClassSimpleEnum::new(enum_)?;\n            Self::Simple(simple_enum)\n        } else {\n            let complex_enum = PyClassComplexEnum::new(enum_)?;\n            Self::Complex(complex_enum)\n        })\n    }\n}\n\npub fn build_py_enum(\n    enum_: &mut syn::ItemEnum,\n    mut args: PyClassArgs,\n    method_type: PyClassMethodsType,\n) -> syn::Result<TokenStream> {\n    args.options.take_pyo3_options(&mut enum_.attrs)?;\n\n    let ctx = &Ctx::new(&args.options.krate, None);\n    if let Some(extends) = &args.options.extends {\n        bail_spanned!(extends.span() => \"enums can't extend from other classes\");\n    } else if let Some(subclass) = &args.options.subclass {\n        bail_spanned!(subclass.span() => \"enums can't be inherited by other classes\");\n    } else if enum_.variants.is_empty() {\n        bail_spanned!(enum_.brace_token.span.join() => \"#[pyclass] can't be used on enums without any variants\");\n    }\n\n    if let Some(generic) = &args.options.generic {\n        bail_spanned!(generic.span() => \"enums do not support #[pyclass(generic)]\");\n    }\n\n    let doc = utils::get_doc(&enum_.attrs, None);\n    let enum_ = PyClassEnum::new(enum_)?;\n    impl_enum(enum_, &args, doc, method_type, ctx)\n}\n\nstruct PyClassSimpleEnum<'a> {\n    ident: &'a syn::Ident,\n    // The underlying #[repr] of the enum, used to implement __int__ and __richcmp__.\n    // This matters when the underlying representation may not fit in `isize`.\n    repr_type: syn::Ident,\n    variants: Vec<PyClassEnumUnitVariant<'a>>,\n}\n\nimpl<'a> PyClassSimpleEnum<'a> {\n    fn new(enum_: &'a mut syn::ItemEnum) -> syn::Result<Self> {\n        fn is_numeric_type(t: &syn::Ident) -> bool {\n            [\n                \"u8\", \"i8\", \"u16\", \"i16\", \"u32\", \"i32\", \"u64\", \"i64\", \"u128\", \"i128\", \"usize\",\n                \"isize\",\n            ]\n            .iter()\n            .any(|&s| t == s)\n        }\n\n        fn extract_unit_variant_data(\n            variant: &mut syn::Variant,\n        ) -> syn::Result<PyClassEnumUnitVariant<'_>> {\n            use syn::Fields;\n            let ident = match &variant.fields {\n                Fields::Unit => &variant.ident,\n                _ => bail_spanned!(variant.span() => \"Must be a unit variant.\"),\n            };\n            let options = EnumVariantPyO3Options::take_pyo3_options(&mut variant.attrs)?;\n            Ok(PyClassEnumUnitVariant {\n                ident,\n                options,\n                attrs: variant.attrs.clone(),\n            })\n        }\n\n        let ident = &enum_.ident;\n\n        // According to the [reference](https://doc.rust-lang.org/reference/items/enumerations.html),\n        // \"Under the default representation, the specified discriminant is interpreted as an isize\n        // value\", so `isize` should be enough by default.\n        let mut repr_type = syn::Ident::new(\"isize\", proc_macro2::Span::call_site());\n        if let Some(attr) = enum_.attrs.iter().find(|attr| attr.path().is_ident(\"repr\")) {\n            let args =\n                attr.parse_args_with(Punctuated::<TokenStream, Token![!]>::parse_terminated)?;\n            if let Some(ident) = args\n                .into_iter()\n                .filter_map(|ts| syn::parse2::<syn::Ident>(ts).ok())\n                .find(is_numeric_type)\n            {\n                repr_type = ident;\n            }\n        }\n\n        let variants: Vec<_> = enum_\n            .variants\n            .iter_mut()\n            .map(extract_unit_variant_data)\n            .collect::<syn::Result<_>>()?;\n        Ok(Self {\n            ident,\n            repr_type,\n            variants,\n        })\n    }\n}\n\nstruct PyClassComplexEnum<'a> {\n    ident: &'a syn::Ident,\n    variants: Vec<PyClassEnumVariant<'a>>,\n}\n\nimpl<'a> PyClassComplexEnum<'a> {\n    fn new(enum_: &'a mut syn::ItemEnum) -> syn::Result<Self> {\n        let witness = enum_\n            .variants\n            .iter()\n            .find(|variant| !matches!(variant.fields, syn::Fields::Unit))\n            .expect(\"complex enum has a non-unit variant\")\n            .ident\n            .to_owned();\n\n        let extract_variant_data =\n            |variant: &'a mut syn::Variant| -> syn::Result<PyClassEnumVariant<'a>> {\n                use syn::Fields;\n                let ident = &variant.ident;\n                let options = EnumVariantPyO3Options::take_pyo3_options(&mut variant.attrs)?;\n\n                let variant = match &variant.fields {\n                    Fields::Unit => {\n                        bail_spanned!(variant.span() => format!(\n                            \"Unit variant `{ident}` is not yet supported in a complex enum\\n\\\n                            = help: change to an empty tuple variant instead: `{ident}()`\\n\\\n                            = note: the enum is complex because of non-unit variant `{witness}`\",\n                            ident=ident, witness=witness))\n                    }\n                    Fields::Named(fields) => {\n                        let fields = fields\n                            .named\n                            .iter()\n                            .map(|field| PyClassEnumVariantNamedField {\n                                ident: field.ident.as_ref().expect(\"named field has an identifier\"),\n                                ty: &field.ty,\n                                attrs: &field.attrs,\n                                span: field.span(),\n                            })\n                            .collect();\n\n                        PyClassEnumVariant::Struct(PyClassEnumStructVariant {\n                            ident,\n                            fields,\n                            options,\n                            attrs: variant.attrs.clone(),\n                        })\n                    }\n                    Fields::Unnamed(types) => {\n                        let fields = types\n                            .unnamed\n                            .iter()\n                            .map(|field| PyClassEnumVariantUnnamedField {\n                                ty: &field.ty,\n                                span: field.span(),\n                                attrs: &field.attrs,\n                            })\n                            .collect();\n\n                        PyClassEnumVariant::Tuple(PyClassEnumTupleVariant {\n                            ident,\n                            fields,\n                            options,\n                            attrs: variant.attrs.clone(),\n                        })\n                    }\n                };\n\n                Ok(variant)\n            };\n\n        let ident = &enum_.ident;\n\n        let variants: Vec<_> = enum_\n            .variants\n            .iter_mut()\n            .map(extract_variant_data)\n            .collect::<syn::Result<_>>()?;\n\n        Ok(Self { ident, variants })\n    }\n}\n\nenum PyClassEnumVariant<'a> {\n    // TODO(mkovaxx): Unit(PyClassEnumUnitVariant<'a>),\n    Struct(PyClassEnumStructVariant<'a>),\n    Tuple(PyClassEnumTupleVariant<'a>),\n}\n\ntrait EnumVariant {\n    fn get_ident(&self) -> &syn::Ident;\n    fn get_options(&self) -> &EnumVariantPyO3Options;\n    fn get_attrs(&self) -> &[syn::Attribute];\n\n    fn get_python_name(&self, args: &PyClassArgs) -> Cow<'_, syn::Ident> {\n        self.get_options()\n            .name\n            .as_ref()\n            .map(|name_attr| Cow::Borrowed(&name_attr.value.0))\n            .unwrap_or_else(|| {\n                let name = self.get_ident().unraw();\n                if let Some(attr) = &args.options.rename_all {\n                    let new_name = apply_renaming_rule(attr.value.rule, &name.to_string());\n                    Cow::Owned(Ident::new(&new_name, Span::call_site()))\n                } else {\n                    Cow::Owned(name)\n                }\n            })\n    }\n}\n\nimpl EnumVariant for PyClassEnumVariant<'_> {\n    fn get_ident(&self) -> &syn::Ident {\n        match self {\n            Self::Struct(struct_variant) => struct_variant.ident,\n            Self::Tuple(tuple_variant) => tuple_variant.ident,\n        }\n    }\n\n    fn get_options(&self) -> &EnumVariantPyO3Options {\n        match self {\n            Self::Struct(struct_variant) => &struct_variant.options,\n            Self::Tuple(tuple_variant) => &tuple_variant.options,\n        }\n    }\n\n    fn get_attrs(&self) -> &[syn::Attribute] {\n        match self {\n            Self::Struct(struct_variant) => &struct_variant.attrs,\n            Self::Tuple(tuple_variant) => &tuple_variant.attrs,\n        }\n    }\n}\n\n/// A unit variant has no fields\nstruct PyClassEnumUnitVariant<'a> {\n    ident: &'a syn::Ident,\n    options: EnumVariantPyO3Options,\n    attrs: Vec<syn::Attribute>,\n}\n\nimpl EnumVariant for PyClassEnumUnitVariant<'_> {\n    fn get_ident(&self) -> &syn::Ident {\n        self.ident\n    }\n\n    fn get_options(&self) -> &EnumVariantPyO3Options {\n        &self.options\n    }\n\n    fn get_attrs(&self) -> &[syn::Attribute] {\n        &self.attrs\n    }\n}\n\n/// A struct variant has named fields\nstruct PyClassEnumStructVariant<'a> {\n    ident: &'a syn::Ident,\n    fields: Vec<PyClassEnumVariantNamedField<'a>>,\n    options: EnumVariantPyO3Options,\n    attrs: Vec<syn::Attribute>,\n}\n\nimpl PyClassEnumStructVariant<'_> {\n    fn python_name(&self) -> Cow<'_, syn::Ident> {\n        self.options\n            .name\n            .as_ref()\n            .map(|name_attr| Cow::Borrowed(&name_attr.value.0))\n            .unwrap_or_else(|| Cow::Owned(self.ident.unraw()))\n    }\n}\n\nstruct PyClassEnumTupleVariant<'a> {\n    ident: &'a syn::Ident,\n    fields: Vec<PyClassEnumVariantUnnamedField<'a>>,\n    options: EnumVariantPyO3Options,\n    attrs: Vec<syn::Attribute>,\n}\n\nimpl PyClassEnumTupleVariant<'_> {\n    fn python_name(&self) -> Cow<'_, syn::Ident> {\n        self.options\n            .name\n            .as_ref()\n            .map(|name_attr| Cow::Borrowed(&name_attr.value.0))\n            .unwrap_or_else(|| Cow::Owned(self.ident.unraw()))\n    }\n}\n\nstruct PyClassEnumVariantNamedField<'a> {\n    ident: &'a syn::Ident,\n    ty: &'a syn::Type,\n    attrs: &'a [syn::Attribute],\n    span: Span,\n}\n\nstruct PyClassEnumVariantUnnamedField<'a> {\n    ty: &'a syn::Type,\n    attrs: &'a [syn::Attribute],\n    span: Span,\n}\n\n/// `#[pyo3()]` options for pyclass enum variants\n#[derive(Clone, Default)]\nstruct EnumVariantPyO3Options {\n    name: Option<NameAttribute>,\n    constructor: Option<ConstructorAttribute>,\n}\n\nenum EnumVariantPyO3Option {\n    Name(NameAttribute),\n    Constructor(ConstructorAttribute),\n}\n\nimpl Parse for EnumVariantPyO3Option {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let lookahead = input.lookahead1();\n        if lookahead.peek(attributes::kw::name) {\n            input.parse().map(EnumVariantPyO3Option::Name)\n        } else if lookahead.peek(attributes::kw::constructor) {\n            input.parse().map(EnumVariantPyO3Option::Constructor)\n        } else {\n            Err(lookahead.error())\n        }\n    }\n}\n\nimpl EnumVariantPyO3Options {\n    fn take_pyo3_options(attrs: &mut Vec<syn::Attribute>) -> Result<Self> {\n        let mut options = EnumVariantPyO3Options::default();\n\n        take_pyo3_options(attrs)?\n            .into_iter()\n            .try_for_each(|option| options.set_option(option))?;\n\n        Ok(options)\n    }\n\n    fn set_option(&mut self, option: EnumVariantPyO3Option) -> syn::Result<()> {\n        macro_rules! set_option {\n            ($key:ident) => {\n                {\n                    ensure_spanned!(\n                        self.$key.is_none(),\n                        $key.span() => concat!(\"`\", stringify!($key), \"` may only be specified once\")\n                    );\n                    self.$key = Some($key);\n                }\n            };\n        }\n\n        match option {\n            EnumVariantPyO3Option::Constructor(constructor) => set_option!(constructor),\n            EnumVariantPyO3Option::Name(name) => set_option!(name),\n        }\n        Ok(())\n    }\n}\n\n// todo(remove this dead code allowance once __repr__ is implemented\n#[allow(dead_code)]\npub enum PyFmtName {\n    Str,\n    Repr,\n}\n\nfn implement_py_formatting(\n    ty: &syn::Type,\n    ctx: &Ctx,\n    option: &StrFormatterAttribute,\n) -> (ImplItemFn, MethodAndSlotDef) {\n    let mut fmt_impl = match &option.value {\n        Some(opt) => {\n            let fmt = &opt.fmt;\n            let args = &opt\n                .args\n                .iter()\n                .map(|member| quote! {self.#member})\n                .collect::<Vec<TokenStream>>();\n            let fmt_impl: ImplItemFn = syn::parse_quote! {\n                fn __pyo3__generated____str__(&self) -> ::std::string::String {\n                    ::std::format!(#fmt, #(#args, )*)\n                }\n            };\n            fmt_impl\n        }\n        None => {\n            let fmt_impl: syn::ImplItemFn = syn::parse_quote! {\n                fn __pyo3__generated____str__(&self) -> ::std::string::String {\n                    ::std::format!(\"{}\", &self)\n                }\n            };\n            fmt_impl\n        }\n    };\n    let fmt_slot = generate_protocol_slot(\n        ty,\n        &mut fmt_impl,\n        &__STR__,\n        \"__str__\",\n        #[cfg(feature = \"experimental-inspect\")]\n        FunctionIntrospectionData {\n            names: &[\"__str__\"],\n            arguments: Vec::new(),\n            returns: parse_quote! { ::std::string::String },\n            is_returning_not_implemented_on_extraction_error: false,\n        },\n        ctx,\n    )\n    .unwrap();\n    (fmt_impl, fmt_slot)\n}\n\nfn implement_pyclass_str(\n    options: &PyClassPyO3Options,\n    ty: &syn::Type,\n    ctx: &Ctx,\n) -> (Option<ImplItemFn>, Option<MethodAndSlotDef>) {\n    match &options.str {\n        Some(option) => {\n            let (default_str, default_str_slot) = implement_py_formatting(ty, ctx, option);\n            (Some(default_str), Some(default_str_slot))\n        }\n        _ => (None, None),\n    }\n}\n\nfn impl_enum(\n    enum_: PyClassEnum<'_>,\n    args: &PyClassArgs,\n    doc: Option<PythonDoc>,\n    methods_type: PyClassMethodsType,\n    ctx: &Ctx,\n) -> Result<TokenStream> {\n    if let Some(str_fmt) = &args.options.str {\n        ensure_spanned!(str_fmt.value.is_none(), str_fmt.value.span() => \"The format string syntax cannot be used with enums\")\n    }\n\n    match enum_ {\n        PyClassEnum::Simple(simple_enum) => {\n            impl_simple_enum(simple_enum, args, doc, methods_type, ctx)\n        }\n        PyClassEnum::Complex(complex_enum) => {\n            impl_complex_enum(complex_enum, args, doc, methods_type, ctx)\n        }\n    }\n}\n\nfn impl_simple_enum(\n    simple_enum: PyClassSimpleEnum<'_>,\n    args: &PyClassArgs,\n    doc: Option<PythonDoc>,\n    methods_type: PyClassMethodsType,\n    ctx: &Ctx,\n) -> Result<TokenStream> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let cls = simple_enum.ident;\n    let ty: syn::Type = syn::parse_quote!(#cls);\n    let variants = simple_enum.variants;\n    let pytypeinfo = impl_pytypeinfo(cls, args, ctx);\n\n    for variant in &variants {\n        ensure_spanned!(variant.options.constructor.is_none(), variant.options.constructor.span() => \"`constructor` can't be used on a simple enum variant\");\n    }\n\n    let variant_cfg_check = generate_cfg_check(&variants, cls);\n\n    let (default_repr, default_repr_slot) = {\n        let variants_repr = variants.iter().map(|variant| {\n            let variant_name = variant.ident;\n            let cfg_attrs = get_cfg_attributes(&variant.attrs);\n            // Assuming all variants are unit variants because they are the only type we support.\n            let repr = format!(\n                \"{}.{}\",\n                get_class_python_name(cls, args),\n                variant.get_python_name(args),\n            );\n            quote! { #(#cfg_attrs)* #cls::#variant_name => #repr, }\n        });\n        let mut repr_impl: syn::ImplItemFn = syn::parse_quote! {\n            fn __pyo3__repr__(&self) -> &'static str {\n                match *self {\n                    #(#variants_repr)*\n                }\n            }\n        };\n        let repr_slot = generate_default_protocol_slot(\n            &ty,\n            &mut repr_impl,\n            &__REPR__,\n            #[cfg(feature = \"experimental-inspect\")]\n            FunctionIntrospectionData {\n                names: &[\"__repr__\"],\n                arguments: Vec::new(),\n                returns: parse_quote! { &'static str },\n                is_returning_not_implemented_on_extraction_error: false,\n            },\n            ctx,\n        )?;\n        (repr_impl, repr_slot)\n    };\n\n    let (default_str, default_str_slot) = implement_pyclass_str(&args.options, &ty, ctx);\n\n    let repr_type = &simple_enum.repr_type;\n\n    let (default_int, default_int_slot) = {\n        // This implementation allows us to convert &T to #repr_type without implementing `Copy`\n        let variants_to_int = variants.iter().map(|variant| {\n            let variant_name = variant.ident;\n            let cfg_attrs = get_cfg_attributes(&variant.attrs);\n            quote! { #(#cfg_attrs)* #cls::#variant_name => #cls::#variant_name as #repr_type, }\n        });\n        let mut int_impl: syn::ImplItemFn = syn::parse_quote! {\n            fn __pyo3__int__(&self) -> #repr_type {\n                match *self {\n                    #(#variants_to_int)*\n                }\n            }\n        };\n        let int_slot = generate_default_protocol_slot(\n            &ty,\n            &mut int_impl,\n            &__INT__,\n            #[cfg(feature = \"experimental-inspect\")]\n            FunctionIntrospectionData {\n                names: &[\"__int__\"],\n                arguments: Vec::new(),\n                returns: parse_quote!(#repr_type),\n                is_returning_not_implemented_on_extraction_error: false,\n            },\n            ctx,\n        )?;\n        (int_impl, int_slot)\n    };\n\n    let (default_richcmp, default_richcmp_slot) =\n        pyclass_richcmp_simple_enum(&args.options, &ty, repr_type, ctx)?;\n    let (default_hash, default_hash_slot) = pyclass_hash(&args.options, &ty, ctx)?;\n\n    let mut default_slots = vec![default_repr_slot, default_int_slot];\n    default_slots.extend(default_richcmp_slot);\n    default_slots.extend(default_hash_slot);\n    default_slots.extend(default_str_slot);\n\n    let mut impl_builder = PyClassImplsBuilder::new(\n        cls,\n        cls,\n        args,\n        methods_type,\n        simple_enum_default_methods(\n            cls,\n            variants\n                .iter()\n                .map(|v| (v.ident, v.get_python_name(args), v.attrs.as_slice())),\n            ctx,\n        ),\n        default_slots,\n    );\n    if let Some(doc) = doc {\n        impl_builder = impl_builder.doc(doc);\n    }\n\n    let enum_into_pyobject_impl = {\n        let output_type = get_conversion_type_hint(ctx, &format_ident!(\"OUTPUT_TYPE\"), cls);\n\n        let num = variants.len();\n        let i = (0..num).map(proc_macro2::Literal::usize_unsuffixed);\n        let variant_idents = variants.iter().map(|v| v.ident);\n        let cfgs = variants.iter().map(|v| get_cfg_attributes(&v.attrs));\n        quote! {\n            impl<'py> #pyo3_path::conversion::IntoPyObject<'py> for #cls {\n                type Target = Self;\n                type Output = #pyo3_path::Bound<'py, <Self as #pyo3_path::conversion::IntoPyObject<'py>>::Target>;\n                type Error = #pyo3_path::PyErr;\n                #output_type\n\n                fn into_pyobject(self, py: #pyo3_path::Python<'py>) -> ::std::result::Result<\n                    <Self as #pyo3_path::conversion::IntoPyObject<'py>>::Output,\n                    <Self as #pyo3_path::conversion::IntoPyObject<'py>>::Error,\n                > {\n                    // TODO(icxolu): switch this to lookup the variants on the type object, once that is immutable\n                    static SINGLETON: [#pyo3_path::sync::PyOnceLock<#pyo3_path::Py<#cls>>; #num] =\n                        [const { #pyo3_path::sync::PyOnceLock::<#pyo3_path::Py<#cls>>::new() }; #num];\n                    let idx: usize = match self {\n                        #(\n                            #(#cfgs)*\n                            Self::#variant_idents => #i,\n                        )*\n                    };\n                    #[allow(unreachable_code)]\n                    SINGLETON[idx].get_or_try_init(py, || {\n                        #pyo3_path::Py::new(py, self)\n                    }).map(|obj| ::std::clone::Clone::clone(obj.bind(py)))\n                }\n            }\n        }\n    };\n\n    let pyclass_impls: TokenStream = [\n        impl_builder.impl_pyclass(ctx),\n        enum_into_pyobject_impl,\n        impl_builder.impl_pyclassimpl(ctx)?,\n        impl_builder.impl_add_to_module(ctx),\n        impl_builder.impl_freelist(ctx),\n        impl_builder.impl_introspection(ctx, None),\n    ]\n    .into_iter()\n    .collect();\n\n    Ok(quote! {\n        #variant_cfg_check\n\n        #pytypeinfo\n\n        #pyclass_impls\n\n        #[doc(hidden)]\n        #[allow(non_snake_case)]\n        impl #cls {\n            #default_repr\n            #default_int\n            #default_richcmp\n            #default_hash\n            #default_str\n        }\n    })\n}\n\nfn impl_complex_enum(\n    complex_enum: PyClassComplexEnum<'_>,\n    args: &PyClassArgs,\n    doc: Option<PythonDoc>,\n    methods_type: PyClassMethodsType,\n    ctx: &Ctx,\n) -> Result<TokenStream> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let cls = complex_enum.ident;\n    let ty: syn::Type = syn::parse_quote!(#cls);\n\n    // Need to rig the enum PyClass options\n    let args = {\n        let mut rigged_args = args.clone();\n        // Needs to be frozen to disallow `&mut self` methods, which could break a runtime invariant\n        rigged_args.options.frozen = parse_quote!(frozen);\n        // Needs to be subclassable by the variant PyClasses\n        rigged_args.options.subclass = parse_quote!(subclass);\n        rigged_args\n    };\n\n    let ctx = &Ctx::new(&args.options.krate, None);\n    let cls = complex_enum.ident;\n    let variants = complex_enum.variants;\n    let pytypeinfo = impl_pytypeinfo(cls, &args, ctx);\n\n    let (default_richcmp, default_richcmp_slot) = pyclass_richcmp(&args.options, &ty, ctx)?;\n    let (default_hash, default_hash_slot) = pyclass_hash(&args.options, &ty, ctx)?;\n\n    let (default_str, default_str_slot) = implement_pyclass_str(&args.options, &ty, ctx);\n\n    let mut default_slots = vec![];\n    default_slots.extend(default_richcmp_slot);\n    default_slots.extend(default_hash_slot);\n    default_slots.extend(default_str_slot);\n\n    let mut impl_builder = PyClassImplsBuilder::new(\n        cls,\n        cls,\n        &args,\n        methods_type,\n        complex_enum_default_methods(\n            cls,\n            variants\n                .iter()\n                .map(|v| (v.get_ident(), v.get_python_name(&args), v.get_attrs())),\n            ctx,\n        ),\n        default_slots,\n    );\n    if let Some(doc) = doc {\n        impl_builder = impl_builder.doc(doc);\n    }\n\n    let enum_into_pyobject_impl = {\n        let match_arms = variants\n            .iter()\n            .map(|variant| {\n                let variant_ident = variant.get_ident();\n                let variant_cls = gen_complex_enum_variant_class_ident(cls, variant.get_ident());\n                quote! {\n                    #cls::#variant_ident { .. } => {\n                        let pyclass_init = <#pyo3_path::PyClassInitializer<Self> as ::std::convert::From<Self>>::from(self).add_subclass(#variant_cls);\n                        unsafe { #pyo3_path::Bound::new(py, pyclass_init).map(|b| b.cast_into_unchecked()) }\n                    }\n                }\n            });\n        let output_type = get_conversion_type_hint(ctx, &format_ident!(\"OUTPUT_TYPE\"), cls);\n        quote! {\n            impl<'py> #pyo3_path::conversion::IntoPyObject<'py> for #cls {\n                type Target = Self;\n                type Output = #pyo3_path::Bound<'py, <Self as #pyo3_path::conversion::IntoPyObject<'py>>::Target>;\n                type Error = #pyo3_path::PyErr;\n                #output_type\n\n                fn into_pyobject(self, py: #pyo3_path::Python<'py>) -> ::std::result::Result<\n                    <Self as #pyo3_path::conversion::IntoPyObject>::Output,\n                    <Self as #pyo3_path::conversion::IntoPyObject>::Error,\n                > {\n                    match self {\n                        #(#match_arms)*\n                    }\n                }\n            }\n        }\n    };\n\n    let pyclass_impls: TokenStream = [\n        impl_builder.impl_pyclass(ctx),\n        enum_into_pyobject_impl,\n        impl_builder.impl_pyclassimpl(ctx)?,\n        impl_builder.impl_add_to_module(ctx),\n        impl_builder.impl_freelist(ctx),\n        impl_builder.impl_introspection(ctx, None),\n    ]\n    .into_iter()\n    .collect();\n\n    let mut variant_cls_zsts = vec![];\n    let mut variant_cls_pytypeinfos = vec![];\n    let mut variant_cls_pyclass_impls = vec![];\n    let mut variant_cls_impls = vec![];\n    for variant in variants {\n        let variant_name = variant.get_ident().clone();\n        let variant_cls = gen_complex_enum_variant_class_ident(cls, &variant_name);\n\n        let variant_cls_zst = quote! {\n            #[doc(hidden)]\n            #[allow(non_camel_case_types)]\n            struct #variant_cls;\n        };\n        variant_cls_zsts.push(variant_cls_zst);\n\n        let variant_args = PyClassArgs {\n            class_kind: PyClassKind::Struct,\n            // TODO(mkovaxx): propagate variant.options\n            options: {\n                let mut rigged_options: PyClassPyO3Options = parse_quote!(extends = #cls, frozen);\n                // If a specific module was given to the base class, use it for all variants.\n                rigged_options.module.clone_from(&args.options.module);\n                rigged_options\n            },\n        };\n\n        let variant_cls_pytypeinfo = impl_pytypeinfo(&variant_cls, &variant_args, ctx);\n        variant_cls_pytypeinfos.push(variant_cls_pytypeinfo);\n\n        let (variant_cls_impl, field_getters, mut slots) =\n            impl_complex_enum_variant_cls(cls, &args, &variant, ctx)?;\n        variant_cls_impls.push(variant_cls_impl);\n\n        let variant_doc = get_doc(variant.get_attrs(), None);\n        let variant_new = complex_enum_variant_new(cls, variant, ctx)?;\n        slots.push(variant_new);\n\n        let mut impl_builder = PyClassImplsBuilder::new(\n            &variant_cls,\n            &variant_name,\n            &variant_args,\n            methods_type,\n            field_getters,\n            slots,\n        );\n        if let Some(doc) = variant_doc {\n            impl_builder = impl_builder.doc(doc);\n        }\n\n        let pyclass_impl: TokenStream = [\n            impl_builder.impl_pyclass(ctx),\n            impl_builder.impl_into_py(ctx),\n            impl_builder.impl_pyclassimpl(ctx)?,\n            impl_builder.impl_add_to_module(ctx),\n            impl_builder.impl_freelist(ctx),\n            impl_builder.impl_introspection(ctx, Some(cls)),\n        ]\n        .into_iter()\n        .collect();\n\n        variant_cls_pyclass_impls.push(pyclass_impl);\n    }\n\n    Ok(quote! {\n        #pytypeinfo\n\n        #pyclass_impls\n\n        #[doc(hidden)]\n        #[allow(non_snake_case)]\n        impl #cls {\n            #default_richcmp\n            #default_hash\n            #default_str\n        }\n\n        #(#variant_cls_zsts)*\n\n        #(#variant_cls_pytypeinfos)*\n\n        #(#variant_cls_pyclass_impls)*\n\n        #(#variant_cls_impls)*\n    })\n}\n\nfn impl_complex_enum_variant_cls(\n    enum_name: &syn::Ident,\n    args: &PyClassArgs,\n    variant: &PyClassEnumVariant<'_>,\n    ctx: &Ctx,\n) -> Result<(TokenStream, Vec<MethodAndMethodDef>, Vec<MethodAndSlotDef>)> {\n    match variant {\n        PyClassEnumVariant::Struct(struct_variant) => {\n            impl_complex_enum_struct_variant_cls(enum_name, args, struct_variant, ctx)\n        }\n        PyClassEnumVariant::Tuple(tuple_variant) => {\n            impl_complex_enum_tuple_variant_cls(enum_name, args, tuple_variant, ctx)\n        }\n    }\n}\n\nfn impl_complex_enum_variant_match_args(\n    ctx @ Ctx { pyo3_path, .. }: &Ctx,\n    variant_cls_type: &syn::Type,\n    field_names: &[Ident],\n) -> syn::Result<(MethodAndMethodDef, syn::ImplItemFn)> {\n    let ident = format_ident!(\"__match_args__\");\n    let field_names_unraw = field_names.iter().map(|name| name.unraw());\n    let mut match_args_impl: syn::ImplItemFn = {\n        parse_quote! {\n            #[classattr]\n            fn #ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::Bound<'_, #pyo3_path::types::PyTuple>> {\n                #pyo3_path::types::PyTuple::new::<&str, _>(py, [\n                    #(stringify!(#field_names_unraw),)*\n                ])\n            }\n        }\n    };\n\n    let spec = FnSpec::parse(\n        &mut match_args_impl.sig,\n        &mut match_args_impl.attrs,\n        Default::default(),\n    )?;\n    #[cfg_attr(not(feature = \"experimental-inspect\"), allow(unused_mut))]\n    let mut variant_match_args = impl_py_class_attribute(variant_cls_type, &spec, ctx)?;\n    #[cfg(feature = \"experimental-inspect\")]\n    variant_match_args.add_introspection(attribute_introspection_code(\n        pyo3_path,\n        Some(variant_cls_type),\n        \"__match_args__\".into(),\n        PyExpr::tuple(\n            field_names\n                .iter()\n                .map(|name| PyExpr::str_constant(name.unraw().to_string())),\n        ),\n        syn::Type::Tuple(syn::TypeTuple {\n            paren_token: syn::token::Paren::default(),\n            elems: field_names\n                .iter()\n                .map(|_| {\n                    let t: syn::Type = parse_quote!(&'static str);\n                    t\n                })\n                .collect(),\n        }),\n        None,\n        true,\n    ));\n    Ok((variant_match_args, match_args_impl))\n}\n\nfn impl_complex_enum_struct_variant_cls(\n    enum_name: &syn::Ident,\n    args: &PyClassArgs,\n    variant: &PyClassEnumStructVariant<'_>,\n    ctx: &Ctx,\n) -> Result<(TokenStream, Vec<MethodAndMethodDef>, Vec<MethodAndSlotDef>)> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let variant_ident = &variant.ident;\n    let variant_cls = gen_complex_enum_variant_class_ident(enum_name, variant.ident);\n    let variant_cls_type = parse_quote!(#variant_cls);\n\n    let mut field_names: Vec<Ident> = vec![];\n    let mut fields_with_types: Vec<TokenStream> = vec![];\n    let mut field_getters = vec![];\n    let mut field_getter_impls: Vec<TokenStream> = vec![];\n    for field in &variant.fields {\n        let field_name = field.ident;\n        let field_type = field.ty;\n        let field_with_type = quote! { #field_name: #field_type };\n\n        let field_getter = complex_enum_variant_field_getter(\n            &variant_cls_type,\n            field_name,\n            field_type,\n            field.attrs,\n            field.span,\n            ctx,\n        )?;\n\n        let field_getter_impl = quote! {\n            fn #field_name(slf: #pyo3_path::PyClassGuard<'_, Self>, py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::Py<#pyo3_path::PyAny>> {\n                #[allow(unused_imports)]\n                use #pyo3_path::impl_::pyclass::Probe as _;\n                match &*slf.into_super() {\n                    #enum_name::#variant_ident { #field_name, .. } =>\n                        #pyo3_path::impl_::pyclass::ConvertField::<\n                            { #pyo3_path::impl_::pyclass::IsIntoPyObjectRef::<#field_type>::VALUE },\n                            { #pyo3_path::impl_::pyclass::IsIntoPyObject::<#field_type>::VALUE },\n                        >::convert_field::<#field_type>(#field_name, py),\n                    _ => ::core::unreachable!(\"Wrong complex enum variant found in variant wrapper PyClass\"),\n                }\n            }\n        };\n\n        field_names.push(field_name.clone());\n        fields_with_types.push(field_with_type);\n        field_getters.push(field_getter);\n        field_getter_impls.push(field_getter_impl);\n    }\n\n    let (qualname, qualname_impl) = impl_complex_enum_variant_qualname(\n        &get_class_python_name(enum_name, args),\n        &variant.python_name(),\n        &variant_cls_type,\n        ctx,\n    )?;\n\n    field_getters.push(qualname);\n\n    let (variant_match_args, match_args_const_impl) =\n        impl_complex_enum_variant_match_args(ctx, &variant_cls_type, &field_names)?;\n\n    field_getters.push(variant_match_args);\n\n    let cls_impl = quote! {\n        #[doc(hidden)]\n        #[allow(non_snake_case)]\n        impl #variant_cls {\n            #[allow(clippy::too_many_arguments)]\n            fn __pymethod_constructor__(py: #pyo3_path::Python<'_>, #(#fields_with_types,)*) -> #pyo3_path::PyClassInitializer<#variant_cls> {\n                let base_value = #enum_name::#variant_ident { #(#field_names,)* };\n                <#pyo3_path::PyClassInitializer<#enum_name> as ::std::convert::From<#enum_name>>::from(base_value).add_subclass(#variant_cls)\n            }\n\n            #match_args_const_impl\n\n            #qualname_impl\n\n            #(#field_getter_impls)*\n        }\n    };\n\n    Ok((cls_impl, field_getters, Vec::new()))\n}\n\nfn impl_complex_enum_tuple_variant_field_getters(\n    ctx: &Ctx,\n    variant: &PyClassEnumTupleVariant<'_>,\n    enum_name: &syn::Ident,\n    variant_cls_type: &syn::Type,\n    variant_ident: &&Ident,\n    field_names: &mut Vec<Ident>,\n    fields_types: &mut Vec<syn::Type>,\n) -> Result<(Vec<MethodAndMethodDef>, Vec<syn::ImplItemFn>)> {\n    let Ctx { pyo3_path, .. } = ctx;\n\n    let mut field_getters = vec![];\n    let mut field_getter_impls = vec![];\n\n    for (index, field) in variant.fields.iter().enumerate() {\n        let field_name = format_ident!(\"_{}\", index);\n        let field_type = field.ty;\n\n        let field_getter = complex_enum_variant_field_getter(\n            variant_cls_type,\n            &field_name,\n            field_type,\n            field.attrs,\n            field.span,\n            ctx,\n        )?;\n\n        // Generate the match arms needed to destructure the tuple and access the specific field\n        let field_access_tokens: Vec<_> = (0..variant.fields.len())\n            .map(|i| {\n                if i == index {\n                    quote! { val }\n                } else {\n                    quote! { _ }\n                }\n            })\n            .collect();\n        let field_getter_impl: syn::ImplItemFn = parse_quote! {\n            fn #field_name(slf: #pyo3_path::PyClassGuard<'_, Self>, py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::Py<#pyo3_path::PyAny>> {\n                #[allow(unused_imports)]\n                use #pyo3_path::impl_::pyclass::Probe as _;\n                match &*slf.into_super() {\n                    #enum_name::#variant_ident ( #(#field_access_tokens), *) =>\n                        #pyo3_path::impl_::pyclass::ConvertField::<\n                            { #pyo3_path::impl_::pyclass::IsIntoPyObjectRef::<#field_type>::VALUE },\n                            { #pyo3_path::impl_::pyclass::IsIntoPyObject::<#field_type>::VALUE },\n                        >::convert_field::<#field_type>(val, py),\n                    _ => ::core::unreachable!(\"Wrong complex enum variant found in variant wrapper PyClass\"),\n                }\n            }\n        };\n\n        field_names.push(field_name);\n        fields_types.push(field_type.clone());\n        field_getters.push(field_getter);\n        field_getter_impls.push(field_getter_impl);\n    }\n\n    Ok((field_getters, field_getter_impls))\n}\n\nfn impl_complex_enum_tuple_variant_len(\n    ctx: &Ctx,\n\n    variant_cls_type: &syn::Type,\n    num_fields: usize,\n) -> Result<(MethodAndSlotDef, syn::ImplItemFn)> {\n    let Ctx { pyo3_path, .. } = ctx;\n\n    let mut len_method_impl: syn::ImplItemFn = parse_quote! {\n        fn __len__(slf: #pyo3_path::PyClassGuard<'_, Self>) -> #pyo3_path::PyResult<usize> {\n            ::std::result::Result::Ok(#num_fields)\n        }\n    };\n\n    let variant_len = generate_default_protocol_slot(\n        variant_cls_type,\n        &mut len_method_impl,\n        &__LEN__,\n        #[cfg(feature = \"experimental-inspect\")]\n        FunctionIntrospectionData {\n            names: &[\"__len__\"],\n            arguments: Vec::new(),\n            returns: parse_quote! { ::std::primitive::usize },\n            is_returning_not_implemented_on_extraction_error: false,\n        },\n        ctx,\n    )?;\n\n    Ok((variant_len, len_method_impl))\n}\n\nfn impl_complex_enum_tuple_variant_getitem(\n    ctx: &Ctx,\n    variant_cls: &syn::Ident,\n    variant_cls_type: &syn::Type,\n    num_fields: usize,\n) -> Result<(MethodAndSlotDef, syn::ImplItemFn)> {\n    let Ctx { pyo3_path, .. } = ctx;\n\n    let match_arms: Vec<_> = (0..num_fields)\n        .map(|i| {\n            let field_access = format_ident!(\"_{}\", i);\n            quote! { #i =>\n                #pyo3_path::IntoPyObjectExt::into_py_any(#variant_cls::#field_access(slf, py)?, py)\n            }\n        })\n        .collect();\n\n    let mut get_item_method_impl: syn::ImplItemFn = parse_quote! {\n        fn __getitem__(slf: #pyo3_path::PyClassGuard<'_, Self>, py: #pyo3_path::Python<'_>, idx: usize) -> #pyo3_path::PyResult< #pyo3_path::Py<#pyo3_path::PyAny>> {\n            match idx {\n                #( #match_arms, )*\n                _ => ::std::result::Result::Err(#pyo3_path::exceptions::PyIndexError::new_err(\"tuple index out of range\")),\n            }\n        }\n    };\n\n    let variant_getitem = generate_default_protocol_slot(\n        variant_cls_type,\n        &mut get_item_method_impl,\n        &__GETITEM__,\n        #[cfg(feature = \"experimental-inspect\")]\n        FunctionIntrospectionData {\n            names: &[\"__getitem__\"],\n            arguments: vec![FnArg::Regular(RegularArg {\n                name: Cow::Owned(Ident::new(\"key\", variant_cls.span())),\n                ty: &parse_quote! { ::std::primitive::usize },\n                from_py_with: None,\n                default_value: None,\n                option_wrapped_type: None,\n                annotation: None,\n            })],\n            returns: parse_quote! { #pyo3_path::Py<#pyo3_path::PyAny> }, // TODO: figure out correct type\n            is_returning_not_implemented_on_extraction_error: false,\n        },\n        ctx,\n    )?;\n\n    Ok((variant_getitem, get_item_method_impl))\n}\n\nfn impl_complex_enum_tuple_variant_cls(\n    enum_name: &syn::Ident,\n    args: &PyClassArgs,\n    variant: &PyClassEnumTupleVariant<'_>,\n    ctx: &Ctx,\n) -> Result<(TokenStream, Vec<MethodAndMethodDef>, Vec<MethodAndSlotDef>)> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let variant_ident = &variant.ident;\n    let variant_cls = gen_complex_enum_variant_class_ident(enum_name, variant.ident);\n    let variant_cls_type = parse_quote!(#variant_cls);\n\n    let mut slots = vec![];\n\n    // represents the index of the field\n    let mut field_names: Vec<Ident> = vec![];\n    let mut field_types: Vec<syn::Type> = vec![];\n\n    let (mut field_getters, field_getter_impls) = impl_complex_enum_tuple_variant_field_getters(\n        ctx,\n        variant,\n        enum_name,\n        &variant_cls_type,\n        variant_ident,\n        &mut field_names,\n        &mut field_types,\n    )?;\n\n    let (qualname, qualname_impl) = impl_complex_enum_variant_qualname(\n        &get_class_python_name(enum_name, args),\n        &variant.python_name(),\n        &variant_cls_type,\n        ctx,\n    )?;\n\n    field_getters.push(qualname);\n\n    let num_fields = variant.fields.len();\n\n    let (variant_len, len_method_impl) =\n        impl_complex_enum_tuple_variant_len(ctx, &variant_cls_type, num_fields)?;\n\n    slots.push(variant_len);\n\n    let (variant_getitem, getitem_method_impl) =\n        impl_complex_enum_tuple_variant_getitem(ctx, &variant_cls, &variant_cls_type, num_fields)?;\n\n    slots.push(variant_getitem);\n\n    let (variant_match_args, match_args_method_impl) =\n        impl_complex_enum_variant_match_args(ctx, &variant_cls_type, &field_names)?;\n\n    field_getters.push(variant_match_args);\n\n    let cls_impl = quote! {\n        #[doc(hidden)]\n        #[allow(non_snake_case)]\n        impl #variant_cls {\n            #[allow(clippy::too_many_arguments)]\n            fn __pymethod_constructor__(py: #pyo3_path::Python<'_>, #(#field_names : #field_types,)*) -> #pyo3_path::PyClassInitializer<#variant_cls> {\n                let base_value = #enum_name::#variant_ident ( #(#field_names,)* );\n                <#pyo3_path::PyClassInitializer<#enum_name> as ::std::convert::From<#enum_name>>::from(base_value).add_subclass(#variant_cls)\n            }\n\n            #len_method_impl\n\n            #getitem_method_impl\n\n            #match_args_method_impl\n\n            #qualname_impl\n\n            #(#field_getter_impls)*\n        }\n    };\n\n    Ok((cls_impl, field_getters, slots))\n}\n\nfn gen_complex_enum_variant_class_ident(enum_: &Ident, variant: &Ident) -> Ident {\n    format_ident!(\"{}_{}\", enum_, variant)\n}\n\nfn impl_complex_enum_variant_qualname(\n    enum_name: &syn::Ident,\n    variant_ident: &syn::Ident,\n    variant_cls_type: &syn::Type,\n    ctx: &Ctx,\n) -> syn::Result<(MethodAndMethodDef, syn::ImplItemFn)> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let qualname = format!(\"{}.{}\", enum_name, variant_ident);\n    let mut qualname_impl: syn::ImplItemFn = {\n        parse_quote! {\n            #[classattr]\n            fn __qualname__(py: #pyo3_path::Python<'_>) -> &'static str {\n                #qualname\n            }\n        }\n    };\n\n    let spec = FnSpec::parse(\n        &mut qualname_impl.sig,\n        &mut qualname_impl.attrs,\n        Default::default(),\n    )?;\n\n    // NB: Deliberately add no introspection here, this is __qualname__\n    let qualname = impl_py_class_attribute(variant_cls_type, &spec, ctx)?;\n    Ok((qualname, qualname_impl))\n}\n\n#[cfg(feature = \"experimental-inspect\")]\nstruct FunctionIntrospectionData<'a> {\n    names: &'a [&'a str],\n    arguments: Vec<FnArg<'a>>,\n    is_returning_not_implemented_on_extraction_error: bool,\n    returns: syn::Type,\n}\n\n#[cfg(feature = \"experimental-inspect\")]\nimpl FunctionIntrospectionData<'_> {\n    fn generate(self, ctx: &Ctx, cls: &syn::Type) -> TokenStream {\n        let signature = FunctionSignature::from_arguments(self.arguments);\n        let returns = self.returns;\n        self.names\n            .iter()\n            .flat_map(|name| {\n                function_introspection_code(\n                    &ctx.pyo3_path,\n                    None,\n                    name,\n                    &signature,\n                    Some(\"self\"),\n                    parse_quote!(-> #returns),\n                    [],\n                    false,\n                    self.is_returning_not_implemented_on_extraction_error,\n                    None,\n                    Some(cls),\n                )\n            })\n            .collect()\n    }\n}\n\nfn generate_protocol_slot(\n    cls: &syn::Type,\n    method: &mut syn::ImplItemFn,\n    slot: &SlotDef,\n    name: &str,\n    #[cfg(feature = \"experimental-inspect\")] introspection_data: FunctionIntrospectionData<'_>,\n    ctx: &Ctx,\n) -> syn::Result<MethodAndSlotDef> {\n    let spec = FnSpec::parse(\n        &mut method.sig,\n        &mut method.attrs,\n        PyFunctionOptions::default(),\n    )?;\n    #[cfg_attr(not(feature = \"experimental-inspect\"), allow(unused_mut))]\n    let mut def = slot.generate_type_slot(cls, &spec, name, ctx)?;\n    #[cfg(feature = \"experimental-inspect\")]\n    def.add_introspection(introspection_data.generate(ctx, cls));\n    Ok(def)\n}\n\nfn generate_default_protocol_slot(\n    cls: &syn::Type,\n    method: &mut syn::ImplItemFn,\n    slot: &SlotDef,\n    #[cfg(feature = \"experimental-inspect\")] introspection_data: FunctionIntrospectionData<'_>,\n    ctx: &Ctx,\n) -> syn::Result<MethodAndSlotDef> {\n    let spec = FnSpec::parse(\n        &mut method.sig,\n        &mut Vec::new(),\n        PyFunctionOptions::default(),\n    )?;\n    let name = spec.name.to_string();\n    #[cfg_attr(not(feature = \"experimental-inspect\"), allow(unused_mut))]\n    let mut def = slot.generate_type_slot(\n        &syn::parse_quote!(#cls),\n        &spec,\n        &format!(\"__default_{name}__\"),\n        ctx,\n    )?;\n    #[cfg(feature = \"experimental-inspect\")]\n    def.add_introspection(introspection_data.generate(ctx, cls));\n    Ok(def)\n}\n\nfn simple_enum_default_methods<'a>(\n    cls: &'a syn::Ident,\n    unit_variant_names: impl IntoIterator<\n        Item = (&'a syn::Ident, Cow<'a, syn::Ident>, &'a [syn::Attribute]),\n    >,\n    ctx: &Ctx,\n) -> Vec<MethodAndMethodDef> {\n    let cls_type: syn::Type = syn::parse_quote!(#cls);\n    unit_variant_names\n        .into_iter()\n        .map(|(var, py_name, attrs)| {\n            let spec = ConstSpec {\n                rust_ident: var.clone(),\n                attributes: ConstAttributes {\n                    is_class_attr: true,\n                    name: Some(NameAttribute {\n                        kw: syn::parse_quote! { name },\n                        value: NameLitStr(py_name.into_owned()),\n                    }),\n                },\n                #[cfg(feature = \"experimental-inspect\")]\n                expr: None,\n                #[cfg(feature = \"experimental-inspect\")]\n                ty: cls_type.clone(),\n                #[cfg(feature = \"experimental-inspect\")]\n                doc: get_doc(attrs, None),\n            };\n            let method = gen_py_const(&cls_type, &spec, ctx);\n            let associated_method_tokens = method.associated_method;\n            let method_def_tokens = method.method_def;\n            let cfg_attrs = get_cfg_attributes(attrs);\n\n            let associated_method = quote! {\n                #(#cfg_attrs)*\n                #associated_method_tokens\n            };\n            let method_def = quote! {\n                #(#cfg_attrs)*\n                #method_def_tokens\n            };\n\n            MethodAndMethodDef {\n                associated_method,\n                method_def,\n            }\n        })\n        .collect()\n}\n\n#[cfg_attr(not(feature = \"experimental-inspect\"), expect(unused_variables))]\nfn complex_enum_default_methods<'a>(\n    cls: &'a Ident,\n    variant_names: impl IntoIterator<Item = (&'a Ident, Cow<'a, Ident>, &'a [syn::Attribute])>,\n    ctx: &Ctx,\n) -> Vec<MethodAndMethodDef> {\n    let cls_type = syn::parse_quote!(#cls);\n    variant_names\n        .into_iter()\n        .map(|(var, py_name, attrs)| {\n            #[cfg(feature = \"experimental-inspect\")]\n            let variant_cls = gen_complex_enum_variant_class_ident(cls, &py_name);\n            let spec = ConstSpec {\n                rust_ident: var.clone(),\n                attributes: ConstAttributes {\n                    is_class_attr: true,\n                    name: Some(NameAttribute {\n                        kw: syn::parse_quote! { name },\n                        value: NameLitStr(py_name.into_owned()),\n                    }),\n                },\n                #[cfg(feature = \"experimental-inspect\")]\n                expr: None,\n                #[cfg(feature = \"experimental-inspect\")]\n                ty: parse_quote!(#variant_cls),\n                #[cfg(feature = \"experimental-inspect\")]\n                doc: get_doc(attrs, None),\n            };\n            gen_complex_enum_variant_attr(cls, &cls_type, &spec, ctx)\n        })\n        .collect()\n}\n\npub fn gen_complex_enum_variant_attr(\n    cls: &syn::Ident,\n    cls_type: &syn::Type,\n    spec: &ConstSpec,\n    ctx: &Ctx,\n) -> MethodAndMethodDef {\n    let Ctx { pyo3_path, .. } = ctx;\n    let member = &spec.rust_ident;\n    let wrapper_ident = format_ident!(\"__pymethod_variant_cls_{}__\", member);\n    let python_name = spec.null_terminated_python_name();\n\n    let variant_cls = gen_complex_enum_variant_class_ident(cls, member);\n    let associated_method = quote! {\n        fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::Py<#pyo3_path::PyAny>> {\n            ::std::result::Result::Ok(py.get_type::<#variant_cls>().into_any().unbind())\n        }\n    };\n\n    let method_def = quote! {\n        #pyo3_path::impl_::pymethods::PyMethodDefType::ClassAttribute({\n            #pyo3_path::impl_::pymethods::PyClassAttributeDef::new(\n                #python_name,\n                #cls_type::#wrapper_ident\n            )\n        })\n    };\n\n    MethodAndMethodDef {\n        associated_method,\n        method_def,\n    }\n}\n\nfn complex_enum_variant_new<'a>(\n    cls: &'a syn::Ident,\n    variant: PyClassEnumVariant<'a>,\n    ctx: &Ctx,\n) -> Result<MethodAndSlotDef> {\n    match variant {\n        PyClassEnumVariant::Struct(struct_variant) => {\n            complex_enum_struct_variant_new(cls, struct_variant, ctx)\n        }\n        PyClassEnumVariant::Tuple(tuple_variant) => {\n            complex_enum_tuple_variant_new(cls, tuple_variant, ctx)\n        }\n    }\n}\n\nfn complex_enum_struct_variant_new<'a>(\n    cls: &'a syn::Ident,\n    variant: PyClassEnumStructVariant<'a>,\n    ctx: &Ctx,\n) -> Result<MethodAndSlotDef> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let variant_cls = gen_complex_enum_variant_class_ident(cls, variant.ident);\n    let variant_cls_type: syn::Type = parse_quote!(#variant_cls);\n\n    let arg_py_ident: syn::Ident = parse_quote!(py);\n    let arg_py_type: syn::Type = parse_quote!(#pyo3_path::Python<'_>);\n\n    let args = {\n        let mut args = vec![\n            // py: Python<'_>\n            FnArg::Py(PyArg {\n                name: &arg_py_ident,\n                ty: &arg_py_type,\n            }),\n        ];\n\n        for field in &variant.fields {\n            args.push(FnArg::Regular(RegularArg {\n                name: Cow::Borrowed(field.ident),\n                ty: field.ty,\n                from_py_with: None,\n                default_value: None,\n                option_wrapped_type: None,\n                #[cfg(feature = \"experimental-inspect\")]\n                annotation: None,\n            }));\n        }\n        args\n    };\n\n    let signature = if let Some(constructor) = variant.options.constructor {\n        FunctionSignature::from_arguments_and_attribute(args, constructor.into_signature())?\n    } else {\n        FunctionSignature::from_arguments(args)\n    };\n\n    let spec = FnSpec {\n        tp: crate::method::FnType::FnStatic,\n        name: &format_ident!(\"__pymethod_constructor__\"),\n        python_name: format_ident!(\"__new__\"),\n        signature,\n        text_signature: None,\n        asyncness: None,\n        unsafety: None,\n        warnings: vec![],\n        output: syn::ReturnType::Default,\n    };\n\n    #[cfg_attr(not(feature = \"experimental-inspect\"), allow(unused_mut))]\n    let mut def =\n        __NEW__.generate_type_slot(&variant_cls_type, &spec, \"__default___new____\", ctx)?;\n    #[cfg(feature = \"experimental-inspect\")]\n    def.add_introspection(method_introspection_code(\n        &spec,\n        &[],\n        &variant_cls_type,\n        false,\n        ctx,\n    ));\n    Ok(def)\n}\n\nfn complex_enum_tuple_variant_new<'a>(\n    cls: &'a syn::Ident,\n    variant: PyClassEnumTupleVariant<'a>,\n    ctx: &Ctx,\n) -> Result<MethodAndSlotDef> {\n    let Ctx { pyo3_path, .. } = ctx;\n\n    let variant_cls = gen_complex_enum_variant_class_ident(cls, variant.ident);\n    let variant_cls_type: syn::Type = parse_quote!(#variant_cls);\n\n    let arg_py_ident: syn::Ident = parse_quote!(py);\n    let arg_py_type: syn::Type = parse_quote!(#pyo3_path::Python<'_>);\n\n    let args = {\n        let mut args = vec![FnArg::Py(PyArg {\n            name: &arg_py_ident,\n            ty: &arg_py_type,\n        })];\n\n        for (i, field) in variant.fields.iter().enumerate() {\n            args.push(FnArg::Regular(RegularArg {\n                name: std::borrow::Cow::Owned(format_ident!(\"_{}\", i)),\n                ty: field.ty,\n                from_py_with: None,\n                default_value: None,\n                option_wrapped_type: None,\n                #[cfg(feature = \"experimental-inspect\")]\n                annotation: None,\n            }));\n        }\n        args\n    };\n\n    let signature = if let Some(constructor) = variant.options.constructor {\n        FunctionSignature::from_arguments_and_attribute(args, constructor.into_signature())?\n    } else {\n        FunctionSignature::from_arguments(args)\n    };\n\n    let spec = FnSpec {\n        tp: crate::method::FnType::FnStatic,\n        name: &format_ident!(\"__pymethod_constructor__\"),\n        python_name: format_ident!(\"__new__\"),\n        signature,\n        text_signature: None,\n        asyncness: None,\n        unsafety: None,\n        warnings: vec![],\n        output: syn::ReturnType::Default,\n    };\n\n    #[cfg_attr(not(feature = \"experimental-inspect\"), allow(unused_mut))]\n    let mut def =\n        __NEW__.generate_type_slot(&variant_cls_type, &spec, \"__default___new____\", ctx)?;\n    #[cfg(feature = \"experimental-inspect\")]\n    def.add_introspection(method_introspection_code(\n        &spec,\n        &[],\n        &variant_cls_type,\n        false,\n        ctx,\n    ));\n    Ok(def)\n}\n\nfn complex_enum_variant_field_getter(\n    variant_cls_type: &syn::Type,\n    field_name: &Ident,\n    field_type: &syn::Type,\n    field_attrs: &[syn::Attribute],\n    field_span: Span,\n    ctx: &Ctx,\n) -> Result<MethodAndMethodDef> {\n    let mut arg = parse_quote!(py: Python<'_>);\n    let py = FnArg::parse(&mut arg)?;\n    let signature = FunctionSignature::from_arguments(vec![py]);\n\n    let self_type = crate::method::SelfType::TryFromBoundRef {\n        span: field_span,\n        non_null: true,\n    };\n\n    let spec = FnSpec {\n        tp: crate::method::FnType::Getter(self_type.clone()),\n        name: field_name,\n        python_name: field_name.unraw(),\n        signature,\n        text_signature: None,\n        asyncness: None,\n        unsafety: None,\n        warnings: vec![],\n        output: parse_quote!(-> #field_type),\n    };\n\n    let property_type = PropertyType::Function {\n        self_type: &self_type,\n        spec: &spec,\n        doc: get_doc(field_attrs, None),\n    };\n\n    #[cfg_attr(not(feature = \"experimental-inspect\"), allow(unused_mut))]\n    let mut getter = impl_py_getter_def(variant_cls_type, property_type, ctx)?;\n    #[cfg(feature = \"experimental-inspect\")]\n    getter.add_introspection(method_introspection_code(\n        &spec,\n        field_attrs,\n        variant_cls_type,\n        false,\n        ctx,\n    ));\n    Ok(getter)\n}\n\nfn descriptors_to_items(\n    cls: &Ident,\n    rename_all: Option<&RenameAllAttribute>,\n    frozen: Option<frozen>,\n    field_options: Vec<(&syn::Field, FieldPyO3Options)>,\n    ctx: &Ctx,\n) -> Result<Vec<MethodAndMethodDef>> {\n    let ty = syn::parse_quote!(#cls);\n    let mut items = Vec::new();\n    for (field_index, (field, options)) in field_options.into_iter().enumerate() {\n        if let FieldPyO3Options {\n            name: Some(name),\n            get: None,\n            set: None,\n        } = options\n        {\n            return Err(syn::Error::new_spanned(name, USELESS_NAME));\n        }\n\n        if options.get.is_some() {\n            let renaming_rule = rename_all.map(|rename_all| rename_all.value.rule);\n            #[cfg_attr(not(feature = \"experimental-inspect\"), allow(unused_mut))]\n            let mut getter = impl_py_getter_def(\n                &ty,\n                PropertyType::Descriptor {\n                    field_index,\n                    field,\n                    python_name: options.name.as_ref(),\n                    renaming_rule,\n                },\n                ctx,\n            )?;\n            #[cfg(feature = \"experimental-inspect\")]\n            {\n                // We generate introspection data\n                let return_type = &field.ty;\n                getter.add_introspection(function_introspection_code(\n                    &ctx.pyo3_path,\n                    None,\n                    &field_python_name(field, options.name.as_ref(), renaming_rule)?,\n                    &FunctionSignature::from_arguments(vec![]),\n                    Some(\"self\"),\n                    parse_quote!(-> #return_type),\n                    vec![PyExpr::builtin(\"property\")],\n                    false,\n                    false,\n                    utils::get_doc(&field.attrs, None).as_ref(),\n                    Some(&parse_quote!(#cls)),\n                ));\n            }\n            items.push(getter);\n        }\n\n        if let Some(set) = options.set {\n            ensure_spanned!(frozen.is_none(), set.span() => \"cannot use `#[pyo3(set)]` on a `frozen` class\");\n            let renaming_rule = rename_all.map(|rename_all| rename_all.value.rule);\n            #[cfg_attr(not(feature = \"experimental-inspect\"), allow(unused_mut))]\n            let mut setter = impl_py_setter_def(\n                &ty,\n                PropertyType::Descriptor {\n                    field_index,\n                    field,\n                    python_name: options.name.as_ref(),\n                    renaming_rule,\n                },\n                ctx,\n            )?;\n            #[cfg(feature = \"experimental-inspect\")]\n            {\n                // We generate introspection data\n                let name = field_python_name(field, options.name.as_ref(), renaming_rule)?;\n                setter.add_introspection(function_introspection_code(\n                    &ctx.pyo3_path,\n                    None,\n                    &name,\n                    &FunctionSignature::from_arguments(vec![FnArg::Regular(RegularArg {\n                        name: Cow::Owned(format_ident!(\"value\")),\n                        ty: &field.ty,\n                        from_py_with: None,\n                        default_value: None,\n                        option_wrapped_type: None,\n                        annotation: None,\n                    })]),\n                    Some(\"self\"),\n                    syn::ReturnType::Default,\n                    vec![PyExpr::attribute(\n                        PyExpr::attribute(\n                            PyExpr::from_type(\n                                syn::TypePath {\n                                    qself: None,\n                                    path: cls.clone().into(),\n                                }\n                                .into(),\n                                None,\n                            ),\n                            name.clone(),\n                        ),\n                        \"setter\",\n                    )],\n                    false,\n                    false,\n                    get_doc(&field.attrs, None).as_ref(),\n                    Some(&parse_quote!(#cls)),\n                ));\n            }\n            items.push(setter);\n        };\n    }\n    Ok(items)\n}\n\nfn impl_pytypeinfo(cls: &Ident, attr: &PyClassArgs, ctx: &Ctx) -> TokenStream {\n    let Ctx { pyo3_path, .. } = ctx;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    let type_hint = {\n        let type_hint = get_class_type_hint(cls, attr, ctx);\n        quote! { const TYPE_HINT: #pyo3_path::inspect::PyStaticExpr = #type_hint; }\n    };\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    let type_hint = quote! {};\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    let _ = attr;\n\n    quote! {\n        unsafe impl #pyo3_path::type_object::PyTypeInfo for #cls {\n\n            const NAME: &str = <Self as #pyo3_path::PyClass>::NAME;\n            const MODULE: ::std::option::Option<&str> = <Self as #pyo3_path::impl_::pyclass::PyClassImpl>::MODULE;\n\n            #type_hint\n\n            #[inline]\n            fn type_object_raw(py: #pyo3_path::Python<'_>) -> *mut #pyo3_path::ffi::PyTypeObject {\n                use #pyo3_path::prelude::PyTypeMethods;\n                <#cls as #pyo3_path::impl_::pyclass::PyClassImpl>::lazy_type_object()\n                    .get_or_try_init(py)\n                    .unwrap_or_else(|e| #pyo3_path::impl_::pyclass::type_object_init_failed(\n                        py,\n                        e,\n                        <Self as #pyo3_path::PyClass>::NAME\n                    ))\n                    .as_type_ptr()\n            }\n        }\n    }\n}\n\nfn pyclass_richcmp_arms(\n    options: &PyClassPyO3Options,\n    ctx: &Ctx,\n) -> std::result::Result<TokenStream, syn::Error> {\n    let Ctx { pyo3_path, .. } = ctx;\n\n    let eq_arms = options\n        .eq\n        .map(|eq| eq.span)\n        .or(options.eq_int.map(|eq_int| eq_int.span))\n        .map(|span| {\n            quote_spanned! { span =>\n                #pyo3_path::pyclass::CompareOp::Eq => {\n                    #pyo3_path::IntoPyObjectExt::into_py_any(self_val == other, py)\n                },\n                #pyo3_path::pyclass::CompareOp::Ne => {\n                    #pyo3_path::IntoPyObjectExt::into_py_any(self_val != other, py)\n                },\n            }\n        })\n        .unwrap_or_default();\n\n    if let Some(ord) = options.ord {\n        ensure_spanned!(options.eq.is_some(), ord.span() => \"The `ord` option requires the `eq` option.\");\n    }\n\n    let ord_arms = options\n        .ord\n        .map(|ord| {\n            quote_spanned! { ord.span() =>\n                #pyo3_path::pyclass::CompareOp::Gt => {\n                    #pyo3_path::IntoPyObjectExt::into_py_any(self_val > other, py)\n                },\n                #pyo3_path::pyclass::CompareOp::Lt => {\n                    #pyo3_path::IntoPyObjectExt::into_py_any(self_val < other, py)\n                 },\n                #pyo3_path::pyclass::CompareOp::Le => {\n                    #pyo3_path::IntoPyObjectExt::into_py_any(self_val <= other, py)\n                 },\n                #pyo3_path::pyclass::CompareOp::Ge => {\n                    #pyo3_path::IntoPyObjectExt::into_py_any(self_val >= other, py)\n                 },\n            }\n        })\n        .unwrap_or_else(|| quote! { _ => ::std::result::Result::Ok(py.NotImplemented()) });\n\n    Ok(quote! {\n        #eq_arms\n        #ord_arms\n    })\n}\n\nfn pyclass_richcmp_simple_enum(\n    options: &PyClassPyO3Options,\n    cls: &syn::Type,\n    repr_type: &syn::Ident,\n    ctx: &Ctx,\n) -> Result<(Option<syn::ImplItemFn>, Option<MethodAndSlotDef>)> {\n    let Ctx { pyo3_path, .. } = ctx;\n    if let Some(eq_int) = options.eq_int {\n        ensure_spanned!(options.eq.is_some(), eq_int.span() => \"The `eq_int` option requires the `eq` option.\");\n    }\n\n    if options.eq.is_none() && options.eq_int.is_none() {\n        return Ok((None, None));\n    }\n\n    let arms = pyclass_richcmp_arms(options, ctx)?;\n\n    let eq = options.eq.map(|eq| {\n        quote_spanned! { eq.span() =>\n            let self_val = self;\n            if let ::std::result::Result::Ok(other) = other.cast::<Self>() {\n                let other = &*other.borrow();\n                return match op {\n                    #arms\n                }\n            }\n        }\n    });\n\n    let eq_int = options.eq_int.map(|eq_int| {\n        quote_spanned! { eq_int.span() =>\n            let self_val = self.__pyo3__int__();\n            if let ::std::result::Result::Ok(other) = #pyo3_path::types::PyAnyMethods::extract::<#repr_type>(other).or_else(|_| {\n                other.cast::<Self>().map(|o| o.borrow().__pyo3__int__())\n            }) {\n                return match op {\n                    #arms\n                }\n            }\n        }\n    });\n\n    let mut richcmp_impl = parse_quote! {\n        fn __pyo3__generated____richcmp__(\n            &self,\n            py: #pyo3_path::Python,\n            other: &#pyo3_path::Bound<'_, #pyo3_path::PyAny>,\n            op: #pyo3_path::pyclass::CompareOp\n        ) -> #pyo3_path::PyResult<#pyo3_path::Py<#pyo3_path::PyAny>> {\n            #eq\n\n            #eq_int\n\n            ::std::result::Result::Ok(py.NotImplemented())\n        }\n    };\n    #[cfg(feature = \"experimental-inspect\")]\n    let any = parse_quote!(#pyo3_path::Py<#pyo3_path::PyAny>);\n    #[cfg(feature = \"experimental-inspect\")]\n    let introspection = FunctionIntrospectionData {\n        names: &[\"__eq__\", \"__ne__\"],\n        arguments: vec![FnArg::Regular(RegularArg {\n            name: Cow::Owned(format_ident!(\"other\")),\n            ty: &any,\n            from_py_with: None,\n            default_value: None,\n            option_wrapped_type: None,\n            annotation: None,\n        })],\n        returns: parse_quote!(::std::primitive::bool),\n        is_returning_not_implemented_on_extraction_error: true,\n    };\n    let richcmp_slot = if options.eq.is_some() {\n        generate_protocol_slot(\n            cls,\n            &mut richcmp_impl,\n            &__RICHCMP__,\n            \"__richcmp__\",\n            #[cfg(feature = \"experimental-inspect\")]\n            introspection,\n            ctx,\n        )?\n    } else {\n        generate_default_protocol_slot(\n            cls,\n            &mut richcmp_impl,\n            &__RICHCMP__,\n            #[cfg(feature = \"experimental-inspect\")]\n            introspection,\n            ctx,\n        )?\n    };\n    Ok((Some(richcmp_impl), Some(richcmp_slot)))\n}\n\nfn pyclass_richcmp(\n    options: &PyClassPyO3Options,\n    cls: &syn::Type,\n    ctx: &Ctx,\n) -> Result<(Option<syn::ImplItemFn>, Option<MethodAndSlotDef>)> {\n    let Ctx { pyo3_path, .. } = ctx;\n    if let Some(eq_int) = options.eq_int {\n        bail_spanned!(eq_int.span() => \"`eq_int` can only be used on simple enums.\")\n    }\n\n    let arms = pyclass_richcmp_arms(options, ctx)?;\n    if options.eq.is_some() {\n        let mut richcmp_impl = parse_quote! {\n            fn __pyo3__generated____richcmp__(\n                &self,\n                py: #pyo3_path::Python,\n                other: &#pyo3_path::Bound<'_, #pyo3_path::PyAny>,\n                op: #pyo3_path::pyclass::CompareOp\n            ) -> #pyo3_path::PyResult<#pyo3_path::Py<#pyo3_path::PyAny>> {\n                let self_val = self;\n                if let ::std::result::Result::Ok(other) = other.cast::<Self>() {\n                    let other = &*other.borrow();\n                    match op {\n                        #arms\n                    }\n                } else {\n                    ::std::result::Result::Ok(py.NotImplemented())\n                }\n            }\n        };\n        let richcmp_slot = generate_protocol_slot(\n            cls,\n            &mut richcmp_impl,\n            &__RICHCMP__,\n            \"__richcmp__\",\n            #[cfg(feature = \"experimental-inspect\")]\n            FunctionIntrospectionData {\n                names: if options.ord.is_some() {\n                    &[\"__eq__\", \"__ne__\", \"__lt__\", \"__le__\", \"__gt__\", \"__ge__\"]\n                } else {\n                    &[\"__eq__\", \"__ne__\"]\n                },\n                arguments: vec![FnArg::Regular(RegularArg {\n                    name: Cow::Owned(format_ident!(\"other\")),\n                    ty: &parse_quote!(&#cls),\n                    from_py_with: None,\n                    default_value: None,\n                    option_wrapped_type: None,\n                    annotation: None,\n                })],\n                returns: parse_quote! { ::std::primitive::bool },\n                is_returning_not_implemented_on_extraction_error: true,\n            },\n            ctx,\n        )?;\n        Ok((Some(richcmp_impl), Some(richcmp_slot)))\n    } else {\n        Ok((None, None))\n    }\n}\n\nfn pyclass_hash(\n    options: &PyClassPyO3Options,\n    cls: &syn::Type,\n    ctx: &Ctx,\n) -> Result<(Option<syn::ImplItemFn>, Option<MethodAndSlotDef>)> {\n    if options.hash.is_some() {\n        ensure_spanned!(\n            options.frozen.is_some(), options.hash.span() => \"The `hash` option requires the `frozen` option.\";\n            options.eq.is_some(), options.hash.span() => \"The `hash` option requires the `eq` option.\";\n        );\n    }\n    match options.hash {\n        Some(opt) => {\n            let mut hash_impl = parse_quote_spanned! { opt.span() =>\n                fn __pyo3__generated____hash__(&self) -> u64 {\n                    let mut s = ::std::collections::hash_map::DefaultHasher::new();\n                    ::std::hash::Hash::hash(self, &mut s);\n                    ::std::hash::Hasher::finish(&s)\n                }\n            };\n            let hash_slot = generate_protocol_slot(\n                cls,\n                &mut hash_impl,\n                &__HASH__,\n                \"__hash__\",\n                #[cfg(feature = \"experimental-inspect\")]\n                FunctionIntrospectionData {\n                    names: &[\"__hash__\"],\n                    arguments: Vec::new(),\n                    returns: parse_quote! { ::std::primitive::u64 },\n                    is_returning_not_implemented_on_extraction_error: false,\n                },\n                ctx,\n            )?;\n            Ok((Some(hash_impl), Some(hash_slot)))\n        }\n        None => Ok((None, None)),\n    }\n}\n\nfn pyclass_new_impl<'a>(\n    options: &PyClassPyO3Options,\n    ty: &syn::Type,\n    fields: impl Iterator<Item = &'a &'a syn::Field>,\n    ctx: &Ctx,\n) -> Result<(Option<ImplItemFn>, Option<MethodAndSlotDef>)> {\n    if options\n        .new\n        .as_ref()\n        .is_some_and(|o| matches!(o.value, NewImplTypeAttributeValue::FromFields))\n    {\n        ensure_spanned!(\n            options.extends.is_none(), options.new.span() => \"The `new=\\\"from_fields\\\"` option cannot be used with `extends`.\";\n        );\n    }\n\n    let mut tuple_struct: bool = false;\n\n    match &options.new {\n        Some(opt) => {\n            let mut field_idents = vec![];\n            let mut field_types = vec![];\n            for (idx, field) in fields.enumerate() {\n                tuple_struct = field.ident.is_none();\n\n                field_idents.push(\n                    field\n                        .ident\n                        .clone()\n                        .unwrap_or_else(|| format_ident!(\"_{}\", idx)),\n                );\n                field_types.push(&field.ty);\n            }\n\n            let mut new_impl = if tuple_struct {\n                parse_quote_spanned! { opt.span() =>\n                    #[new]\n                    fn __pyo3_generated____new__( #( #field_idents : #field_types ),* ) -> Self {\n                        Self (\n                            #( #field_idents, )*\n                        )\n                    }\n                }\n            } else {\n                parse_quote_spanned! { opt.span() =>\n                    #[new]\n                    fn __pyo3_generated____new__( #( #field_idents : #field_types ),* ) -> Self {\n                        Self {\n                            #( #field_idents, )*\n                        }\n                    }\n                }\n            };\n\n            let new_slot = generate_protocol_slot(\n                ty,\n                &mut new_impl,\n                &__NEW__,\n                \"__new__\",\n                #[cfg(feature = \"experimental-inspect\")]\n                FunctionIntrospectionData {\n                    names: &[\"__new__\"],\n                    arguments: field_idents\n                        .iter()\n                        .zip(field_types.iter())\n                        .map(|(ident, ty)| {\n                            FnArg::Regular(RegularArg {\n                                name: Cow::Owned(ident.clone()),\n                                ty,\n                                from_py_with: None,\n                                default_value: None,\n                                option_wrapped_type: None,\n                                annotation: None,\n                            })\n                        })\n                        .collect(),\n                    returns: ty.clone(),\n                    is_returning_not_implemented_on_extraction_error: false,\n                },\n                ctx,\n            )\n            .unwrap();\n\n            Ok((Some(new_impl), Some(new_slot)))\n        }\n        None => Ok((None, None)),\n    }\n}\n\nfn pyclass_class_getitem(\n    options: &PyClassPyO3Options,\n    cls: &syn::Type,\n    ctx: &Ctx,\n) -> Result<(Option<syn::ImplItemFn>, Option<MethodAndMethodDef>)> {\n    let Ctx { pyo3_path, .. } = ctx;\n    match options.generic {\n        Some(_) => {\n            let ident = format_ident!(\"__class_getitem__\");\n            let mut class_getitem_impl: syn::ImplItemFn = {\n                parse_quote! {\n                    #[classmethod]\n                    fn #ident<'py>(\n                        cls: &#pyo3_path::Bound<'py, #pyo3_path::types::PyType>,\n                        key: &#pyo3_path::Bound<'py, #pyo3_path::types::PyAny>\n                    ) -> #pyo3_path::PyResult<#pyo3_path::Bound<'py, #pyo3_path::types::PyGenericAlias>> {\n                        #pyo3_path::types::PyGenericAlias::new(cls.py(), cls.as_any(), key)\n                    }\n                }\n            };\n\n            let spec = FnSpec::parse(\n                &mut class_getitem_impl.sig,\n                &mut class_getitem_impl.attrs,\n                Default::default(),\n            )?;\n\n            let class_getitem_method = crate::pymethod::impl_py_method_def(\n                cls,\n                &spec,\n                spec.get_doc(&class_getitem_impl.attrs).as_ref(),\n                ctx,\n            )?;\n            Ok((Some(class_getitem_impl), Some(class_getitem_method)))\n        }\n        None => Ok((None, None)),\n    }\n}\n\n/// Implements most traits used by `#[pyclass]`.\n///\n/// Specifically, it implements traits that only depend on class name,\n/// and attributes of `#[pyclass]`, and docstrings.\n/// Therefore it doesn't implement traits that depends on struct fields and enum variants.\nstruct PyClassImplsBuilder<'a> {\n    /// Identifier of the class Rust struct\n    cls_ident: &'a Ident,\n    /// Name of the class in Python\n    cls_name: &'a Ident,\n    attr: &'a PyClassArgs,\n    methods_type: PyClassMethodsType,\n    default_methods: Vec<MethodAndMethodDef>,\n    default_slots: Vec<MethodAndSlotDef>,\n    doc: Option<PythonDoc>,\n}\n\nimpl<'a> PyClassImplsBuilder<'a> {\n    fn new(\n        cls_ident: &'a Ident,\n        cls_name: &'a Ident,\n        attr: &'a PyClassArgs,\n        methods_type: PyClassMethodsType,\n        default_methods: Vec<MethodAndMethodDef>,\n        default_slots: Vec<MethodAndSlotDef>,\n    ) -> Self {\n        Self {\n            cls_ident,\n            cls_name,\n            attr,\n            methods_type,\n            default_methods,\n            default_slots,\n            doc: None,\n        }\n    }\n\n    fn doc(self, doc: PythonDoc) -> Self {\n        Self {\n            doc: Some(doc),\n            ..self\n        }\n    }\n\n    fn impl_pyclass(&self, ctx: &Ctx) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        let cls = self.cls_ident;\n\n        let cls_name = get_class_python_name(self.cls_name, self.attr).to_string();\n\n        let frozen = if self.attr.options.frozen.is_some() {\n            quote! { #pyo3_path::pyclass::boolean_struct::True }\n        } else {\n            quote! { #pyo3_path::pyclass::boolean_struct::False }\n        };\n\n        quote! {\n            impl #pyo3_path::PyClass for #cls {\n                const NAME: &str = #cls_name;\n                type Frozen = #frozen;\n            }\n        }\n    }\n\n    fn impl_into_py(&self, ctx: &Ctx) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        let cls = self.cls_ident;\n        let attr = self.attr;\n        // If #cls is not extended type, we allow Self->PyObject conversion\n        if attr.options.extends.is_none() {\n            let output_type = get_conversion_type_hint(ctx, &format_ident!(\"OUTPUT_TYPE\"), cls);\n            quote! {\n                impl<'py> #pyo3_path::conversion::IntoPyObject<'py> for #cls {\n                    type Target = Self;\n                    type Output = #pyo3_path::Bound<'py, <Self as #pyo3_path::conversion::IntoPyObject<'py>>::Target>;\n                    type Error = #pyo3_path::PyErr;\n                    #output_type\n\n                    fn into_pyobject(self, py: #pyo3_path::Python<'py>) -> ::std::result::Result<\n                        <Self as #pyo3_path::conversion::IntoPyObject>::Output,\n                        <Self as #pyo3_path::conversion::IntoPyObject>::Error,\n                    > {\n                        #pyo3_path::Bound::new(py, self)\n                    }\n                }\n            }\n        } else {\n            quote! {}\n        }\n    }\n    fn impl_pyclassimpl(&self, ctx: &Ctx) -> Result<TokenStream> {\n        let Ctx { pyo3_path, .. } = ctx;\n        let cls = self.cls_ident;\n        let doc = if let Some(doc) = &self.doc {\n            doc.to_cstr_stream(ctx)?\n        } else {\n            c\"\".to_token_stream()\n        };\n\n        let module = if let Some(ModuleAttribute { value, .. }) = &self.attr.options.module {\n            quote! { ::core::option::Option::Some(#value) }\n        } else {\n            quote! { ::core::option::Option::None }\n        };\n\n        let is_basetype = self.attr.options.subclass.is_some();\n        let base = match &self.attr.options.extends {\n            Some(extends_attr) => extends_attr.value.clone(),\n            None => parse_quote! { #pyo3_path::PyAny },\n        };\n        let is_subclass = self.attr.options.extends.is_some();\n        let is_mapping: bool = self.attr.options.mapping.is_some();\n        let is_sequence: bool = self.attr.options.sequence.is_some();\n        let is_immutable_type = self.attr.options.immutable_type.is_some();\n\n        ensure_spanned!(\n            !(is_mapping && is_sequence),\n            cls.span() => \"a `#[pyclass]` cannot be both a `mapping` and a `sequence`\"\n        );\n\n        let dict_offset = if self.attr.options.dict.is_some() {\n            quote! {\n                fn dict_offset() -> ::std::option::Option<#pyo3_path::impl_::pyclass::PyObjectOffset> {\n                    ::std::option::Option::Some(#pyo3_path::impl_::pyclass::dict_offset::<Self>())\n                }\n            }\n        } else {\n            TokenStream::new()\n        };\n\n        let weaklist_offset = if self.attr.options.weakref.is_some() {\n            quote! {\n                fn weaklist_offset() -> ::std::option::Option<#pyo3_path::impl_::pyclass::PyObjectOffset> {\n                    ::std::option::Option::Some(#pyo3_path::impl_::pyclass::weaklist_offset::<Self>())\n                }\n            }\n        } else {\n            TokenStream::new()\n        };\n\n        let thread_checker = if self.attr.options.unsendable.is_some() {\n            quote! { #pyo3_path::impl_::pyclass::ThreadCheckerImpl }\n        } else {\n            quote! { #pyo3_path::impl_::pyclass::NoopThreadChecker }\n        };\n\n        let (pymethods_items, inventory, inventory_class) = match self.methods_type {\n            PyClassMethodsType::Specialization => (\n                quote! {{ use #pyo3_path::impl_::pyclass::PyMethods as _; collector.py_methods() }},\n                None,\n                None,\n            ),\n            PyClassMethodsType::Inventory => {\n                // To allow multiple #[pymethods] block, we define inventory types.\n                let inventory_class_name = syn::Ident::new(\n                    &format!(\"Pyo3MethodsInventoryFor{}\", cls.unraw()),\n                    Span::call_site(),\n                );\n                (\n                    quote! {\n                        ::std::boxed::Box::new(\n                            ::std::iter::Iterator::map(\n                                #pyo3_path::inventory::iter::<<Self as #pyo3_path::impl_::pyclass::PyClassImpl>::Inventory>(),\n                                #pyo3_path::impl_::pyclass::PyClassInventory::items\n                            )\n                        )\n                    },\n                    Some(quote! { type Inventory = #inventory_class_name; }),\n                    Some(define_inventory_class(&inventory_class_name, ctx)),\n                )\n            }\n        };\n\n        let default_methods = self\n            .default_methods\n            .iter()\n            .map(|meth| &meth.associated_method)\n            .chain(\n                self.default_slots\n                    .iter()\n                    .map(|meth| &meth.associated_method),\n            );\n\n        let default_method_defs = self.default_methods.iter().map(|meth| &meth.method_def);\n        let default_slot_defs = self.default_slots.iter().map(|slot| &slot.slot_def);\n        let freelist_slots = self.freelist_slots(ctx);\n\n        let class_mutability = if self.attr.options.frozen.is_some() {\n            quote! {\n                ImmutableChild\n            }\n        } else {\n            quote! {\n                MutableChild\n            }\n        };\n\n        let attr = self.attr;\n        let dict = if attr.options.dict.is_some() {\n            quote! { #pyo3_path::impl_::pyclass::PyClassDictSlot }\n        } else {\n            quote! { #pyo3_path::impl_::pyclass::PyClassDummySlot }\n        };\n\n        // insert space for weak ref\n        let weakref = if attr.options.weakref.is_some() {\n            quote! { #pyo3_path::impl_::pyclass::PyClassWeakRefSlot }\n        } else {\n            quote! { #pyo3_path::impl_::pyclass::PyClassDummySlot }\n        };\n\n        let base_nativetype = if attr.options.extends.is_some() {\n            quote! { <Self::BaseType as #pyo3_path::impl_::pyclass::PyClassBaseType>::BaseNativeType }\n        } else {\n            quote! { #pyo3_path::PyAny }\n        };\n\n        let pyclass_base_type_impl = attr.options.subclass.map(|subclass| {\n            quote_spanned! { subclass.span() =>\n                impl #pyo3_path::impl_::pyclass::PyClassBaseType for #cls {\n                    type LayoutAsBase = <Self as #pyo3_path::impl_::pyclass::PyClassImpl>::Layout;\n                    type BaseNativeType = <Self as #pyo3_path::impl_::pyclass::PyClassImpl>::BaseNativeType;\n                    type Initializer = #pyo3_path::pyclass_init::PyClassInitializer<Self>;\n                    type PyClassMutability = <Self as #pyo3_path::impl_::pyclass::PyClassImpl>::PyClassMutability;\n                    type Layout<T: #pyo3_path::impl_::pyclass::PyClassImpl> = <Self::BaseNativeType as #pyo3_path::impl_::pyclass::PyClassBaseType>::Layout<T>;\n                }\n            }\n        });\n\n        let mut assertions = TokenStream::new();\n\n        // Classes must implement send / sync, unless `#[pyclass(unsendable)]` is used\n        if attr.options.unsendable.is_none() {\n            let pyo3_path = locate_tokens_at(pyo3_path.to_token_stream(), cls.span());\n            assertions.extend(quote_spanned! { cls.span() => #pyo3_path::impl_::pyclass::assert_pyclass_send_sync::<#cls>(); });\n        };\n\n        if let Some(kw) = &attr.options.dict {\n            let pyo3_path = locate_tokens_at(pyo3_path.to_token_stream(), kw.span());\n            assertions.extend(quote_spanned! {\n                kw.span() =>\n                    const ASSERT_DICT_SUPPORTED: () = #pyo3_path::impl_::pyclass::assert_dict_supported();\n\n            });\n        }\n\n        if let Some(kw) = &attr.options.weakref {\n            let pyo3_path = locate_tokens_at(pyo3_path.to_token_stream(), kw.span());\n            assertions.extend(quote_spanned! {\n                kw.span() => {\n                    const ASSERT_WEAKREF_SUPPORTED: () = #pyo3_path::impl_::pyclass::assert_weakref_supported();\n                };\n            });\n        }\n\n        if let Some(kw) = &attr.options.immutable_type {\n            let pyo3_path = locate_tokens_at(pyo3_path.to_token_stream(), kw.span());\n            assertions.extend(quote_spanned! {\n                kw.span() => {\n                    const ASSERT_IMMUTABLE_SUPPORTED: () = #pyo3_path::impl_::pyclass::assert_immutable_type_supported();\n                };\n            });\n        }\n\n        let deprecation = if self.attr.options.skip_from_py_object.is_none()\n            && self.attr.options.from_py_object.is_none()\n        {\n            quote! {\n                const _: () = {\n                    #[allow(unused_import)]\n                    use #pyo3_path::impl_::pyclass::Probe as _;\n                    #pyo3_path::impl_::deprecated::HasAutomaticFromPyObject::<{ #pyo3_path::impl_::pyclass::IsClone::<#cls>::VALUE }>::MSG\n                };\n            }\n        } else {\n            TokenStream::new()\n        };\n\n        let extract_pyclass_with_clone = if let Some(from_py_object) =\n            self.attr.options.from_py_object\n        {\n            let input_type = get_conversion_type_hint(ctx, &format_ident!(\"INPUT_TYPE\"), cls);\n            quote_spanned! { from_py_object.span() =>\n                impl<'a, 'py> #pyo3_path::FromPyObject<'a, 'py> for #cls\n                where\n                    Self: ::std::clone::Clone,\n                {\n                    type Error = #pyo3_path::pyclass::PyClassGuardError<'a, 'py>;\n\n                    #input_type\n\n                    fn extract(obj: #pyo3_path::Borrowed<'a, 'py, #pyo3_path::PyAny>) -> ::std::result::Result<Self,  <Self as #pyo3_path::FromPyObject<'a, 'py>>::Error> {\n                        ::std::result::Result::Ok(::std::clone::Clone::clone(&*obj.extract::<#pyo3_path::PyClassGuard<'_, #cls>>()?))\n                    }\n                }\n            }\n        } else if self.attr.options.skip_from_py_object.is_none() {\n            quote!( impl #pyo3_path::impl_::pyclass::ExtractPyClassWithClone for #cls {} )\n        } else {\n            TokenStream::new()\n        };\n\n        Ok(quote! {\n            #deprecation\n\n            #extract_pyclass_with_clone\n\n            #[allow(dead_code)]\n            const _: () ={\n                #assertions\n            };\n\n            #pyclass_base_type_impl\n\n            impl #pyo3_path::impl_::pyclass::PyClassImpl for #cls {\n                const MODULE: ::std::option::Option<&str> = #module;\n                const IS_BASETYPE: bool = #is_basetype;\n                const IS_SUBCLASS: bool = #is_subclass;\n                const IS_MAPPING: bool = #is_mapping;\n                const IS_SEQUENCE: bool = #is_sequence;\n                const IS_IMMUTABLE_TYPE: bool = #is_immutable_type;\n\n                type Layout = <Self::BaseNativeType as #pyo3_path::impl_::pyclass::PyClassBaseType>::Layout<Self>;\n                type BaseType = #base;\n                type ThreadChecker = #thread_checker;\n                #inventory\n                type PyClassMutability = <<#base as #pyo3_path::impl_::pyclass::PyClassBaseType>::PyClassMutability as #pyo3_path::impl_::pycell::PyClassMutability>::#class_mutability;\n                type Dict = #dict;\n                type WeakRef = #weakref;\n                type BaseNativeType = #base_nativetype;\n\n                fn items_iter() -> #pyo3_path::impl_::pyclass::PyClassItemsIter {\n                    let collector = #pyo3_path::impl_::pyclass::PyClassImplCollector::<Self>::new();\n                    static INTRINSIC_ITEMS: #pyo3_path::impl_::pyclass::PyClassItems = #pyo3_path::impl_::pyclass::PyClassItems {\n                        methods: &[#(#default_method_defs),*],\n                        slots: &[#(#default_slot_defs),* #(#freelist_slots),*],\n                    };\n                    #pyo3_path::impl_::pyclass::PyClassItemsIter::new(&INTRINSIC_ITEMS, #pymethods_items)\n                }\n\n                const RAW_DOC: &'static ::std::ffi::CStr = #doc;\n\n                const DOC: &'static ::std::ffi::CStr = {\n                    use #pyo3_path::impl_ as impl_;\n                    use impl_::pyclass::Probe as _;\n                    const DOC_PIECES: &'static [&'static [u8]] = impl_::pyclass::doc::PyClassDocGenerator::<\n                        #cls,\n                        { impl_::pyclass::HasNewTextSignature::<#cls>::VALUE }\n                    >::DOC_PIECES;\n                    const LEN: usize = impl_::concat::combined_len(DOC_PIECES);\n                    const DOC: &'static [u8] = &impl_::concat::combine_to_array::<LEN>(DOC_PIECES);\n                    impl_::pyclass::doc::doc_bytes_as_cstr(DOC)\n                };\n\n                #dict_offset\n\n                #weaklist_offset\n\n                fn lazy_type_object() -> &'static #pyo3_path::impl_::pyclass::LazyTypeObject<Self> {\n                    use #pyo3_path::impl_::pyclass::LazyTypeObject;\n                    static TYPE_OBJECT: LazyTypeObject<#cls> = LazyTypeObject::new();\n                    &TYPE_OBJECT\n                }\n            }\n\n            #[doc(hidden)]\n            #[allow(non_snake_case)]\n            impl #cls {\n                #(#default_methods)*\n            }\n\n            #inventory_class\n        })\n    }\n\n    fn impl_add_to_module(&self, ctx: &Ctx) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        let cls = self.cls_ident;\n        quote! {\n            impl #cls {\n                #[doc(hidden)]\n                pub const _PYO3_DEF: #pyo3_path::impl_::pymodule::AddClassToModule<Self> = #pyo3_path::impl_::pymodule::AddClassToModule::new();\n            }\n        }\n    }\n\n    fn impl_freelist(&self, ctx: &Ctx) -> TokenStream {\n        let cls = self.cls_ident;\n        let Ctx { pyo3_path, .. } = ctx;\n\n        self.attr.options.freelist.as_ref().map_or(quote! {}, |freelist| {\n            let freelist = &freelist.value;\n            quote! {\n                impl #pyo3_path::impl_::pyclass::PyClassWithFreeList for #cls {\n                    #[inline]\n                    fn get_free_list(py: #pyo3_path::Python<'_>) -> &'static ::std::sync::Mutex<#pyo3_path::impl_::freelist::PyObjectFreeList> {\n                        static FREELIST: #pyo3_path::sync::PyOnceLock<::std::sync::Mutex<#pyo3_path::impl_::freelist::PyObjectFreeList>> = #pyo3_path::sync::PyOnceLock::new();\n                        &FREELIST.get_or_init(py, || ::std::sync::Mutex::new(#pyo3_path::impl_::freelist::PyObjectFreeList::with_capacity(#freelist)))\n                    }\n                }\n            }\n        })\n    }\n\n    fn freelist_slots(&self, ctx: &Ctx) -> Vec<TokenStream> {\n        let Ctx { pyo3_path, .. } = ctx;\n        let cls = self.cls_ident;\n\n        if self.attr.options.freelist.is_some() {\n            vec![\n                quote! {\n                    #pyo3_path::ffi::PyType_Slot {\n                        slot: #pyo3_path::ffi::Py_tp_alloc,\n                        pfunc: #pyo3_path::impl_::pyclass::alloc_with_freelist::<#cls> as *mut _,\n                    }\n                },\n                quote! {\n                    #pyo3_path::ffi::PyType_Slot {\n                        slot: #pyo3_path::ffi::Py_tp_free,\n                        pfunc: #pyo3_path::impl_::pyclass::free_with_freelist::<#cls> as *mut _,\n                    }\n                },\n            ]\n        } else {\n            Vec::new()\n        }\n    }\n\n    #[cfg(feature = \"experimental-inspect\")]\n    fn impl_introspection(&self, ctx: &Ctx, parent: Option<&Ident>) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        let name = get_class_python_name(self.cls_name, self.attr).to_string();\n        let ident = self.cls_ident;\n        let static_introspection = class_introspection_code(\n            pyo3_path,\n            ident,\n            &name,\n            self.attr.options.extends.as_ref().map(|attr| {\n                PyExpr::from_type(\n                    syn::TypePath {\n                        qself: None,\n                        path: attr.value.clone(),\n                    }\n                    .into(),\n                    None,\n                )\n            }),\n            self.attr.options.subclass.is_none(),\n            parent.map(|p| parse_quote!(#p)).as_ref(),\n            self.doc.as_ref(),\n        );\n        let introspection_id = introspection_id_const();\n        quote! {\n            #static_introspection\n            impl #ident {\n                #introspection_id\n            }\n        }\n    }\n\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    fn impl_introspection(&self, _ctx: &Ctx, _parent: Option<&Ident>) -> TokenStream {\n        quote! {}\n    }\n}\n\nfn define_inventory_class(inventory_class_name: &syn::Ident, ctx: &Ctx) -> TokenStream {\n    let Ctx { pyo3_path, .. } = ctx;\n    quote! {\n        #[doc(hidden)]\n        pub struct #inventory_class_name {\n            items: #pyo3_path::impl_::pyclass::PyClassItems,\n        }\n        impl #inventory_class_name {\n            pub const fn new(items: #pyo3_path::impl_::pyclass::PyClassItems) -> Self {\n                Self { items }\n            }\n        }\n\n        impl #pyo3_path::impl_::pyclass::PyClassInventory for #inventory_class_name {\n            fn items(&self) -> &#pyo3_path::impl_::pyclass::PyClassItems {\n                &self.items\n            }\n        }\n\n        #pyo3_path::inventory::collect!(#inventory_class_name);\n    }\n}\n\nfn generate_cfg_check(variants: &[PyClassEnumUnitVariant<'_>], cls: &syn::Ident) -> TokenStream {\n    if variants.is_empty() {\n        return quote! {};\n    }\n\n    let mut conditions = Vec::new();\n\n    for variant in variants {\n        let cfg_attrs = get_cfg_attributes(&variant.attrs);\n\n        if cfg_attrs.is_empty() {\n            // There's at least one variant of the enum without cfg attributes,\n            // so the check is not necessary\n            return quote! {};\n        }\n\n        for attr in cfg_attrs {\n            if let syn::Meta::List(meta) = &attr.meta {\n                let cfg_tokens = &meta.tokens;\n                conditions.push(quote! { not(#cfg_tokens) });\n            }\n        }\n    }\n\n    quote_spanned! {\n        cls.span() =>\n        #[cfg(all(#(#conditions),*))]\n        ::core::compile_error!(concat!(\"#[pyclass] can't be used on enums without any variants - all variants of enum `\", stringify!(#cls), \"` have been configured out by cfg attributes\"));\n    }\n}\n\nfn get_conversion_type_hint(\n    Ctx { pyo3_path, .. }: &Ctx,\n    konst: &Ident,\n    cls: &Ident,\n) -> TokenStream {\n    if cfg!(feature = \"experimental-inspect\") {\n        quote!(const #konst: #pyo3_path::inspect::PyStaticExpr = <#cls as #pyo3_path::PyTypeInfo>::TYPE_HINT;)\n    } else {\n        TokenStream::new()\n    }\n}\n\nconst UNIQUE_GET: &str = \"`get` may only be specified once\";\nconst UNIQUE_SET: &str = \"`set` may only be specified once\";\nconst UNIQUE_NAME: &str = \"`name` may only be specified once\";\n\nconst DUPE_SET: &str = \"useless `set` - the struct is already annotated with `set_all`\";\nconst DUPE_GET: &str = \"useless `get` - the struct is already annotated with `get_all`\";\nconst UNIT_GET: &str =\n    \"`get_all` on an unit struct does nothing, because unit structs have no fields\";\nconst UNIT_SET: &str =\n    \"`set_all` on an unit struct does nothing, because unit structs have no fields\";\n\nconst USELESS_NAME: &str = \"`name` is useless without `get` or `set`\";\n"
  },
  {
    "path": "pyo3-macros-backend/src/pyfunction/signature.rs",
    "content": "#[cfg(feature = \"experimental-inspect\")]\nuse crate::py_expr::PyExpr;\nuse crate::{\n    attributes::{kw, KeywordAttribute},\n    method::FnArg,\n    utils::expr_to_python,\n};\nuse proc_macro2::{Span, TokenStream};\nuse quote::ToTokens;\nuse syn::{\n    ext::IdentExt,\n    parse::{Parse, ParseStream},\n    punctuated::Punctuated,\n    spanned::Spanned,\n    Expr, Token,\n};\n\n#[derive(Clone)]\npub struct Signature {\n    paren_token: syn::token::Paren,\n    pub items: Punctuated<SignatureItem, Token![,]>,\n    pub returns: Option<(Token![->], PyTypeAnnotation)>,\n}\n\nimpl Parse for Signature {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        let content;\n        let paren_token = syn::parenthesized!(content in input);\n        let items = content.parse_terminated(SignatureItem::parse, Token![,])?;\n        let returns = if input.peek(Token![->]) {\n            Some((input.parse()?, input.parse()?))\n        } else {\n            None\n        };\n        Ok(Signature {\n            paren_token,\n            items,\n            returns,\n        })\n    }\n}\n\nimpl ToTokens for Signature {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.paren_token\n            .surround(tokens, |tokens| self.items.to_tokens(tokens));\n        if let Some((arrow, returns)) = &self.returns {\n            arrow.to_tokens(tokens);\n            returns.to_tokens(tokens);\n        }\n    }\n}\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct SignatureItemArgument {\n    pub ident: syn::Ident,\n    pub colon_and_annotation: Option<(Token![:], PyTypeAnnotation)>,\n    pub eq_and_default: Option<(Token![=], syn::Expr)>,\n}\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct SignatureItemPosargsSep {\n    pub slash: Token![/],\n}\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct SignatureItemVarargsSep {\n    pub asterisk: Token![*],\n}\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct SignatureItemVarargs {\n    pub sep: SignatureItemVarargsSep,\n    pub ident: syn::Ident,\n    pub colon_and_annotation: Option<(Token![:], PyTypeAnnotation)>,\n}\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct SignatureItemKwargs {\n    pub asterisks: (Token![*], Token![*]),\n    pub ident: syn::Ident,\n    pub colon_and_annotation: Option<(Token![:], PyTypeAnnotation)>,\n}\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub enum SignatureItem {\n    Argument(Box<SignatureItemArgument>),\n    PosargsSep(SignatureItemPosargsSep),\n    VarargsSep(SignatureItemVarargsSep),\n    Varargs(SignatureItemVarargs),\n    Kwargs(SignatureItemKwargs),\n}\n\nimpl Parse for SignatureItem {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        let lookahead = input.lookahead1();\n        if lookahead.peek(Token![*]) {\n            if input.peek2(Token![*]) {\n                input.parse().map(SignatureItem::Kwargs)\n            } else {\n                let sep = input.parse()?;\n                if input.is_empty() || input.peek(Token![,]) {\n                    Ok(SignatureItem::VarargsSep(sep))\n                } else {\n                    Ok(SignatureItem::Varargs(SignatureItemVarargs {\n                        sep,\n                        ident: input.parse()?,\n                        colon_and_annotation: if input.peek(Token![:]) {\n                            Some((input.parse()?, input.parse()?))\n                        } else {\n                            None\n                        },\n                    }))\n                }\n            }\n        } else if lookahead.peek(Token![/]) {\n            input.parse().map(SignatureItem::PosargsSep)\n        } else {\n            input.parse().map(SignatureItem::Argument)\n        }\n    }\n}\n\nimpl ToTokens for SignatureItem {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        match self {\n            SignatureItem::Argument(arg) => arg.to_tokens(tokens),\n            SignatureItem::Varargs(varargs) => varargs.to_tokens(tokens),\n            SignatureItem::VarargsSep(sep) => sep.to_tokens(tokens),\n            SignatureItem::Kwargs(kwargs) => kwargs.to_tokens(tokens),\n            SignatureItem::PosargsSep(sep) => sep.to_tokens(tokens),\n        }\n    }\n}\n\nimpl Parse for SignatureItemArgument {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        Ok(Self {\n            ident: input.parse()?,\n            colon_and_annotation: if input.peek(Token![:]) {\n                Some((input.parse()?, input.parse()?))\n            } else {\n                None\n            },\n            eq_and_default: if input.peek(Token![=]) {\n                Some((input.parse()?, input.parse()?))\n            } else {\n                None\n            },\n        })\n    }\n}\n\nimpl ToTokens for SignatureItemArgument {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.ident.to_tokens(tokens);\n        if let Some((colon, annotation)) = &self.colon_and_annotation {\n            colon.to_tokens(tokens);\n            annotation.to_tokens(tokens);\n        }\n        if let Some((eq, default)) = &self.eq_and_default {\n            eq.to_tokens(tokens);\n            default.to_tokens(tokens);\n        }\n    }\n}\n\nimpl Parse for SignatureItemVarargsSep {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        Ok(Self {\n            asterisk: input.parse()?,\n        })\n    }\n}\n\nimpl ToTokens for SignatureItemVarargsSep {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.asterisk.to_tokens(tokens);\n    }\n}\n\nimpl Parse for SignatureItemVarargs {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        Ok(Self {\n            sep: input.parse()?,\n            ident: input.parse()?,\n            colon_and_annotation: if input.peek(Token![:]) {\n                Some((input.parse()?, input.parse()?))\n            } else {\n                None\n            },\n        })\n    }\n}\n\nimpl ToTokens for SignatureItemVarargs {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.sep.to_tokens(tokens);\n        self.ident.to_tokens(tokens);\n    }\n}\n\nimpl Parse for SignatureItemKwargs {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        Ok(Self {\n            asterisks: (input.parse()?, input.parse()?),\n            ident: input.parse()?,\n            colon_and_annotation: if input.peek(Token![:]) {\n                Some((input.parse()?, input.parse()?))\n            } else {\n                None\n            },\n        })\n    }\n}\n\nimpl ToTokens for SignatureItemKwargs {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.asterisks.0.to_tokens(tokens);\n        self.asterisks.1.to_tokens(tokens);\n        self.ident.to_tokens(tokens);\n    }\n}\n\nimpl Parse for SignatureItemPosargsSep {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        Ok(Self {\n            slash: input.parse()?,\n        })\n    }\n}\n\nimpl ToTokens for SignatureItemPosargsSep {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.slash.to_tokens(tokens);\n    }\n}\n\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct PyTypeAnnotation(syn::LitStr);\n\nimpl Parse for PyTypeAnnotation {\n    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {\n        Ok(Self(input.parse()?))\n    }\n}\n\nimpl ToTokens for PyTypeAnnotation {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        self.0.to_tokens(tokens);\n    }\n}\n\nimpl PyTypeAnnotation {\n    #[cfg(feature = \"experimental-inspect\")]\n    pub fn as_type_hint(&self) -> PyExpr {\n        PyExpr::str_constant(self.0.value())\n    }\n}\n\npub type SignatureAttribute = KeywordAttribute<kw::signature, Signature>;\npub type ConstructorAttribute = KeywordAttribute<kw::constructor, Signature>;\n\nimpl ConstructorAttribute {\n    pub fn into_signature(self) -> SignatureAttribute {\n        SignatureAttribute {\n            kw: kw::signature(self.kw.span),\n            value: self.value,\n        }\n    }\n}\n\n#[derive(Default, Clone)]\npub struct PythonSignature {\n    pub positional_parameters: Vec<String>,\n    pub positional_only_parameters: usize,\n    /// Vector of expressions representing positional defaults\n    pub default_positional_parameters: Vec<Expr>,\n    pub varargs: Option<String>,\n    // Tuples of keyword name and optional default value\n    pub keyword_only_parameters: Vec<(String, Option<Expr>)>,\n    pub kwargs: Option<String>,\n}\n\nimpl PythonSignature {\n    pub fn has_no_args(&self) -> bool {\n        self.positional_parameters.is_empty()\n            && self.keyword_only_parameters.is_empty()\n            && self.varargs.is_none()\n            && self.kwargs.is_none()\n    }\n\n    pub fn required_positional_parameters(&self) -> usize {\n        self.positional_parameters\n            .len()\n            .checked_sub(self.default_positional_parameters.len())\n            .expect(\"should always have positional defaults <= positional parameters\")\n    }\n}\n\n#[derive(Clone)]\npub struct FunctionSignature<'a> {\n    pub arguments: Vec<FnArg<'a>>,\n    pub python_signature: PythonSignature,\n    pub attribute: Option<SignatureAttribute>,\n}\n\npub enum ParseState {\n    /// Accepting positional parameters, which might be positional only\n    Positional,\n    /// Accepting positional parameters after '/'\n    PositionalAfterPosargs,\n    /// Accepting keyword-only parameters after '*' or '*args'\n    Keywords,\n    /// After `**kwargs` nothing is allowed\n    Done,\n}\n\nimpl ParseState {\n    fn add_argument(\n        &mut self,\n        signature: &mut PythonSignature,\n        name: String,\n        default_value: Option<Expr>,\n        span: Span,\n    ) -> syn::Result<()> {\n        match self {\n            ParseState::Positional | ParseState::PositionalAfterPosargs => {\n                signature.positional_parameters.push(name);\n                if let Some(default_value) = default_value {\n                    signature.default_positional_parameters.push(default_value);\n                    // Now all subsequent positional parameters must also have defaults\n                } else if !signature.default_positional_parameters.is_empty() {\n                    bail_spanned!(span => \"cannot have required positional parameter after an optional parameter\")\n                }\n                Ok(())\n            }\n            ParseState::Keywords => {\n                signature\n                    .keyword_only_parameters\n                    .push((name, default_value));\n                Ok(())\n            }\n            ParseState::Done => {\n                bail_spanned!(span => format!(\"no more arguments are allowed after `**{}`\", signature.kwargs.as_deref().unwrap_or(\"\")))\n            }\n        }\n    }\n\n    fn add_varargs(\n        &mut self,\n        signature: &mut PythonSignature,\n        varargs: &SignatureItemVarargs,\n    ) -> syn::Result<()> {\n        match self {\n            ParseState::Positional | ParseState::PositionalAfterPosargs => {\n                signature.varargs = Some(varargs.ident.to_string());\n                *self = ParseState::Keywords;\n                Ok(())\n            }\n            ParseState::Keywords => {\n                bail_spanned!(varargs.span() => format!(\"`*{}` not allowed after `*{}`\", varargs.ident, signature.varargs.as_deref().unwrap_or(\"\")))\n            }\n            ParseState::Done => {\n                bail_spanned!(varargs.span() => format!(\"`*{}` not allowed after `**{}`\", varargs.ident, signature.kwargs.as_deref().unwrap_or(\"\")))\n            }\n        }\n    }\n\n    fn add_kwargs(\n        &mut self,\n        signature: &mut PythonSignature,\n        kwargs: &SignatureItemKwargs,\n    ) -> syn::Result<()> {\n        match self {\n            ParseState::Positional | ParseState::PositionalAfterPosargs | ParseState::Keywords => {\n                signature.kwargs = Some(kwargs.ident.to_string());\n                *self = ParseState::Done;\n                Ok(())\n            }\n            ParseState::Done => {\n                bail_spanned!(kwargs.span() => format!(\"`**{}` not allowed after `**{}`\", kwargs.ident, signature.kwargs.as_deref().unwrap_or(\"\")))\n            }\n        }\n    }\n\n    fn finish_pos_only_args(\n        &mut self,\n        signature: &mut PythonSignature,\n        span: Span,\n    ) -> syn::Result<()> {\n        match self {\n            ParseState::Positional => {\n                signature.positional_only_parameters = signature.positional_parameters.len();\n                *self = ParseState::PositionalAfterPosargs;\n                Ok(())\n            }\n            ParseState::PositionalAfterPosargs => {\n                bail_spanned!(span => \"`/` not allowed after `/`\")\n            }\n            ParseState::Keywords => {\n                bail_spanned!(span => format!(\"`/` not allowed after `*{}`\", signature.varargs.as_deref().unwrap_or(\"\")))\n            }\n            ParseState::Done => {\n                bail_spanned!(span => format!(\"`/` not allowed after `**{}`\", signature.kwargs.as_deref().unwrap_or(\"\")))\n            }\n        }\n    }\n\n    fn finish_pos_args(&mut self, signature: &PythonSignature, span: Span) -> syn::Result<()> {\n        match self {\n            ParseState::Positional | ParseState::PositionalAfterPosargs => {\n                *self = ParseState::Keywords;\n                Ok(())\n            }\n            ParseState::Keywords => {\n                bail_spanned!(span => format!(\"`*` not allowed after `*{}`\", signature.varargs.as_deref().unwrap_or(\"\")))\n            }\n            ParseState::Done => {\n                bail_spanned!(span => format!(\"`*` not allowed after `**{}`\", signature.kwargs.as_deref().unwrap_or(\"\")))\n            }\n        }\n    }\n}\n\nimpl<'a> FunctionSignature<'a> {\n    pub fn from_arguments_and_attribute(\n        mut arguments: Vec<FnArg<'a>>,\n        attribute: SignatureAttribute,\n    ) -> syn::Result<Self> {\n        let mut parse_state = ParseState::Positional;\n        let mut python_signature = PythonSignature::default();\n\n        let mut args_iter = arguments.iter_mut();\n\n        let mut next_non_py_argument_checked = |name: &syn::Ident| {\n            for fn_arg in args_iter.by_ref() {\n                match fn_arg {\n                    FnArg::Py(..) => {\n                        // If the user incorrectly tried to include py: Python in the\n                        // signature, give a useful error as a hint.\n                        ensure_spanned!(\n                            name != fn_arg.name(),\n                            name.span() => \"arguments of type `Python` must not be part of the signature\"\n                        );\n                        // Otherwise try next argument.\n                        continue;\n                    }\n                    FnArg::CancelHandle(..) => {\n                        // If the user incorrectly tried to include cancel: CoroutineCancel in the\n                        // signature, give a useful error as a hint.\n                        ensure_spanned!(\n                            name != fn_arg.name(),\n                            name.span() => \"`cancel_handle` argument must not be part of the signature\"\n                        );\n                        // Otherwise try next argument.\n                        continue;\n                    }\n                    _ => {\n                        ensure_spanned!(\n                            name == fn_arg.name(),\n                            name.span() => format!(\n                                \"expected argument from function definition `{}` but got argument `{}`\",\n                                fn_arg.name().unraw(),\n                                name.unraw(),\n                            )\n                        );\n                        return Ok(fn_arg);\n                    }\n                }\n            }\n            bail_spanned!(\n                name.span() => \"signature entry does not have a corresponding function argument\"\n            )\n        };\n\n        if let Some(returns) = &attribute.value.returns {\n            ensure_spanned!(\n                cfg!(feature = \"experimental-inspect\"),\n                returns.1.span() => \"Return type annotation in the signature is only supported with the `experimental-inspect` feature\"\n            );\n        }\n\n        for item in &attribute.value.items {\n            match item {\n                SignatureItem::Argument(arg) => {\n                    let fn_arg = next_non_py_argument_checked(&arg.ident)?;\n                    parse_state.add_argument(\n                        &mut python_signature,\n                        arg.ident.unraw().to_string(),\n                        arg.eq_and_default\n                            .as_ref()\n                            .map(|(_, default)| default.clone()),\n                        arg.span(),\n                    )?;\n                    let FnArg::Regular(fn_arg) = fn_arg else {\n                        unreachable!(\n                            \"`Python` and `CancelHandle` are already handled above and `*args`/`**kwargs` are \\\n                                parsed and transformed below. Because the have to come last and are only allowed \\\n                                once, this has to be a regular argument.\"\n                        );\n                    };\n                    if let Some((_, default)) = &arg.eq_and_default {\n                        fn_arg.default_value = Some(Box::new(default.clone()));\n                    }\n                    if let Some((_, annotation)) = &arg.colon_and_annotation {\n                        ensure_spanned!(\n                            cfg!(feature = \"experimental-inspect\"),\n                            annotation.span() => \"Type annotations in the signature is only supported with the `experimental-inspect` feature\"\n                        );\n                        #[cfg(feature = \"experimental-inspect\")]\n                        {\n                            fn_arg.annotation = Some(annotation.as_type_hint());\n                        }\n                    }\n                }\n                SignatureItem::VarargsSep(sep) => {\n                    parse_state.finish_pos_args(&python_signature, sep.span())?\n                }\n                SignatureItem::Varargs(varargs) => {\n                    let fn_arg = next_non_py_argument_checked(&varargs.ident)?;\n                    fn_arg.to_varargs_mut()?;\n                    parse_state.add_varargs(&mut python_signature, varargs)?;\n                    if let Some((_, annotation)) = &varargs.colon_and_annotation {\n                        ensure_spanned!(\n                            cfg!(feature = \"experimental-inspect\"),\n                            annotation.span() => \"Type annotations in the signature is only supported with the `experimental-inspect` feature\"\n                        );\n                        #[cfg(feature = \"experimental-inspect\")]\n                        {\n                            let FnArg::VarArgs(fn_arg) = fn_arg else {\n                                unreachable!(\n                                    \"`Python` and `CancelHandle` are already handled above and `*args`/`**kwargs` are \\\n                                parsed and transformed below. Because the have to come last and are only allowed \\\n                                once, this has to be a regular argument.\"\n                                );\n                            };\n                            fn_arg.annotation = Some(annotation.as_type_hint());\n                        }\n                    }\n                }\n                SignatureItem::Kwargs(kwargs) => {\n                    let fn_arg = next_non_py_argument_checked(&kwargs.ident)?;\n                    fn_arg.to_kwargs_mut()?;\n                    parse_state.add_kwargs(&mut python_signature, kwargs)?;\n                    if let Some((_, annotation)) = &kwargs.colon_and_annotation {\n                        ensure_spanned!(\n                            cfg!(feature = \"experimental-inspect\"),\n                            annotation.span() => \"Type annotations in the signature is only supported with the `experimental-inspect` feature\"\n                        );\n                        #[cfg(feature = \"experimental-inspect\")]\n                        {\n                            let FnArg::KwArgs(fn_arg) = fn_arg else {\n                                unreachable!(\n                                    \"`Python` and `CancelHandle` are already handled above and `*args`/`**kwargs` are \\\n                                parsed and transformed below. Because the have to come last and are only allowed \\\n                                once, this has to be a regular argument.\"\n                                );\n                            };\n                            fn_arg.annotation = Some(annotation.as_type_hint());\n                        }\n                    }\n                }\n                SignatureItem::PosargsSep(sep) => {\n                    parse_state.finish_pos_only_args(&mut python_signature, sep.span())?\n                }\n            };\n        }\n\n        // Ensure no non-py arguments remain\n        if let Some(arg) =\n            args_iter.find(|arg| !matches!(arg, FnArg::Py(..) | FnArg::CancelHandle(..)))\n        {\n            bail_spanned!(\n                attribute.kw.span() => format!(\"missing signature entry for argument `{}`\", arg.name())\n            );\n        }\n\n        Ok(FunctionSignature {\n            arguments,\n            python_signature,\n            attribute: Some(attribute),\n        })\n    }\n\n    /// Without `#[pyo3(signature)]` or `#[args]` - just take the Rust function arguments as positional.\n    pub fn from_arguments(arguments: Vec<FnArg<'a>>) -> Self {\n        let mut python_signature = PythonSignature::default();\n        for arg in &arguments {\n            // Python<'_> arguments don't show in Python signature\n            if matches!(arg, FnArg::Py(..) | FnArg::CancelHandle(..)) {\n                continue;\n            }\n\n            python_signature\n                .positional_parameters\n                .push(arg.name().unraw().to_string());\n        }\n\n        Self {\n            arguments,\n            python_signature,\n            attribute: None,\n        }\n    }\n\n    pub fn text_signature(&self, self_argument: Option<&str>) -> String {\n        let mut output = String::new();\n        output.push('(');\n\n        if let Some(arg) = self_argument {\n            output.push('$');\n            output.push_str(arg);\n        }\n\n        let mut maybe_push_comma = {\n            let mut first = self_argument.is_none();\n            move |output: &mut String| {\n                if !first {\n                    output.push_str(\", \");\n                } else {\n                    first = false;\n                }\n            }\n        };\n\n        let py_sig = &self.python_signature;\n\n        let defaults = std::iter::repeat_n(None, py_sig.required_positional_parameters())\n            .chain(py_sig.default_positional_parameters.iter().map(Some));\n\n        for (i, (parameter, default)) in\n            std::iter::zip(&py_sig.positional_parameters, defaults).enumerate()\n        {\n            maybe_push_comma(&mut output);\n\n            output.push_str(parameter);\n\n            if let Some(expr) = default {\n                output.push('=');\n                output.push_str(&expr_to_python(expr));\n            }\n\n            if py_sig.positional_only_parameters > 0 && i + 1 == py_sig.positional_only_parameters {\n                output.push_str(\", /\")\n            }\n        }\n\n        if let Some(varargs) = &py_sig.varargs {\n            maybe_push_comma(&mut output);\n            output.push('*');\n            output.push_str(varargs);\n        } else if !py_sig.keyword_only_parameters.is_empty() {\n            maybe_push_comma(&mut output);\n            output.push('*');\n        }\n\n        for (parameter, default) in &py_sig.keyword_only_parameters {\n            maybe_push_comma(&mut output);\n            output.push_str(parameter);\n            if let Some(expr) = default {\n                output.push('=');\n                output.push_str(&expr_to_python(expr));\n            }\n        }\n\n        if let Some(kwargs) = &py_sig.kwargs {\n            maybe_push_comma(&mut output);\n            output.push_str(\"**\");\n            output.push_str(kwargs);\n        }\n\n        output.push(')');\n        output\n    }\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/pyfunction.rs",
    "content": "use crate::attributes::KeywordAttribute;\nuse crate::combine_errors::CombineErrors;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::introspection::{function_introspection_code, introspection_id_const};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::utils::get_doc;\nuse crate::utils::Ctx;\nuse crate::{\n    attributes::{\n        self, get_pyo3_options, take_attributes, take_pyo3_options, CrateAttribute,\n        FromPyWithAttribute, NameAttribute, TextSignatureAttribute,\n    },\n    method::{self, CallingConvention, FnArg},\n    pymethod::check_generic,\n};\nuse proc_macro2::{Span, TokenStream};\nuse quote::{format_ident, quote, ToTokens};\nuse std::cmp::PartialEq;\nuse std::ffi::CString;\n#[cfg(feature = \"experimental-inspect\")]\nuse std::iter::empty;\nuse syn::parse::{Parse, ParseStream};\nuse syn::punctuated::Punctuated;\nuse syn::LitCStr;\nuse syn::{ext::IdentExt, spanned::Spanned, LitStr, Path, Result, Token};\n\nmod signature;\n\npub use self::signature::{ConstructorAttribute, FunctionSignature, SignatureAttribute};\n\n#[derive(Clone, Debug)]\npub struct PyFunctionArgPyO3Attributes {\n    pub from_py_with: Option<FromPyWithAttribute>,\n    pub cancel_handle: Option<attributes::kw::cancel_handle>,\n}\n\nenum PyFunctionArgPyO3Attribute {\n    FromPyWith(FromPyWithAttribute),\n    CancelHandle(attributes::kw::cancel_handle),\n}\n\nimpl Parse for PyFunctionArgPyO3Attribute {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let lookahead = input.lookahead1();\n        if lookahead.peek(attributes::kw::cancel_handle) {\n            input.parse().map(PyFunctionArgPyO3Attribute::CancelHandle)\n        } else if lookahead.peek(attributes::kw::from_py_with) {\n            input.parse().map(PyFunctionArgPyO3Attribute::FromPyWith)\n        } else {\n            Err(lookahead.error())\n        }\n    }\n}\n\nimpl PyFunctionArgPyO3Attributes {\n    /// Parses #[pyo3(from_python_with = \"func\")]\n    pub fn from_attrs(attrs: &mut Vec<syn::Attribute>) -> syn::Result<Self> {\n        let mut attributes = PyFunctionArgPyO3Attributes {\n            from_py_with: None,\n            cancel_handle: None,\n        };\n        take_attributes(attrs, |attr| {\n            if let Some(pyo3_attrs) = get_pyo3_options(attr)? {\n                for attr in pyo3_attrs {\n                    match attr {\n                        PyFunctionArgPyO3Attribute::FromPyWith(from_py_with) => {\n                            ensure_spanned!(\n                                attributes.from_py_with.is_none(),\n                                from_py_with.span() => \"`from_py_with` may only be specified once per argument\"\n                            );\n                            attributes.from_py_with = Some(from_py_with);\n                        }\n                        PyFunctionArgPyO3Attribute::CancelHandle(cancel_handle) => {\n                            ensure_spanned!(\n                                attributes.cancel_handle.is_none(),\n                                cancel_handle.span() => \"`cancel_handle` may only be specified once per argument\"\n                            );\n                            attributes.cancel_handle = Some(cancel_handle);\n                        }\n                    }\n                    ensure_spanned!(\n                        attributes.from_py_with.is_none() || attributes.cancel_handle.is_none(),\n                        attributes.cancel_handle.unwrap().span() => \"`from_py_with` and `cancel_handle` cannot be specified together\"\n                    );\n                }\n                Ok(true)\n            } else {\n                Ok(false)\n            }\n        })?;\n        Ok(attributes)\n    }\n}\n\ntype PyFunctionWarningMessageAttribute = KeywordAttribute<attributes::kw::message, LitStr>;\ntype PyFunctionWarningCategoryAttribute = KeywordAttribute<attributes::kw::category, Path>;\n\npub struct PyFunctionWarningAttribute {\n    pub message: PyFunctionWarningMessageAttribute,\n    pub category: Option<PyFunctionWarningCategoryAttribute>,\n    pub span: Span,\n}\n\n#[derive(PartialEq, Clone)]\npub enum PyFunctionWarningCategory {\n    Path(Path),\n    UserWarning,\n    DeprecationWarning, // TODO: unused for now, intended for pyo3(deprecated) special-case\n}\n\n#[derive(Clone)]\npub struct PyFunctionWarning {\n    pub message: LitStr,\n    pub category: PyFunctionWarningCategory,\n    pub span: Span,\n}\n\nimpl From<PyFunctionWarningAttribute> for PyFunctionWarning {\n    fn from(value: PyFunctionWarningAttribute) -> Self {\n        Self {\n            message: value.message.value,\n            category: value\n                .category\n                .map_or(PyFunctionWarningCategory::UserWarning, |cat| {\n                    PyFunctionWarningCategory::Path(cat.value)\n                }),\n            span: value.span,\n        }\n    }\n}\n\npub trait WarningFactory {\n    fn build_py_warning(&self, ctx: &Ctx) -> TokenStream;\n    fn span(&self) -> Span;\n}\n\nimpl WarningFactory for PyFunctionWarning {\n    fn build_py_warning(&self, ctx: &Ctx) -> TokenStream {\n        let message = &self.message.value();\n        let c_message = LitCStr::new(\n            &CString::new(message.clone()).unwrap(),\n            Spanned::span(&message),\n        );\n        let pyo3_path = &ctx.pyo3_path;\n        let category = match &self.category {\n            PyFunctionWarningCategory::Path(path) => quote! {#path},\n            PyFunctionWarningCategory::UserWarning => {\n                quote! {#pyo3_path::exceptions::PyUserWarning}\n            }\n            PyFunctionWarningCategory::DeprecationWarning => {\n                quote! {#pyo3_path::exceptions::PyDeprecationWarning}\n            }\n        };\n        quote! {\n            #pyo3_path::PyErr::warn(py, &<#category as #pyo3_path::PyTypeInfo>::type_object(py), #c_message, 1)?;\n        }\n    }\n\n    fn span(&self) -> Span {\n        self.span\n    }\n}\n\nimpl<T: WarningFactory> WarningFactory for Vec<T> {\n    fn build_py_warning(&self, ctx: &Ctx) -> TokenStream {\n        let warnings = self.iter().map(|warning| warning.build_py_warning(ctx));\n\n        quote! {\n            #(#warnings)*\n        }\n    }\n\n    fn span(&self) -> Span {\n        self.iter()\n            .map(|val| val.span())\n            .reduce(|acc, span| acc.join(span).unwrap_or(acc))\n            .unwrap()\n    }\n}\n\nimpl Parse for PyFunctionWarningAttribute {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let mut message: Option<PyFunctionWarningMessageAttribute> = None;\n        let mut category: Option<PyFunctionWarningCategoryAttribute> = None;\n\n        let span = input.parse::<attributes::kw::warn>()?.span();\n\n        let content;\n        syn::parenthesized!(content in input);\n\n        while !content.is_empty() {\n            let lookahead = content.lookahead1();\n\n            if lookahead.peek(attributes::kw::message) {\n                message = content\n                    .parse::<PyFunctionWarningMessageAttribute>()\n                    .map(Some)?;\n            } else if lookahead.peek(attributes::kw::category) {\n                category = content\n                    .parse::<PyFunctionWarningCategoryAttribute>()\n                    .map(Some)?;\n            } else {\n                return Err(lookahead.error());\n            }\n\n            if content.peek(Token![,]) {\n                content.parse::<Token![,]>()?;\n            }\n        }\n\n        Ok(PyFunctionWarningAttribute {\n            message: message.ok_or(syn::Error::new(\n                content.span(),\n                \"missing `message` in `warn` attribute\",\n            ))?,\n            category,\n            span,\n        })\n    }\n}\n\nimpl ToTokens for PyFunctionWarningAttribute {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let message_tokens = self.message.to_token_stream();\n        let category_tokens = self\n            .category\n            .as_ref()\n            .map_or(quote! {}, |cat| cat.to_token_stream());\n\n        let token_stream = quote! {\n            warn(#message_tokens, #category_tokens)\n        };\n\n        tokens.extend(token_stream);\n    }\n}\n\n#[derive(Default)]\npub struct PyFunctionOptions {\n    pub pass_module: Option<attributes::kw::pass_module>,\n    pub name: Option<NameAttribute>,\n    pub signature: Option<SignatureAttribute>,\n    pub text_signature: Option<TextSignatureAttribute>,\n    pub krate: Option<CrateAttribute>,\n    pub warnings: Vec<PyFunctionWarning>,\n}\n\nimpl Parse for PyFunctionOptions {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let mut options = PyFunctionOptions::default();\n\n        let attrs = Punctuated::<PyFunctionOption, syn::Token![,]>::parse_terminated(input)?;\n        options.add_attributes(attrs)?;\n\n        Ok(options)\n    }\n}\n\npub enum PyFunctionOption {\n    Name(NameAttribute),\n    PassModule(attributes::kw::pass_module),\n    Signature(SignatureAttribute),\n    TextSignature(TextSignatureAttribute),\n    Crate(CrateAttribute),\n    Warning(PyFunctionWarningAttribute),\n}\n\nimpl Parse for PyFunctionOption {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let lookahead = input.lookahead1();\n        if lookahead.peek(attributes::kw::name) {\n            input.parse().map(PyFunctionOption::Name)\n        } else if lookahead.peek(attributes::kw::pass_module) {\n            input.parse().map(PyFunctionOption::PassModule)\n        } else if lookahead.peek(attributes::kw::signature) {\n            input.parse().map(PyFunctionOption::Signature)\n        } else if lookahead.peek(attributes::kw::text_signature) {\n            input.parse().map(PyFunctionOption::TextSignature)\n        } else if lookahead.peek(syn::Token![crate]) {\n            input.parse().map(PyFunctionOption::Crate)\n        } else if lookahead.peek(attributes::kw::warn) {\n            input.parse().map(PyFunctionOption::Warning)\n        } else {\n            Err(lookahead.error())\n        }\n    }\n}\n\nimpl PyFunctionOptions {\n    pub fn from_attrs(attrs: &mut Vec<syn::Attribute>) -> syn::Result<Self> {\n        let mut options = PyFunctionOptions::default();\n        options.add_attributes(take_pyo3_options(attrs)?)?;\n        Ok(options)\n    }\n\n    pub fn add_attributes(\n        &mut self,\n        attrs: impl IntoIterator<Item = PyFunctionOption>,\n    ) -> Result<()> {\n        macro_rules! set_option {\n            ($key:ident) => {\n                {\n                    ensure_spanned!(\n                        self.$key.is_none(),\n                        $key.span() => concat!(\"`\", stringify!($key), \"` may only be specified once\")\n                    );\n                    self.$key = Some($key);\n                }\n            };\n        }\n        for attr in attrs {\n            match attr {\n                PyFunctionOption::Name(name) => set_option!(name),\n                PyFunctionOption::PassModule(pass_module) => set_option!(pass_module),\n                PyFunctionOption::Signature(signature) => set_option!(signature),\n                PyFunctionOption::TextSignature(text_signature) => set_option!(text_signature),\n                PyFunctionOption::Crate(krate) => set_option!(krate),\n                PyFunctionOption::Warning(warning) => {\n                    self.warnings.push(warning.into());\n                }\n            }\n        }\n        Ok(())\n    }\n}\n\npub fn build_py_function(\n    ast: &mut syn::ItemFn,\n    mut options: PyFunctionOptions,\n) -> syn::Result<TokenStream> {\n    options.add_attributes(take_pyo3_options(&mut ast.attrs)?)?;\n    impl_wrap_pyfunction(ast, options)\n}\n\n/// Generates python wrapper over a function that allows adding it to a python module as a python\n/// function\npub fn impl_wrap_pyfunction(\n    func: &mut syn::ItemFn,\n    options: PyFunctionOptions,\n) -> syn::Result<TokenStream> {\n    check_generic(&func.sig)?;\n    let PyFunctionOptions {\n        pass_module,\n        name,\n        signature,\n        text_signature,\n        krate,\n        warnings,\n    } = options;\n\n    let ctx = &Ctx::new(&krate, Some(&func.sig));\n    let Ctx { pyo3_path, .. } = &ctx;\n\n    let python_name = name\n        .as_ref()\n        .map_or_else(|| &func.sig.ident, |name| &name.value.0)\n        .unraw();\n\n    let tp = if pass_module.is_some() {\n        let span = match func.sig.inputs.first() {\n            Some(syn::FnArg::Typed(first_arg)) => first_arg.ty.span(),\n            Some(syn::FnArg::Receiver(_)) | None => bail_spanned!(\n                func.sig.paren_token.span.join() => \"expected `&PyModule` or `Py<PyModule>` as first argument with `pass_module`\"\n            ),\n        };\n        method::FnType::FnModule(span)\n    } else {\n        method::FnType::FnStatic\n    };\n\n    let arguments = func\n        .sig\n        .inputs\n        .iter_mut()\n        .skip(if tp.skip_first_rust_argument_in_python_signature() {\n            1\n        } else {\n            0\n        })\n        .map(FnArg::parse)\n        .try_combine_syn_errors()?;\n\n    let signature = if let Some(signature) = signature {\n        FunctionSignature::from_arguments_and_attribute(arguments, signature)?\n    } else {\n        FunctionSignature::from_arguments(arguments)\n    };\n\n    let spec = method::FnSpec {\n        tp,\n        name: &func.sig.ident,\n        python_name,\n        signature,\n        text_signature,\n        asyncness: func.sig.asyncness,\n        unsafety: func.sig.unsafety,\n        warnings,\n        output: func.sig.output.clone(),\n    };\n\n    let vis = &func.vis;\n    let name = &func.sig.ident;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    let introspection = function_introspection_code(\n        pyo3_path,\n        Some(name),\n        &name.to_string(),\n        &spec.signature,\n        None,\n        func.sig.output.clone(),\n        empty(),\n        func.sig.asyncness.is_some(),\n        false,\n        get_doc(&func.attrs, None).as_ref(),\n        None,\n    );\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    let introspection = quote! {};\n    #[cfg(feature = \"experimental-inspect\")]\n    let introspection_id = introspection_id_const();\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    let introspection_id = quote! {};\n\n    let wrapper_ident = format_ident!(\"__pyfunction_{}\", spec.name);\n    if spec.asyncness.is_some() {\n        ensure_spanned!(\n            cfg!(feature = \"experimental-async\"),\n            spec.asyncness.span() => \"async functions are only supported with the `experimental-async` feature\"\n        );\n    }\n    let calling_convention = CallingConvention::from_signature(&spec.signature);\n    let wrapper = spec.get_wrapper_function(&wrapper_ident, None, calling_convention, ctx)?;\n    let methoddef = spec.get_methoddef(\n        wrapper_ident,\n        spec.get_doc(&func.attrs).as_ref(),\n        calling_convention,\n        ctx,\n    )?;\n\n    let wrapped_pyfunction = quote! {\n        // Create a module with the same name as the `#[pyfunction]` - this way `use <the function>`\n        // will actually bring both the module and the function into scope.\n        #[doc(hidden)]\n        #vis mod #name {\n            pub(crate) struct MakeDef;\n            pub static _PYO3_DEF: #pyo3_path::impl_::pyfunction::PyFunctionDef = MakeDef::_PYO3_DEF;\n            #introspection_id\n        }\n\n        // Generate the definition in the same scope as the original function -\n        // this avoids complications around the fact that the generated module has a different scope\n        // (and `super` doesn't always refer to the outer scope, e.g. if the `#[pyfunction] is\n        // inside a function body)\n        #[allow(unknown_lints, non_local_definitions)]\n        impl #name::MakeDef {\n            // We're using this to initialize a static, so it's fine.\n            #[allow(clippy::declare_interior_mutable_const)]\n            const _PYO3_DEF: #pyo3_path::impl_::pyfunction::PyFunctionDef =\n                #pyo3_path::impl_::pyfunction::PyFunctionDef::from_method_def(#methoddef);\n        }\n\n        #[allow(non_snake_case)]\n        #wrapper\n\n        #introspection\n    };\n    Ok(wrapped_pyfunction)\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/pyimpl.rs",
    "content": "use std::collections::HashSet;\n\nuse crate::combine_errors::CombineErrors;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::get_doc;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::introspection::{attribute_introspection_code, function_introspection_code};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::method::{FnSpec, FnType};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::py_expr::PyExpr;\nuse crate::utils::{has_attribute, has_attribute_with_namespace, Ctx, PyO3CratePath};\nuse crate::{\n    attributes::{take_pyo3_options, CrateAttribute},\n    konst::{ConstAttributes, ConstSpec},\n    pyfunction::PyFunctionOptions,\n    pymethod::{\n        self, is_proto_method, GeneratedPyMethod, MethodAndMethodDef, MethodAndSlotDef, PyMethod,\n    },\n};\nuse proc_macro2::TokenStream;\nuse quote::{format_ident, quote};\nuse syn::{\n    parse::{Parse, ParseStream},\n    spanned::Spanned,\n    ImplItemFn, Result,\n};\n#[cfg(feature = \"experimental-inspect\")]\nuse syn::{parse_quote, Ident, ReturnType};\n\n/// The mechanism used to collect `#[pymethods]` into the type object\n#[derive(Copy, Clone)]\npub enum PyClassMethodsType {\n    Specialization,\n    Inventory,\n}\n\nenum PyImplPyO3Option {\n    Crate(CrateAttribute),\n}\n\nimpl Parse for PyImplPyO3Option {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let lookahead = input.lookahead1();\n        if lookahead.peek(syn::Token![crate]) {\n            input.parse().map(PyImplPyO3Option::Crate)\n        } else {\n            Err(lookahead.error())\n        }\n    }\n}\n\n#[derive(Default)]\npub struct PyImplOptions {\n    krate: Option<CrateAttribute>,\n}\n\nimpl PyImplOptions {\n    pub fn from_attrs(attrs: &mut Vec<syn::Attribute>) -> Result<Self> {\n        let mut options: PyImplOptions = Default::default();\n\n        for option in take_pyo3_options(attrs)? {\n            match option {\n                PyImplPyO3Option::Crate(path) => options.set_crate(path)?,\n            }\n        }\n\n        Ok(options)\n    }\n\n    fn set_crate(&mut self, path: CrateAttribute) -> Result<()> {\n        ensure_spanned!(\n            self.krate.is_none(),\n            path.span() => \"`crate` may only be specified once\"\n        );\n\n        self.krate = Some(path);\n        Ok(())\n    }\n}\n\npub fn build_py_methods(\n    ast: &mut syn::ItemImpl,\n    methods_type: PyClassMethodsType,\n) -> syn::Result<TokenStream> {\n    if let Some((_, path, _)) = &ast.trait_ {\n        bail_spanned!(path.span() => \"#[pymethods] cannot be used on trait impl blocks\");\n    } else if ast.generics != Default::default() {\n        bail_spanned!(\n            ast.generics.span() =>\n            \"#[pymethods] cannot be used with lifetime parameters or generics\"\n        );\n    } else {\n        let options = PyImplOptions::from_attrs(&mut ast.attrs)?;\n        impl_methods(&ast.self_ty, &mut ast.items, methods_type, options)\n    }\n}\n\nfn check_pyfunction(pyo3_path: &PyO3CratePath, meth: &mut ImplItemFn) -> syn::Result<()> {\n    let mut error = None;\n\n    meth.attrs.retain(|attr| {\n        let attrs = [attr.clone()];\n\n        if has_attribute(&attrs, \"pyfunction\")\n            || has_attribute_with_namespace(&attrs, Some(pyo3_path),  &[\"pyfunction\"])\n            || has_attribute_with_namespace(&attrs, Some(pyo3_path),  &[\"prelude\", \"pyfunction\"]) {\n                error = Some(err_spanned!(meth.sig.span() => \"functions inside #[pymethods] do not need to be annotated with #[pyfunction]\"));\n                false\n        } else {\n            true\n        }\n    });\n\n    error.map_or(Ok(()), Err)\n}\n\npub fn impl_methods(\n    ty: &syn::Type,\n    impls: &mut [syn::ImplItem],\n    methods_type: PyClassMethodsType,\n    options: PyImplOptions,\n) -> syn::Result<TokenStream> {\n    let mut extra_fragments = Vec::new();\n    let mut proto_impls = Vec::new();\n    let mut methods = Vec::new();\n    let mut associated_methods = Vec::new();\n\n    let mut implemented_proto_fragments = HashSet::new();\n\n    let _: Vec<()> = impls\n        .iter_mut()\n        .map(|iimpl| {\n            match iimpl {\n                syn::ImplItem::Fn(meth) => {\n                    let ctx = &Ctx::new(&options.krate, Some(&meth.sig));\n                    let mut fun_options = PyFunctionOptions::from_attrs(&mut meth.attrs)?;\n                    fun_options.krate = fun_options.krate.or_else(|| options.krate.clone());\n\n                    check_pyfunction(&ctx.pyo3_path, meth)?;\n                    let method = PyMethod::parse(&mut meth.sig, &mut meth.attrs, fun_options)?;\n                    #[cfg(feature = \"experimental-inspect\")]\n                    extra_fragments.push(method_introspection_code(\n                        &method.spec,\n                        &meth.attrs,\n                        ty,\n                        method.is_returning_not_implemented_on_extraction_error(),\n                        ctx,\n                    ));\n                    match pymethod::gen_py_method(ty, method, &meth.attrs, ctx)? {\n                        GeneratedPyMethod::Method(MethodAndMethodDef {\n                            associated_method,\n                            method_def,\n                        }) => {\n                            let attrs = get_cfg_attributes(&meth.attrs);\n                            associated_methods.push(quote!(#(#attrs)* #associated_method));\n                            methods.push(quote!(#(#attrs)* #method_def));\n                        }\n                        GeneratedPyMethod::SlotTraitImpl(method_name, token_stream) => {\n                            implemented_proto_fragments.insert(method_name);\n                            let attrs = get_cfg_attributes(&meth.attrs);\n                            extra_fragments.push(quote!(#(#attrs)* #token_stream));\n                        }\n                        GeneratedPyMethod::Proto(MethodAndSlotDef {\n                            associated_method,\n                            slot_def,\n                        }) => {\n                            let attrs = get_cfg_attributes(&meth.attrs);\n                            proto_impls.push(quote!(#(#attrs)* #slot_def));\n                            associated_methods.push(quote!(#(#attrs)* #associated_method));\n                        }\n                    }\n                }\n                syn::ImplItem::Const(konst) => {\n                    let ctx = &Ctx::new(&options.krate, None);\n                    #[cfg(feature = \"experimental-inspect\")]\n                    let doc = get_doc(&konst.attrs, None);\n                    let attributes = ConstAttributes::from_attrs(&mut konst.attrs)?;\n                    if attributes.is_class_attr {\n                        let spec = ConstSpec {\n                            rust_ident: konst.ident.clone(),\n                            attributes,\n                            #[cfg(feature = \"experimental-inspect\")]\n                            expr: Some(konst.expr.clone()),\n                            #[cfg(feature = \"experimental-inspect\")]\n                            ty: konst.ty.clone(),\n                            #[cfg(feature = \"experimental-inspect\")]\n                            doc,\n                        };\n                        let attrs = get_cfg_attributes(&konst.attrs);\n                        let MethodAndMethodDef {\n                            associated_method,\n                            method_def,\n                        } = gen_py_const(ty, &spec, ctx);\n                        methods.push(quote!(#(#attrs)* #method_def));\n                        associated_methods.push(quote!(#(#attrs)* #associated_method));\n                        if is_proto_method(&spec.python_name().to_string()) {\n                            // If this is a known protocol method e.g. __contains__, then allow this\n                            // symbol even though it's not an uppercase constant.\n                            konst\n                                .attrs\n                                .push(syn::parse_quote!(#[allow(non_upper_case_globals)]));\n                        }\n                    }\n                }\n                syn::ImplItem::Macro(m) => bail_spanned!(\n                    m.span() =>\n                    \"macros cannot be used as items in `#[pymethods]` impl blocks\\n\\\n                    = note: this was previously accepted and ignored\"\n                ),\n                _ => {}\n            }\n            Ok(())\n        })\n        .try_combine_syn_errors()?;\n\n    let ctx = &Ctx::new(&options.krate, None);\n\n    add_shared_proto_slots(ty, &mut proto_impls, implemented_proto_fragments, ctx);\n\n    let items = match methods_type {\n        PyClassMethodsType::Specialization => impl_py_methods(ty, methods, proto_impls, ctx),\n        PyClassMethodsType::Inventory => submit_methods_inventory(ty, methods, proto_impls, ctx),\n    };\n\n    Ok(quote! {\n        #(#extra_fragments)*\n\n        #items\n\n        #[doc(hidden)]\n        #[allow(non_snake_case)]\n        impl #ty {\n            #(#associated_methods)*\n        }\n    })\n}\n\npub fn gen_py_const(cls: &syn::Type, spec: &ConstSpec, ctx: &Ctx) -> MethodAndMethodDef {\n    let member = &spec.rust_ident;\n    let wrapper_ident = format_ident!(\"__pymethod_{}__\", member);\n    let python_name = spec.null_terminated_python_name();\n    let Ctx { pyo3_path, .. } = ctx;\n\n    let associated_method = quote! {\n        fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::Py<#pyo3_path::PyAny>> {\n            #pyo3_path::IntoPyObjectExt::into_py_any(#cls::#member, py)\n        }\n    };\n\n    let method_def = quote! {\n        #pyo3_path::impl_::pymethods::PyMethodDefType::ClassAttribute({\n            #pyo3_path::impl_::pymethods::PyClassAttributeDef::new(\n                #python_name,\n                #cls::#wrapper_ident\n            )\n        })\n    };\n\n    #[cfg_attr(not(feature = \"experimental-inspect\"), allow(unused_mut))]\n    let mut def = MethodAndMethodDef {\n        associated_method,\n        method_def,\n    };\n\n    #[cfg(feature = \"experimental-inspect\")]\n    def.add_introspection(attribute_introspection_code(\n        &ctx.pyo3_path,\n        Some(cls),\n        spec.python_name().to_string(),\n        spec.expr\n            .as_ref()\n            .map_or_else(PyExpr::ellipsis, PyExpr::constant_from_expression),\n        spec.ty.clone(),\n        spec.doc.as_ref(),\n        true,\n    ));\n\n    def\n}\n\nfn impl_py_methods(\n    ty: &syn::Type,\n    methods: Vec<TokenStream>,\n    proto_impls: Vec<TokenStream>,\n    ctx: &Ctx,\n) -> TokenStream {\n    let Ctx { pyo3_path, .. } = ctx;\n    quote! {\n        #[allow(unknown_lints, non_local_definitions)]\n        impl #pyo3_path::impl_::pyclass::PyMethods<#ty>\n            for #pyo3_path::impl_::pyclass::PyClassImplCollector<#ty>\n        {\n            fn py_methods(self) -> &'static #pyo3_path::impl_::pyclass::PyClassItems {\n                static ITEMS: #pyo3_path::impl_::pyclass::PyClassItems = #pyo3_path::impl_::pyclass::PyClassItems {\n                    methods: &[#(#methods),*],\n                    slots: &[#(#proto_impls),*]\n                };\n                &ITEMS\n            }\n        }\n    }\n}\n\nfn add_shared_proto_slots(\n    ty: &syn::Type,\n    proto_impls: &mut Vec<TokenStream>,\n    mut implemented_proto_fragments: HashSet<String>,\n    ctx: &Ctx,\n) {\n    let Ctx { pyo3_path, .. } = ctx;\n    macro_rules! try_add_shared_slot {\n        ($slot:ident, $($fragments:literal),*) => {{\n            let mut implemented = false;\n            $(implemented |= implemented_proto_fragments.remove($fragments));*;\n            if implemented {\n                proto_impls.push(quote! { #pyo3_path::impl_::pyclass::$slot!(#ty) })\n            }\n        }};\n    }\n\n    try_add_shared_slot!(\n        generate_pyclass_getattro_slot,\n        \"__getattribute__\",\n        \"__getattr__\"\n    );\n    try_add_shared_slot!(generate_pyclass_setattr_slot, \"__setattr__\", \"__delattr__\");\n    try_add_shared_slot!(generate_pyclass_setdescr_slot, \"__set__\", \"__delete__\");\n    try_add_shared_slot!(generate_pyclass_setitem_slot, \"__setitem__\", \"__delitem__\");\n    try_add_shared_slot!(generate_pyclass_add_slot, \"__add__\", \"__radd__\");\n    try_add_shared_slot!(generate_pyclass_sub_slot, \"__sub__\", \"__rsub__\");\n    try_add_shared_slot!(generate_pyclass_mul_slot, \"__mul__\", \"__rmul__\");\n    try_add_shared_slot!(generate_pyclass_mod_slot, \"__mod__\", \"__rmod__\");\n    try_add_shared_slot!(generate_pyclass_divmod_slot, \"__divmod__\", \"__rdivmod__\");\n    try_add_shared_slot!(generate_pyclass_lshift_slot, \"__lshift__\", \"__rlshift__\");\n    try_add_shared_slot!(generate_pyclass_rshift_slot, \"__rshift__\", \"__rrshift__\");\n    try_add_shared_slot!(generate_pyclass_and_slot, \"__and__\", \"__rand__\");\n    try_add_shared_slot!(generate_pyclass_or_slot, \"__or__\", \"__ror__\");\n    try_add_shared_slot!(generate_pyclass_xor_slot, \"__xor__\", \"__rxor__\");\n    try_add_shared_slot!(generate_pyclass_matmul_slot, \"__matmul__\", \"__rmatmul__\");\n    try_add_shared_slot!(generate_pyclass_truediv_slot, \"__truediv__\", \"__rtruediv__\");\n    try_add_shared_slot!(\n        generate_pyclass_floordiv_slot,\n        \"__floordiv__\",\n        \"__rfloordiv__\"\n    );\n    try_add_shared_slot!(generate_pyclass_pow_slot, \"__pow__\", \"__rpow__\");\n    try_add_shared_slot!(\n        generate_pyclass_richcompare_slot,\n        \"__lt__\",\n        \"__le__\",\n        \"__eq__\",\n        \"__ne__\",\n        \"__gt__\",\n        \"__ge__\"\n    );\n\n    // if this assertion trips, a slot fragment has been implemented which has not been added in the\n    // list above\n    assert!(implemented_proto_fragments.is_empty());\n}\n\nfn submit_methods_inventory(\n    ty: &syn::Type,\n    methods: Vec<TokenStream>,\n    proto_impls: Vec<TokenStream>,\n    ctx: &Ctx,\n) -> TokenStream {\n    let Ctx { pyo3_path, .. } = ctx;\n    quote! {\n        #pyo3_path::inventory::submit! {\n            type Inventory = <#ty as #pyo3_path::impl_::pyclass::PyClassImpl>::Inventory;\n            Inventory::new(#pyo3_path::impl_::pyclass::PyClassItems { methods: &[#(#methods),*], slots: &[#(#proto_impls),*] })\n        }\n    }\n}\n\npub(crate) fn get_cfg_attributes(attrs: &[syn::Attribute]) -> Vec<&syn::Attribute> {\n    attrs\n        .iter()\n        .filter(|attr| attr.path().is_ident(\"cfg\"))\n        .collect()\n}\n\n#[cfg(feature = \"experimental-inspect\")]\npub fn method_introspection_code(\n    spec: &FnSpec<'_>,\n    attrs: &[syn::Attribute],\n    parent: &syn::Type,\n    is_returning_not_implemented_on_extraction_error: bool,\n    ctx: &Ctx,\n) -> TokenStream {\n    let Ctx { pyo3_path, .. } = ctx;\n\n    let name = spec.python_name.to_string();\n\n    // __richcmp__ special case\n    if name == \"__richcmp__\" {\n        // We expend into each individual method\n        return [\"__eq__\", \"__ne__\", \"__lt__\", \"__le__\", \"__gt__\", \"__ge__\"]\n            .into_iter()\n            .map(|method_name| {\n                let mut spec = (*spec).clone();\n                spec.python_name = Ident::new(method_name, spec.python_name.span());\n                // We remove the CompareOp arg, this is safe because the signature is always the same\n                // First the other value to compare with then the CompareOp\n                // We cant to keep the first argument type, hence this hack\n                spec.signature.arguments.pop();\n                spec.signature.python_signature.positional_parameters.pop();\n                method_introspection_code(\n                    &spec,\n                    attrs,\n                    parent,\n                    is_returning_not_implemented_on_extraction_error,\n                    ctx,\n                )\n            })\n            .collect();\n    }\n    // We map or ignore some magic methods\n    // TODO: this might create a naming conflict\n    let name = match name.as_str() {\n        \"__concat__\" => \"__add__\".into(),\n        \"__repeat__\" => \"__mul__\".into(),\n        \"__inplace_concat__\" => \"__iadd__\".into(),\n        \"__inplace_repeat__\" => \"__imul__\".into(),\n        \"__getbuffer__\" | \"__releasebuffer__\" | \"__traverse__\" | \"__clear__\" => return quote! {},\n        _ => name,\n    };\n\n    // We introduce self/cls argument and setup decorators\n    let mut first_argument = None;\n    let mut decorators = Vec::new();\n    match &spec.tp {\n        FnType::Getter(_) => {\n            first_argument = Some(\"self\");\n            decorators.push(PyExpr::builtin(\"property\"));\n        }\n        FnType::Setter(_) => {\n            first_argument = Some(\"self\");\n            decorators.push(PyExpr::attribute(\n                PyExpr::attribute(PyExpr::from_type(parent.clone(), None), name.clone()),\n                \"setter\",\n            ));\n        }\n        FnType::Deleter(_) => {\n            first_argument = Some(\"self\");\n            decorators.push(PyExpr::attribute(\n                PyExpr::attribute(PyExpr::from_type(parent.clone(), None), name.clone()),\n                \"deleter\",\n            ));\n        }\n        FnType::Fn(_) => {\n            first_argument = Some(\"self\");\n        }\n        FnType::FnClass(_) => {\n            first_argument = Some(\"cls\");\n            if spec.python_name != \"__new__\" {\n                // special case __new__ - does not get the decorator\n                decorators.push(PyExpr::builtin(\"classmethod\"));\n            }\n        }\n        FnType::FnStatic => {\n            if spec.python_name != \"__new__\" {\n                decorators.push(PyExpr::builtin(\"staticmethod\"));\n            } else {\n                // special case __new__ - does not get the decorator and gets first argument\n                first_argument = Some(\"cls\");\n            }\n        }\n        FnType::FnModule(_) => (), // TODO: not sure this can happen\n        FnType::ClassAttribute => {\n            // We return an attribute because there is no decorator for this case\n            return attribute_introspection_code(\n                pyo3_path,\n                Some(parent),\n                name,\n                PyExpr::ellipsis(),\n                if let ReturnType::Type(_, t) = &spec.output {\n                    (**t).clone()\n                } else {\n                    parse_quote!(#pyo3_path::Py<#pyo3_path::types::PyNone>)\n                },\n                get_doc(attrs, None).as_ref(),\n                true,\n            );\n        }\n    }\n    let return_type = if spec.python_name == \"__new__\" {\n        // Hack to return Self while implementing IntoPyObject\n        parse_quote!(-> #pyo3_path::PyRef<Self>)\n    } else {\n        spec.output.clone()\n    };\n    function_introspection_code(\n        pyo3_path,\n        None,\n        &name,\n        &spec.signature,\n        first_argument,\n        return_type,\n        decorators,\n        spec.asyncness.is_some(),\n        is_returning_not_implemented_on_extraction_error,\n        get_doc(attrs, None).as_ref(),\n        Some(parent),\n    )\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/pymethod.rs",
    "content": "use std::borrow::Cow;\nuse std::ffi::CString;\n\nuse crate::attributes::{FromPyWithAttribute, NameAttribute, RenamingRule};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::introspection::unique_element_id;\nuse crate::method::{CallingConvention, ExtractErrorMode, PyArg};\nuse crate::params::{impl_arg_params, impl_regular_arg_param, Holders};\nuse crate::pyfunction::WarningFactory;\nuse crate::utils::PythonDoc;\nuse crate::utils::{Ctx, StaticIdent};\nuse crate::{\n    method::{FnArg, FnSpec, FnType, SelfType},\n    pyfunction::PyFunctionOptions,\n};\nuse crate::{quotes, utils};\nuse proc_macro2::{Span, TokenStream};\nuse quote::{format_ident, quote, quote_spanned, ToTokens};\nuse syn::{ext::IdentExt, spanned::Spanned, Field, Ident, Result};\nuse syn::{parse_quote, LitCStr};\n\n/// Generated code for a single pymethod item.\npub struct MethodAndMethodDef {\n    /// The implementation of the Python wrapper for the pymethod\n    pub associated_method: TokenStream,\n    /// The method def which will be used to register this pymethod\n    pub method_def: TokenStream,\n}\n\n#[cfg(feature = \"experimental-inspect\")]\nimpl MethodAndMethodDef {\n    pub fn add_introspection(&mut self, data: TokenStream) {\n        let const_name = format_ident!(\"_{}\", unique_element_id()); // We need an explicit name here\n        self.associated_method.extend(quote! {\n            const #const_name: () = {\n                #data\n            };\n        });\n    }\n}\n\n/// Generated code for a single pymethod item which is registered by a slot.\npub struct MethodAndSlotDef {\n    /// The implementation of the Python wrapper for the pymethod\n    pub associated_method: TokenStream,\n    /// The slot def which will be used to register this pymethod\n    pub slot_def: TokenStream,\n}\n\n#[cfg(feature = \"experimental-inspect\")]\nimpl MethodAndSlotDef {\n    pub fn add_introspection(&mut self, data: TokenStream) {\n        let const_name = format_ident!(\"_{}\", unique_element_id()); // We need an explicit name here\n        self.associated_method.extend(quote! {\n            const #const_name: () = {\n                #data\n            };\n        });\n    }\n}\n\npub enum GeneratedPyMethod {\n    Method(MethodAndMethodDef),\n    Proto(MethodAndSlotDef),\n    SlotTraitImpl(String, TokenStream),\n}\n\npub struct PyMethod<'a> {\n    kind: PyMethodKind,\n    method_name: String,\n    pub spec: FnSpec<'a>,\n}\n\nenum PyMethodKind {\n    Fn,\n    Proto(PyMethodProtoKind),\n}\n\nimpl PyMethodKind {\n    fn from_name(name: &str) -> Self {\n        match name {\n            // Protocol implemented through slots\n            \"__new__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__NEW__)),\n            \"__init__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INIT__)),\n            \"__str__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__STR__)),\n            \"__repr__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__REPR__)),\n            \"__hash__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__HASH__)),\n            \"__richcmp__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__RICHCMP__)),\n            \"__get__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__GET__)),\n            \"__iter__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ITER__)),\n            \"__next__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__NEXT__)),\n            \"__await__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__AWAIT__)),\n            \"__aiter__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__AITER__)),\n            \"__anext__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ANEXT__)),\n            \"__len__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__LEN__)),\n            \"__contains__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__CONTAINS__)),\n            \"__concat__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__CONCAT__)),\n            \"__repeat__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__REPEAT__)),\n            \"__inplace_concat__\" => {\n                PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INPLACE_CONCAT__))\n            }\n            \"__inplace_repeat__\" => {\n                PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INPLACE_REPEAT__))\n            }\n            \"__getitem__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__GETITEM__)),\n            \"__pos__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__POS__)),\n            \"__neg__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__NEG__)),\n            \"__abs__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ABS__)),\n            \"__invert__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INVERT__)),\n            \"__index__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INDEX__)),\n            \"__int__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INT__)),\n            \"__float__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__FLOAT__)),\n            \"__bool__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__BOOL__)),\n            \"__iadd__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IADD__)),\n            \"__isub__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ISUB__)),\n            \"__imul__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IMUL__)),\n            \"__imatmul__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IMATMUL__)),\n            \"__itruediv__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ITRUEDIV__)),\n            \"__ifloordiv__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IFLOORDIV__)),\n            \"__imod__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IMOD__)),\n            \"__ipow__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IPOW__)),\n            \"__ilshift__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__ILSHIFT__)),\n            \"__irshift__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IRSHIFT__)),\n            \"__iand__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IAND__)),\n            \"__ixor__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IXOR__)),\n            \"__ior__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__IOR__)),\n            \"__getbuffer__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__GETBUFFER__)),\n            \"__releasebuffer__\" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__RELEASEBUFFER__)),\n            // Protocols implemented through traits\n            \"__getattribute__\" => {\n                PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__GETATTRIBUTE__))\n            }\n            \"__getattr__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__GETATTR__)),\n            \"__setattr__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__SETATTR__)),\n            \"__delattr__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__DELATTR__)),\n            \"__set__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__SET__)),\n            \"__delete__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__DELETE__)),\n            \"__setitem__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__SETITEM__)),\n            \"__delitem__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__DELITEM__)),\n            \"__add__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__ADD__)),\n            \"__radd__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RADD__)),\n            \"__sub__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__SUB__)),\n            \"__rsub__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RSUB__)),\n            \"__mul__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__MUL__)),\n            \"__rmul__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RMUL__)),\n            \"__matmul__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__MATMUL__)),\n            \"__rmatmul__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RMATMUL__)),\n            \"__floordiv__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__FLOORDIV__)),\n            \"__rfloordiv__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RFLOORDIV__)),\n            \"__truediv__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__TRUEDIV__)),\n            \"__rtruediv__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RTRUEDIV__)),\n            \"__divmod__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__DIVMOD__)),\n            \"__rdivmod__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RDIVMOD__)),\n            \"__mod__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__MOD__)),\n            \"__rmod__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RMOD__)),\n            \"__lshift__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__LSHIFT__)),\n            \"__rlshift__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RLSHIFT__)),\n            \"__rshift__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RSHIFT__)),\n            \"__rrshift__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RRSHIFT__)),\n            \"__and__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__AND__)),\n            \"__rand__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RAND__)),\n            \"__xor__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__XOR__)),\n            \"__rxor__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RXOR__)),\n            \"__or__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__OR__)),\n            \"__ror__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__ROR__)),\n            \"__pow__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__POW__)),\n            \"__rpow__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__RPOW__)),\n            \"__lt__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__LT__)),\n            \"__le__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__LE__)),\n            \"__eq__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__EQ__)),\n            \"__ne__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__NE__)),\n            \"__gt__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__GT__)),\n            \"__ge__\" => PyMethodKind::Proto(PyMethodProtoKind::SlotFragment(&__GE__)),\n            // Some tricky protocols which don't fit the pattern of the rest\n            \"__call__\" => PyMethodKind::Proto(PyMethodProtoKind::Call),\n            \"__traverse__\" => PyMethodKind::Proto(PyMethodProtoKind::Traverse),\n            \"__clear__\" => PyMethodKind::Proto(PyMethodProtoKind::Clear),\n            // Not a proto\n            _ => PyMethodKind::Fn,\n        }\n    }\n}\n\nenum PyMethodProtoKind {\n    Slot(&'static SlotDef),\n    Call,\n    Traverse,\n    Clear,\n    SlotFragment(&'static SlotFragmentDef),\n}\n\nimpl<'a> PyMethod<'a> {\n    pub fn parse(\n        sig: &'a mut syn::Signature,\n        meth_attrs: &mut Vec<syn::Attribute>,\n        options: PyFunctionOptions,\n    ) -> Result<Self> {\n        check_generic(sig)?;\n        ensure_function_options_valid(&options)?;\n        let spec = FnSpec::parse(sig, meth_attrs, options)?;\n\n        let method_name = spec.python_name.to_string();\n        let kind = PyMethodKind::from_name(&method_name);\n\n        Ok(Self {\n            kind,\n            method_name,\n            spec,\n        })\n    }\n\n    #[cfg(feature = \"experimental-inspect\")]\n    pub fn is_returning_not_implemented_on_extraction_error(&self) -> bool {\n        match &self.kind {\n            PyMethodKind::Fn => false,\n            PyMethodKind::Proto(proto) => match proto {\n                PyMethodProtoKind::Slot(slot) => {\n                    matches!(slot.extract_error_mode, ExtractErrorMode::NotImplemented)\n                }\n                PyMethodProtoKind::SlotFragment(slot) => {\n                    matches!(slot.extract_error_mode, ExtractErrorMode::NotImplemented)\n                }\n                PyMethodProtoKind::Call\n                | PyMethodProtoKind::Traverse\n                | PyMethodProtoKind::Clear => false,\n            },\n        }\n    }\n}\n\npub fn is_proto_method(name: &str) -> bool {\n    match PyMethodKind::from_name(name) {\n        PyMethodKind::Fn => false,\n        PyMethodKind::Proto(_) => true,\n    }\n}\n\npub fn gen_py_method(\n    cls: &syn::Type,\n    method: PyMethod<'_>,\n    meth_attrs: &[syn::Attribute],\n    ctx: &Ctx,\n) -> Result<GeneratedPyMethod> {\n    let spec = &method.spec;\n\n    if spec.asyncness.is_some() {\n        ensure_spanned!(\n            cfg!(feature = \"experimental-async\"),\n            spec.asyncness.span() => \"async functions are only supported with the `experimental-async` feature\"\n        );\n    }\n\n    Ok(match (method.kind, &spec.tp) {\n        // Class attributes go before protos so that class attributes can be used to set proto\n        // method to None.\n        (_, FnType::ClassAttribute) => {\n            GeneratedPyMethod::Method(impl_py_class_attribute(cls, spec, ctx)?)\n        }\n        (PyMethodKind::Proto(proto_kind), _) => {\n            ensure_no_forbidden_protocol_attributes(&proto_kind, spec, &method.method_name)?;\n            match proto_kind {\n                PyMethodProtoKind::Slot(slot_def) => {\n                    let slot = slot_def.generate_type_slot(cls, spec, &method.method_name, ctx)?;\n                    GeneratedPyMethod::Proto(slot)\n                }\n                PyMethodProtoKind::Call => {\n                    GeneratedPyMethod::Proto(impl_call_slot(cls, spec, ctx)?)\n                }\n                PyMethodProtoKind::Traverse => {\n                    GeneratedPyMethod::Proto(impl_traverse_slot(cls, spec, ctx)?)\n                }\n                PyMethodProtoKind::Clear => {\n                    GeneratedPyMethod::Proto(impl_clear_slot(cls, spec, ctx)?)\n                }\n                PyMethodProtoKind::SlotFragment(slot_fragment_def) => {\n                    let proto = slot_fragment_def.generate_pyproto_fragment(cls, spec, ctx)?;\n                    GeneratedPyMethod::SlotTraitImpl(method.method_name, proto)\n                }\n            }\n        }\n        // ordinary functions (with some specialties)\n        (_, FnType::Fn(_) | FnType::FnClass(_) | FnType::FnStatic) => GeneratedPyMethod::Method(\n            impl_py_method_def(cls, spec, spec.get_doc(meth_attrs).as_ref(), ctx)?,\n        ),\n        (_, FnType::Getter(self_type)) => GeneratedPyMethod::Method(impl_py_getter_def(\n            cls,\n            PropertyType::Function {\n                self_type,\n                spec,\n                doc: spec.get_doc(meth_attrs),\n            },\n            ctx,\n        )?),\n        (_, FnType::Setter(self_type)) => GeneratedPyMethod::Method(impl_py_setter_def(\n            cls,\n            PropertyType::Function {\n                self_type,\n                spec,\n                doc: spec.get_doc(meth_attrs),\n            },\n            ctx,\n        )?),\n        (_, FnType::Deleter(self_type)) => GeneratedPyMethod::Method(impl_py_deleter_def(\n            cls,\n            self_type,\n            spec,\n            spec.get_doc(meth_attrs),\n            ctx,\n        )?),\n        (_, FnType::FnModule(_)) => {\n            unreachable!(\"methods cannot be FnModule\")\n        }\n    })\n}\n\npub fn check_generic(sig: &syn::Signature) -> syn::Result<()> {\n    let err_msg = |typ| format!(\"Python functions cannot have generic {typ} parameters\");\n    for param in &sig.generics.params {\n        match param {\n            syn::GenericParam::Lifetime(_) => {}\n            syn::GenericParam::Type(_) => bail_spanned!(param.span() => err_msg(\"type\")),\n            syn::GenericParam::Const(_) => bail_spanned!(param.span() => err_msg(\"const\")),\n        }\n    }\n    Ok(())\n}\n\nfn ensure_function_options_valid(options: &PyFunctionOptions) -> syn::Result<()> {\n    if let Some(pass_module) = &options.pass_module {\n        bail_spanned!(pass_module.span() => \"`pass_module` cannot be used on Python methods\");\n    }\n    Ok(())\n}\n\nfn ensure_no_forbidden_protocol_attributes(\n    proto_kind: &PyMethodProtoKind,\n    spec: &FnSpec<'_>,\n    method_name: &str,\n) -> syn::Result<()> {\n    if let Some(signature) = &spec.signature.attribute {\n        // __new__, __init__ and __call__ are allowed to have a signature, but nothing else is.\n        if !matches!(\n            proto_kind,\n            PyMethodProtoKind::Slot(SlotDef {\n                calling_convention: SlotCallingConvention::TpNew | SlotCallingConvention::TpInit,\n                ..\n            })\n        ) && !matches!(proto_kind, PyMethodProtoKind::Call)\n        {\n            bail_spanned!(signature.kw.span() => format!(\"`signature` cannot be used with magic method `{}`\", method_name));\n        }\n    }\n    if let Some(text_signature) = &spec.text_signature {\n        // __new__ is also allowed a text_signature (no other proto method is)\n        if !matches!(\n            proto_kind,\n            PyMethodProtoKind::Slot(SlotDef {\n                calling_convention: SlotCallingConvention::TpNew,\n                ..\n            })\n        ) {\n            bail_spanned!(text_signature.kw.span() => format!(\"`text_signature` cannot be used with magic method `{}`\", method_name));\n        }\n    }\n    Ok(())\n}\n\npub fn impl_py_method_def(\n    cls: &syn::Type,\n    spec: &FnSpec<'_>,\n    doc: Option<&PythonDoc>,\n    ctx: &Ctx,\n) -> Result<MethodAndMethodDef> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let wrapper_ident = format_ident!(\"__pymethod_{}__\", spec.python_name);\n    let calling_convention = CallingConvention::from_signature(&spec.signature);\n    let associated_method =\n        spec.get_wrapper_function(&wrapper_ident, Some(cls), calling_convention, ctx)?;\n    let methoddef = spec.get_methoddef(\n        quote! { #cls::#wrapper_ident },\n        doc,\n        calling_convention,\n        ctx,\n    )?;\n    let method_def = quote! {\n        #pyo3_path::impl_::pymethods::PyMethodDefType::Method(#methoddef)\n    };\n    Ok(MethodAndMethodDef {\n        associated_method,\n        method_def,\n    })\n}\n\nfn impl_call_slot(cls: &syn::Type, spec: &FnSpec<'_>, ctx: &Ctx) -> Result<MethodAndSlotDef> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let wrapper_ident = syn::Ident::new(\"__pymethod___call____\", Span::call_site());\n    let associated_method =\n        spec.get_wrapper_function(&wrapper_ident, Some(cls), CallingConvention::Varargs, ctx)?;\n    let slot_def = quote! {\n        #pyo3_path::ffi::PyType_Slot {\n            slot: #pyo3_path::ffi::Py_tp_call,\n            pfunc: #pyo3_path::impl_::trampoline::get_trampoline_function!(ternaryfunc, #cls::#wrapper_ident) as _\n        }\n    };\n    Ok(MethodAndSlotDef {\n        associated_method,\n        slot_def,\n    })\n}\n\nfn impl_traverse_slot(\n    cls: &syn::Type,\n    spec: &FnSpec<'_>,\n    ctx: &Ctx,\n) -> syn::Result<MethodAndSlotDef> {\n    let Ctx { pyo3_path, .. } = ctx;\n    if let (Some(py_arg), _) = split_off_python_arg(&spec.signature.arguments) {\n        return Err(syn::Error::new_spanned(py_arg.ty, \"__traverse__ may not take `Python`. \\\n            Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` \\\n            should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is \\\n            prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic.\"));\n    }\n\n    // check that the receiver does not try to smuggle an (implicit) `Python` token into here\n    if let FnType::Fn(SelfType::TryFromBoundRef { span, .. })\n    | FnType::Fn(SelfType::Receiver {\n        mutable: true,\n        span,\n        ..\n    }) = spec.tp\n    {\n        bail_spanned! { span =>\n            \"__traverse__ may not take a receiver other than `&self`. Usually, an implementation of \\\n            `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` \\\n            should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is \\\n            prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic.\"\n        }\n    }\n\n    ensure_spanned!(\n        spec.warnings.is_empty(),\n        spec.warnings.span() => \"__traverse__ cannot be used with #[pyo3(warn)]\"\n    );\n\n    let rust_fn_ident = spec.name;\n\n    let associated_method = quote! {\n        pub unsafe extern \"C\" fn __pymethod_traverse__(\n            slf: *mut #pyo3_path::ffi::PyObject,\n            visit: #pyo3_path::ffi::visitproc,\n            arg: *mut ::std::ffi::c_void,\n        ) -> ::std::ffi::c_int {\n            #pyo3_path::impl_::pymethods::_call_traverse::<#cls>(slf, #cls::#rust_fn_ident, visit, arg, #cls::__pymethod_traverse__)\n        }\n    };\n    let slot_def = quote! {\n        #pyo3_path::ffi::PyType_Slot {\n            slot: #pyo3_path::ffi::Py_tp_traverse,\n            pfunc: #cls::__pymethod_traverse__ as #pyo3_path::ffi::traverseproc as _\n        }\n    };\n    Ok(MethodAndSlotDef {\n        associated_method,\n        slot_def,\n    })\n}\n\nfn impl_clear_slot(cls: &syn::Type, spec: &FnSpec<'_>, ctx: &Ctx) -> syn::Result<MethodAndSlotDef> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);\n    let self_type = match &spec.tp {\n        FnType::Fn(self_type) => self_type,\n        _ => bail_spanned!(spec.name.span() => \"expected instance method for `__clear__` function\"),\n    };\n    let mut holders = Holders::new();\n    let slf = self_type.receiver(cls, ExtractErrorMode::Raise, &mut holders, ctx);\n\n    if let [arg, ..] = args {\n        bail_spanned!(arg.ty().span() => \"`__clear__` function expected to have no arguments\");\n    }\n\n    let name = &spec.name;\n    let holders = holders.init_holders(ctx);\n    let fncall = if py_arg.is_some() {\n        quote!(#cls::#name(#slf, py))\n    } else {\n        quote!(#cls::#name(#slf))\n    };\n\n    let associated_method = quote! {\n        pub unsafe extern \"C\" fn __pymethod___clear____(\n            _slf: *mut #pyo3_path::ffi::PyObject,\n        ) -> ::std::ffi::c_int {\n            #pyo3_path::impl_::pymethods::_call_clear(_slf, |py, _slf| {\n                #holders\n                let result = #fncall;\n                let result = #pyo3_path::impl_::wrap::converter(&result).wrap(result)?;\n                ::std::result::Result::Ok(result)\n            }, #cls::__pymethod___clear____)\n        }\n    };\n    let slot_def = quote! {\n        #pyo3_path::ffi::PyType_Slot {\n            slot: #pyo3_path::ffi::Py_tp_clear,\n            pfunc: #cls::__pymethod___clear____ as #pyo3_path::ffi::inquiry as _\n        }\n    };\n    Ok(MethodAndSlotDef {\n        associated_method,\n        slot_def,\n    })\n}\n\npub(crate) fn impl_py_class_attribute(\n    cls: &syn::Type,\n    spec: &FnSpec<'_>,\n    ctx: &Ctx,\n) -> syn::Result<MethodAndMethodDef> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);\n    ensure_spanned!(\n        args.is_empty(),\n        args[0].ty().span() => \"#[classattr] can only have one argument (of type pyo3::Python)\"\n    );\n\n    ensure_spanned!(\n        spec.warnings.is_empty(),\n        spec.warnings.span()\n        => \"#[classattr] cannot be used with #[pyo3(warn)]\"\n    );\n\n    let name = &spec.name;\n    let fncall = if py_arg.is_some() {\n        quote!(function(py))\n    } else {\n        quote!(function())\n    };\n\n    let wrapper_ident = format_ident!(\"__pymethod_{}__\", name);\n    let python_name = spec.null_terminated_python_name();\n    let body = quotes::ok_wrap(fncall, ctx);\n\n    let associated_method = quote! {\n        fn #wrapper_ident(py: #pyo3_path::Python<'_>) -> #pyo3_path::PyResult<#pyo3_path::Py<#pyo3_path::PyAny>> {\n            let function = #cls::#name; // Shadow the method name to avoid #3017\n            let result = #body;\n            #pyo3_path::impl_::wrap::converter(&result).map_into_pyobject(py, result)\n        }\n    };\n\n    let method_def = quote! {\n        #pyo3_path::impl_::pymethods::PyMethodDefType::ClassAttribute({\n            #pyo3_path::impl_::pymethods::PyClassAttributeDef::new(\n                #python_name,\n                #cls::#wrapper_ident\n            )\n        })\n    };\n\n    Ok(MethodAndMethodDef {\n        associated_method,\n        method_def,\n    })\n}\n\nfn impl_call_setter(\n    cls: &syn::Type,\n    spec: &FnSpec<'_>,\n    self_type: &SelfType,\n    holders: &mut Holders,\n    ctx: &Ctx,\n) -> syn::Result<TokenStream> {\n    let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);\n    let slf = self_type.receiver(cls, ExtractErrorMode::Raise, holders, ctx);\n\n    if args.is_empty() {\n        bail_spanned!(spec.name.span() => \"setter function expected to have one argument\");\n    } else if args.len() > 1 {\n        bail_spanned!(\n            args[1].ty().span() =>\n            \"setter function can have at most two arguments ([pyo3::Python,] and value)\"\n        );\n    }\n\n    let name = &spec.name;\n    let fncall = if py_arg.is_some() {\n        quote!(#cls::#name(#slf, py, _val))\n    } else {\n        quote!(#cls::#name(#slf, _val))\n    };\n\n    Ok(fncall)\n}\n\n// Used here for PropertyType::Function, used in pyclass for descriptors.\npub fn impl_py_setter_def(\n    cls: &syn::Type,\n    property_type: PropertyType<'_>,\n    ctx: &Ctx,\n) -> Result<MethodAndMethodDef> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let python_name = property_type.null_terminated_python_name()?;\n    let doc = property_type.doc();\n    let mut holders = Holders::new();\n    let setter_impl = match property_type {\n        PropertyType::Descriptor {\n            field_index, field, ..\n        } => {\n            let slf = SelfType::Receiver {\n                mutable: true,\n                span: Span::call_site(),\n                non_null: true,\n            }\n            .receiver(cls, ExtractErrorMode::Raise, &mut holders, ctx);\n            if let Some(ident) = &field.ident {\n                // named struct field\n                quote!({ #slf.#ident = _val; })\n            } else {\n                // tuple struct field\n                let index = syn::Index::from(field_index);\n                quote!({ #slf.#index = _val; })\n            }\n        }\n        PropertyType::Function {\n            spec, self_type, ..\n        } => impl_call_setter(cls, spec, self_type, &mut holders, ctx)?,\n    };\n\n    let wrapper_ident = match property_type {\n        PropertyType::Descriptor {\n            field: syn::Field {\n                ident: Some(ident), ..\n            },\n            ..\n        } => {\n            format_ident!(\"__pymethod_set_{}__\", ident)\n        }\n        PropertyType::Descriptor { field_index, .. } => {\n            format_ident!(\"__pymethod_set_field_{}__\", field_index)\n        }\n        PropertyType::Function { spec, .. } => {\n            format_ident!(\"__pymethod_set_{}__\", spec.name)\n        }\n    };\n\n    let extract = match &property_type {\n        PropertyType::Function { spec, .. } => {\n            let (_, args) = split_off_python_arg(&spec.signature.arguments);\n            let value_arg = &args[0];\n            let (from_py_with, ident) =\n                if let Some(from_py_with) = &value_arg.from_py_with().as_ref().map(|f| &f.value) {\n                    let ident = syn::Ident::new(\"from_py_with\", from_py_with.span());\n                    (\n                        quote_spanned! { from_py_with.span() =>\n                            let #ident = #from_py_with;\n                        },\n                        ident,\n                    )\n                } else {\n                    (quote!(), syn::Ident::new(\"dummy\", Span::call_site()))\n                };\n\n            let arg = if let FnArg::Regular(arg) = &value_arg {\n                arg\n            } else {\n                bail_spanned!(value_arg.name().span() => \"The #[setter] value argument can't be *args, **kwargs or `cancel_handle`.\");\n            };\n\n            let extract = impl_regular_arg_param(\n                arg,\n                ident,\n                quote!(::std::option::Option::Some(_value)),\n                &mut holders,\n                ctx,\n            );\n\n            quote! {\n                #from_py_with\n                let _val = #extract;\n            }\n        }\n        PropertyType::Descriptor { field, .. } => {\n            let span = field.ty.span();\n            let name = field\n                .ident\n                .as_ref()\n                .map(|i| i.to_string())\n                .unwrap_or_default();\n\n            let holder = holders.push_holder(span);\n            quote! {\n                #[allow(unused_imports, reason = \"`Probe` trait used on negative case only\")]\n                use #pyo3_path::impl_::pyclass::Probe as _;\n                let _val = #pyo3_path::impl_::extract_argument::extract_argument(_value, &mut #holder, #name)?;\n            }\n        }\n    };\n\n    let mut cfg_attrs = TokenStream::new();\n    if let PropertyType::Descriptor { field, .. } = &property_type {\n        for attr in field\n            .attrs\n            .iter()\n            .filter(|attr| attr.path().is_ident(\"cfg\"))\n        {\n            attr.to_tokens(&mut cfg_attrs);\n        }\n    }\n\n    let warnings = if let PropertyType::Function { spec, .. } = &property_type {\n        spec.warnings.build_py_warning(ctx)\n    } else {\n        quote!()\n    };\n\n    let init_holders = holders.init_holders(ctx);\n    let associated_method = quote! {\n        #cfg_attrs\n        unsafe fn #wrapper_ident(\n            py: #pyo3_path::Python<'_>,\n            _slf: ::std::ptr::NonNull<#pyo3_path::ffi::PyObject>,\n            _value: ::std::ptr::NonNull<#pyo3_path::ffi::PyObject>,\n        ) -> #pyo3_path::PyResult<::std::ffi::c_int> {\n            use ::std::convert::Into;\n            let _value = #pyo3_path::impl_::extract_argument::cast_non_null_function_argument(py, _value);\n            #init_holders\n            #extract\n            #warnings\n            let result = #setter_impl;\n            #pyo3_path::impl_::callback::convert(py, result)\n        }\n    };\n\n    let doc = doc_to_optional_cstr(doc.as_deref(), ctx)?;\n    let method_def = quote! {\n        #cfg_attrs\n        #pyo3_path::impl_::pymethods::PyMethodDefType::Setter(\n            #pyo3_path::impl_::pymethods::PySetterDef::new(\n                #python_name,\n                #cls::#wrapper_ident,\n                #doc\n            )\n        )\n    };\n\n    Ok(MethodAndMethodDef {\n        associated_method,\n        method_def,\n    })\n}\n\nfn impl_call_getter(\n    cls: &syn::Type,\n    spec: &FnSpec<'_>,\n    self_type: &SelfType,\n    holders: &mut Holders,\n    ctx: &Ctx,\n) -> syn::Result<TokenStream> {\n    let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);\n    let slf = self_type.receiver(cls, ExtractErrorMode::Raise, holders, ctx);\n    ensure_spanned!(\n        args.is_empty(),\n        args[0].ty().span() => \"getter function can only have one argument (of type pyo3::Python)\"\n    );\n\n    let name = &spec.name;\n    let fncall = if py_arg.is_some() {\n        quote!(#cls::#name(#slf, py))\n    } else {\n        quote!(#cls::#name(#slf))\n    };\n\n    Ok(fncall)\n}\n\n// Used here for PropertyType::Function, used in pyclass for descriptors.\npub fn impl_py_getter_def(\n    cls: &syn::Type,\n    property_type: PropertyType<'_>,\n    ctx: &Ctx,\n) -> Result<MethodAndMethodDef> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let python_name = property_type.null_terminated_python_name()?;\n    let doc = property_type.doc();\n\n    let mut cfg_attrs = TokenStream::new();\n    if let PropertyType::Descriptor { field, .. } = &property_type {\n        for attr in field\n            .attrs\n            .iter()\n            .filter(|attr| attr.path().is_ident(\"cfg\"))\n        {\n            attr.to_tokens(&mut cfg_attrs);\n        }\n    }\n\n    let mut holders = Holders::new();\n    match property_type {\n        PropertyType::Descriptor {\n            field_index, field, ..\n        } => {\n            let ty = &field.ty;\n            let field = if let Some(ident) = &field.ident {\n                ident.to_token_stream()\n            } else {\n                syn::Index::from(field_index).to_token_stream()\n            };\n\n            let doc = doc_to_optional_cstr(doc.as_deref(), ctx)?;\n            let generator = quote_spanned! { ty.span() =>\n                GENERATOR.generate(#python_name, #doc)\n            };\n            // This is separate from `generator` so that the unsafe below does not inherit the span and thus does not\n            // trigger the `unsafe_code` lint\n            let method_def = quote! {\n                #cfg_attrs\n                {\n                    #[allow(unused_imports, reason = \"`Probe` trait used on negative case only\")]\n                    use #pyo3_path::impl_::pyclass::Probe as _;\n\n                    const GENERATOR: #pyo3_path::impl_::pyclass::PyClassGetterGenerator::<\n                        #cls,\n                        #ty,\n                        { ::std::mem::offset_of!(#cls, #field) },\n                        { #pyo3_path::impl_::pyclass::IsPyT::<#ty>::VALUE },\n                        { #pyo3_path::impl_::pyclass::IsIntoPyObjectRef::<#ty>::VALUE },\n                        { #pyo3_path::impl_::pyclass::IsIntoPyObject::<#ty>::VALUE },\n                    > = unsafe { #pyo3_path::impl_::pyclass::PyClassGetterGenerator::new() };\n                    #generator\n                }\n            };\n\n            Ok(MethodAndMethodDef {\n                associated_method: quote! {},\n                method_def,\n            })\n        }\n        // Forward to `IntoPyCallbackOutput`, to handle `#[getter]`s returning results.\n        PropertyType::Function {\n            spec, self_type, ..\n        } => {\n            let wrapper_ident = format_ident!(\"__pymethod_get_{}__\", spec.name);\n            let call = impl_call_getter(cls, spec, self_type, &mut holders, ctx)?;\n            let body = quote! {\n                #pyo3_path::impl_::callback::convert(py, #call)\n            };\n\n            let init_holders = holders.init_holders(ctx);\n            let warnings = spec.warnings.build_py_warning(ctx);\n\n            let associated_method = quote! {\n                #cfg_attrs\n                unsafe fn #wrapper_ident(\n                    py: #pyo3_path::Python<'_>,\n                    _slf: ::std::ptr::NonNull<#pyo3_path::ffi::PyObject>\n                ) -> #pyo3_path::PyResult<*mut #pyo3_path::ffi::PyObject> {\n                    #init_holders\n                    #warnings\n                    let result = #body;\n                    result\n                }\n            };\n\n            let doc = doc_to_optional_cstr(doc.as_deref(), ctx)?;\n            let method_def = quote! {\n                #cfg_attrs\n                #pyo3_path::impl_::pymethods::PyMethodDefType::Getter(\n                    #pyo3_path::impl_::pymethods::PyGetterDef::new(\n                        #python_name,\n                        #cls::#wrapper_ident,\n                        #doc\n                    )\n                )\n            };\n\n            Ok(MethodAndMethodDef {\n                associated_method,\n                method_def,\n            })\n        }\n    }\n}\n\npub fn impl_py_deleter_def(\n    cls: &syn::Type,\n    self_type: &SelfType,\n    spec: &FnSpec<'_>,\n    doc: Option<PythonDoc>,\n    ctx: &Ctx,\n) -> Result<MethodAndMethodDef> {\n    let Ctx { pyo3_path, .. } = ctx;\n    let python_name = spec.null_terminated_python_name();\n    let mut holders = Holders::new();\n    let deleter_impl = impl_call_deleter(cls, spec, self_type, &mut holders, ctx)?;\n    let wrapper_ident = format_ident!(\"__pymethod_delete_{}__\", spec.name);\n    let warnings = spec.warnings.build_py_warning(ctx);\n    let init_holders = holders.init_holders(ctx);\n    let doc = doc_to_optional_cstr(doc.as_ref(), ctx)?;\n    let associated_method = quote! {\n        unsafe fn #wrapper_ident(\n            py: #pyo3_path::Python<'_>,\n            _slf: ::std::ptr::NonNull<#pyo3_path::ffi::PyObject>,\n        ) -> #pyo3_path::PyResult<::std::ffi::c_int> {\n            #init_holders\n            #warnings\n            let result = #deleter_impl;\n            #pyo3_path::impl_::callback::convert(py, result)\n        }\n    };\n\n    let method_def = quote! {\n        #pyo3_path::impl_::pymethods::PyMethodDefType::Deleter(\n            #pyo3_path::impl_::pymethods::PyDeleterDef::new(\n                #python_name,\n                #cls::#wrapper_ident,\n                #doc\n            )\n        )\n    };\n\n    Ok(MethodAndMethodDef {\n        associated_method,\n        method_def,\n    })\n}\n\nfn impl_call_deleter(\n    cls: &syn::Type,\n    spec: &FnSpec<'_>,\n    self_type: &SelfType,\n    holders: &mut Holders,\n    ctx: &Ctx,\n) -> Result<TokenStream> {\n    let (py_arg, args) = split_off_python_arg(&spec.signature.arguments);\n    let slf = self_type.receiver(cls, ExtractErrorMode::Raise, holders, ctx);\n\n    if !args.is_empty() {\n        bail_spanned!(spec.name.span() =>\n            \"deleter function can have at most one argument ([pyo3::Python,])\"\n        );\n    }\n\n    let name = &spec.name;\n    let fncall = if py_arg.is_some() {\n        quote!(#cls::#name(#slf, py))\n    } else {\n        quote!(#cls::#name(#slf))\n    };\n\n    Ok(fncall)\n}\n\n/// Split an argument of pyo3::Python from the front of the arg list, if present\nfn split_off_python_arg<'a, 'b>(args: &'a [FnArg<'b>]) -> (Option<&'a PyArg<'b>>, &'a [FnArg<'b>]) {\n    match args {\n        [FnArg::Py(py), args @ ..] => (Some(py), args),\n        args => (None, args),\n    }\n}\n\npub enum PropertyType<'a> {\n    Descriptor {\n        field_index: usize,\n        field: &'a Field,\n        python_name: Option<&'a NameAttribute>,\n        renaming_rule: Option<RenamingRule>,\n    },\n    Function {\n        self_type: &'a SelfType,\n        spec: &'a FnSpec<'a>,\n        doc: Option<PythonDoc>,\n    },\n}\n\nimpl PropertyType<'_> {\n    fn null_terminated_python_name(&self) -> Result<LitCStr> {\n        match self {\n            PropertyType::Descriptor {\n                field,\n                python_name,\n                renaming_rule,\n                ..\n            } => {\n                let name = field_python_name(field, *python_name, *renaming_rule)?;\n                let name = CString::new(name).unwrap();\n                Ok(LitCStr::new(&name, field.span()))\n            }\n            PropertyType::Function { spec, .. } => Ok(spec.null_terminated_python_name()),\n        }\n    }\n\n    fn doc(&self) -> Option<Cow<'_, PythonDoc>> {\n        Some(match self {\n            PropertyType::Descriptor { field, .. } => {\n                Cow::Owned(utils::get_doc(&field.attrs, None)?)\n            }\n            PropertyType::Function { doc, .. } => Cow::Borrowed(doc.as_ref()?),\n        })\n    }\n}\n\npub const __NEW__: SlotDef = SlotDef::new(\"Py_tp_new\", \"newfunc\");\npub const __INIT__: SlotDef = SlotDef::new(\"Py_tp_init\", \"initproc\");\npub const __STR__: SlotDef = SlotDef::new(\"Py_tp_str\", \"reprfunc\");\npub const __REPR__: SlotDef = SlotDef::new(\"Py_tp_repr\", \"reprfunc\");\npub const __HASH__: SlotDef =\n    SlotDef::new(\"Py_tp_hash\", \"hashfunc\").return_conversion(TokenGenerator(\n        |Ctx { pyo3_path, .. }: &Ctx| quote! { #pyo3_path::impl_::callback::HashCallbackOutput },\n    ));\npub const __RICHCMP__: SlotDef = SlotDef::new(\"Py_tp_richcompare\", \"richcmpfunc\")\n    .extract_error_mode(ExtractErrorMode::NotImplemented);\nconst __GET__: SlotDef = SlotDef::new(\"Py_tp_descr_get\", \"descrgetfunc\");\nconst __ITER__: SlotDef = SlotDef::new(\"Py_tp_iter\", \"getiterfunc\");\nconst __NEXT__: SlotDef = SlotDef::new(\"Py_tp_iternext\", \"iternextfunc\")\n    .return_specialized_conversion(\n        TokenGenerator(|_| quote! { IterBaseKind, IterOptionKind, IterResultOptionKind }),\n        TokenGenerator(|_| quote! { iter_tag }),\n    );\nconst __AWAIT__: SlotDef = SlotDef::new(\"Py_am_await\", \"unaryfunc\");\nconst __AITER__: SlotDef = SlotDef::new(\"Py_am_aiter\", \"unaryfunc\");\nconst __ANEXT__: SlotDef = SlotDef::new(\"Py_am_anext\", \"unaryfunc\").return_specialized_conversion(\n    TokenGenerator(\n        |_| quote! { AsyncIterBaseKind, AsyncIterOptionKind, AsyncIterResultOptionKind },\n    ),\n    TokenGenerator(|_| quote! { async_iter_tag }),\n);\npub const __LEN__: SlotDef = SlotDef::new(\"Py_mp_length\", \"lenfunc\");\nconst __CONTAINS__: SlotDef = SlotDef::new(\"Py_sq_contains\", \"objobjproc\");\nconst __CONCAT__: SlotDef = SlotDef::new(\"Py_sq_concat\", \"binaryfunc\");\nconst __REPEAT__: SlotDef = SlotDef::new(\"Py_sq_repeat\", \"ssizeargfunc\");\nconst __INPLACE_CONCAT__: SlotDef = SlotDef::new(\"Py_sq_concat\", \"binaryfunc\");\nconst __INPLACE_REPEAT__: SlotDef = SlotDef::new(\"Py_sq_repeat\", \"ssizeargfunc\");\npub const __GETITEM__: SlotDef = SlotDef::new(\"Py_mp_subscript\", \"binaryfunc\");\n\nconst __POS__: SlotDef = SlotDef::new(\"Py_nb_positive\", \"unaryfunc\");\nconst __NEG__: SlotDef = SlotDef::new(\"Py_nb_negative\", \"unaryfunc\");\nconst __ABS__: SlotDef = SlotDef::new(\"Py_nb_absolute\", \"unaryfunc\");\nconst __INVERT__: SlotDef = SlotDef::new(\"Py_nb_invert\", \"unaryfunc\");\nconst __INDEX__: SlotDef = SlotDef::new(\"Py_nb_index\", \"unaryfunc\");\npub const __INT__: SlotDef = SlotDef::new(\"Py_nb_int\", \"unaryfunc\");\nconst __FLOAT__: SlotDef = SlotDef::new(\"Py_nb_float\", \"unaryfunc\");\nconst __BOOL__: SlotDef = SlotDef::new(\"Py_nb_bool\", \"inquiry\");\n\nconst __IADD__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_add\");\nconst __ISUB__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_subtract\");\nconst __IMUL__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_multiply\");\nconst __IMATMUL__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_matrix_multiply\");\nconst __ITRUEDIV__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_true_divide\");\nconst __IFLOORDIV__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_floor_divide\");\nconst __IMOD__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_remainder\");\nconst __ILSHIFT__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_lshift\");\nconst __IRSHIFT__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_rshift\");\nconst __IAND__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_and\");\nconst __IXOR__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_xor\");\nconst __IOR__: SlotDef = SlotDef::binary_inplace_operator(\"Py_nb_inplace_or\");\n\nconst __IPOW__: SlotDef = SlotDef::new(\"Py_nb_inplace_power\", \"ipowfunc\")\n    .extract_error_mode(ExtractErrorMode::NotImplemented)\n    .return_self();\n\nconst __GETBUFFER__: SlotDef = SlotDef::new(\"Py_bf_getbuffer\", \"getbufferproc\").require_unsafe();\nconst __RELEASEBUFFER__: SlotDef =\n    SlotDef::new(\"Py_bf_releasebuffer\", \"releasebufferproc\").require_unsafe();\nconst __CLEAR__: SlotDef = SlotDef::new(\"Py_tp_clear\", \"inquiry\");\n\n#[derive(Clone, Copy)]\nenum Ty {\n    Object,\n    MaybeNullObject,\n    NonNullObject,\n    IPowModulo,\n    CompareOp,\n    Int,\n    PyHashT,\n    PySsizeT,\n    Void,\n    PyBuffer,\n}\n\nimpl Ty {\n    fn ffi_type(self, ctx: &Ctx) -> TokenStream {\n        let Ctx {\n            pyo3_path,\n            output_span,\n        } = ctx;\n        let pyo3_path = pyo3_path.to_tokens_spanned(*output_span);\n        match self {\n            Ty::Object | Ty::MaybeNullObject => quote! { *mut #pyo3_path::ffi::PyObject },\n            Ty::NonNullObject => quote! { ::std::ptr::NonNull<#pyo3_path::ffi::PyObject> },\n            Ty::IPowModulo => quote! { #pyo3_path::impl_::pymethods::IPowModulo },\n            Ty::Int | Ty::CompareOp => quote! { ::std::ffi::c_int },\n            Ty::PyHashT => quote! { #pyo3_path::ffi::Py_hash_t },\n            Ty::PySsizeT => quote! { #pyo3_path::ffi::Py_ssize_t },\n            Ty::Void => quote! { () },\n            Ty::PyBuffer => quote! { *mut #pyo3_path::ffi::Py_buffer },\n        }\n    }\n\n    fn extract(\n        self,\n        ident: &syn::Ident,\n        arg: &FnArg<'_>,\n        extract_error_mode: ExtractErrorMode,\n        holders: &mut Holders,\n        ctx: &Ctx,\n    ) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        match self {\n            Ty::Object => extract_object(\n                extract_error_mode,\n                holders,\n                arg,\n                REF_FROM_PTR,\n                CAST_FUNCTION_ARGUMENT,\n                quote! { #ident },\n                ctx\n            ),\n            Ty::MaybeNullObject => extract_object(\n                extract_error_mode,\n                holders,\n                arg,\n                REF_FROM_PTR,\n                CAST_FUNCTION_ARGUMENT,\n                quote! {\n                    if #ident.is_null() {\n                        #pyo3_path::ffi::Py_None()\n                    } else {\n                        #ident\n                    }\n                },\n                ctx\n            ),\n            Ty::NonNullObject => extract_object(\n                extract_error_mode,\n                holders,\n                arg,\n                REF_FROM_NON_NULL,\n                CAST_NON_NULL_FUNCTION_ARGUMENT,\n                quote! { #ident },\n                ctx\n            ),\n            Ty::IPowModulo => extract_object(\n                extract_error_mode,\n                holders,\n                arg,\n                REF_FROM_PTR,\n                CAST_FUNCTION_ARGUMENT,\n                quote! { #ident.as_ptr() },\n                ctx\n            ),\n            Ty::CompareOp => extract_error_mode.handle_error(\n                quote! {\n                    #pyo3_path::class::basic::CompareOp::from_raw(#ident)\n                        .ok_or_else(|| #pyo3_path::exceptions::PyValueError::new_err(\"invalid comparison operator\"))\n                },\n                ctx\n            ),\n            Ty::PySsizeT => {\n                let ty = arg.ty();\n                extract_error_mode.handle_error(\n                    quote! {\n                            ::std::convert::TryInto::<#ty>::try_into(#ident).map_err(|e| #pyo3_path::exceptions::PyValueError::new_err(e.to_string()))\n                    },\n                    ctx\n                )\n            }\n            // Just pass other types through unmodified\n            Ty::PyBuffer | Ty::Int | Ty::PyHashT | Ty::Void => quote! { #ident },\n        }\n    }\n}\n\nconst REF_FROM_PTR: StaticIdent = StaticIdent::new(\"ref_from_ptr\");\nconst REF_FROM_NON_NULL: StaticIdent = StaticIdent::new(\"ref_from_non_null\");\n\nconst CAST_FUNCTION_ARGUMENT: StaticIdent = StaticIdent::new(\"cast_function_argument\");\nconst CAST_NON_NULL_FUNCTION_ARGUMENT: StaticIdent =\n    StaticIdent::new(\"cast_non_null_function_argument\");\n\nfn extract_object(\n    extract_error_mode: ExtractErrorMode,\n    holders: &mut Holders,\n    arg: &FnArg<'_>,\n    ref_from_method: StaticIdent,\n    cast_method: StaticIdent,\n    source_ptr: TokenStream,\n    ctx: &Ctx,\n) -> TokenStream {\n    let Ctx { pyo3_path, .. } = ctx;\n    let name = arg.name().unraw().to_string();\n\n    let extract = if let Some(FromPyWithAttribute {\n        kw,\n        value: extractor,\n    }) = arg.from_py_with()\n    {\n        let extractor = quote_spanned! { kw.span =>\n            { let from_py_with: fn(_) -> _ = #extractor; from_py_with }\n        };\n\n        quote! {\n            #pyo3_path::impl_::extract_argument::from_py_with(\n                unsafe { #pyo3_path::impl_::pymethods::BoundRef::#ref_from_method(py, &#source_ptr).0 },\n                #name,\n                #extractor,\n            )\n        }\n    } else {\n        let holder = holders.push_holder(Span::call_site());\n        quote! {{\n            #[allow(unused_imports, reason = \"`Probe` trait used on negative case only\")]\n            use #pyo3_path::impl_::pyclass::Probe as _;\n            #pyo3_path::impl_::extract_argument::extract_argument(\n                unsafe { #pyo3_path::impl_::extract_argument::#cast_method(py, #source_ptr) },\n                &mut #holder,\n                #name\n            )\n        }}\n    };\n\n    let extracted = extract_error_mode.handle_error(extract, ctx);\n    quote!(#extracted)\n}\n\nenum ReturnMode {\n    ReturnSelf,\n    Conversion(TokenGenerator),\n    SpecializedConversion(TokenGenerator, TokenGenerator),\n}\n\nimpl ReturnMode {\n    fn return_call_output(&self, call: TokenStream, ctx: &Ctx) -> TokenStream {\n        let Ctx { pyo3_path, .. } = ctx;\n        match self {\n            ReturnMode::Conversion(conversion) => {\n                let conversion = TokenGeneratorCtx(*conversion, ctx);\n                quote! {\n                    let _result: #pyo3_path::PyResult<#conversion> = #pyo3_path::impl_::callback::convert(py, #call);\n                    #pyo3_path::impl_::callback::convert(py, _result)\n                }\n            }\n            ReturnMode::SpecializedConversion(traits, tag) => {\n                let traits = TokenGeneratorCtx(*traits, ctx);\n                let tag = TokenGeneratorCtx(*tag, ctx);\n                quote! {\n                    let _result = #call;\n                    use #pyo3_path::impl_::pymethods::{#traits};\n                    (&_result).#tag().convert(py, _result)\n                }\n            }\n            ReturnMode::ReturnSelf => quote! {\n                let _result: #pyo3_path::PyResult<()> = #pyo3_path::impl_::callback::convert(py, #call);\n                _result?;\n                #pyo3_path::ffi::Py_XINCREF(_slf);\n                ::std::result::Result::Ok(_slf)\n            },\n        }\n    }\n}\n\npub struct SlotDef {\n    slot: StaticIdent,\n    func_ty: StaticIdent,\n    calling_convention: SlotCallingConvention,\n    ret_ty: Ty,\n    extract_error_mode: ExtractErrorMode,\n    return_mode: Option<ReturnMode>,\n    require_unsafe: bool,\n}\n\nenum SlotCallingConvention {\n    /// Specific set of arguments for the slot function\n    FixedArguments(&'static [Ty]),\n    /// Arbitrary arguments for `__new__` from the signature (extracted from args / kwargs)\n    TpNew,\n    TpInit,\n}\n\nimpl SlotDef {\n    const fn new(slot: &'static str, func_ty: &'static str) -> Self {\n        // The FFI function pointer type determines the arguments and return type\n        let (calling_convention, ret_ty) = match func_ty.as_bytes() {\n            b\"newfunc\" => (SlotCallingConvention::TpNew, Ty::Object),\n            b\"initproc\" => (SlotCallingConvention::TpInit, Ty::Int),\n            b\"reprfunc\" => (SlotCallingConvention::FixedArguments(&[]), Ty::Object),\n            b\"hashfunc\" => (SlotCallingConvention::FixedArguments(&[]), Ty::PyHashT),\n            b\"richcmpfunc\" => (\n                SlotCallingConvention::FixedArguments(&[Ty::Object, Ty::CompareOp]),\n                Ty::Object,\n            ),\n            b\"descrgetfunc\" => (\n                SlotCallingConvention::FixedArguments(&[Ty::MaybeNullObject, Ty::MaybeNullObject]),\n                Ty::Object,\n            ),\n            b\"getiterfunc\" => (SlotCallingConvention::FixedArguments(&[]), Ty::Object),\n            b\"iternextfunc\" => (SlotCallingConvention::FixedArguments(&[]), Ty::Object),\n            b\"unaryfunc\" => (SlotCallingConvention::FixedArguments(&[]), Ty::Object),\n            b\"lenfunc\" => (SlotCallingConvention::FixedArguments(&[]), Ty::PySsizeT),\n            b\"objobjproc\" => (\n                SlotCallingConvention::FixedArguments(&[Ty::Object]),\n                Ty::Int,\n            ),\n            b\"binaryfunc\" => (\n                SlotCallingConvention::FixedArguments(&[Ty::Object]),\n                Ty::Object,\n            ),\n            b\"inquiry\" => (SlotCallingConvention::FixedArguments(&[]), Ty::Int),\n            b\"ssizeargfunc\" => (\n                SlotCallingConvention::FixedArguments(&[Ty::PySsizeT]),\n                Ty::Object,\n            ),\n            b\"getbufferproc\" => (\n                SlotCallingConvention::FixedArguments(&[Ty::PyBuffer, Ty::Int]),\n                Ty::Int,\n            ),\n            b\"releasebufferproc\" => (\n                SlotCallingConvention::FixedArguments(&[Ty::PyBuffer]),\n                Ty::Void,\n            ),\n            b\"ipowfunc\" => (\n                SlotCallingConvention::FixedArguments(&[Ty::Object, Ty::IPowModulo]),\n                Ty::Object,\n            ),\n            _ => panic!(\"don't know calling convention for func_ty\"),\n        };\n\n        SlotDef {\n            slot: StaticIdent::new(slot),\n            func_ty: StaticIdent::new(func_ty),\n            calling_convention,\n            ret_ty,\n            extract_error_mode: ExtractErrorMode::Raise,\n            return_mode: None,\n            require_unsafe: false,\n        }\n    }\n\n    /// Specialized constructor for binary inplace operators\n    const fn binary_inplace_operator(slot: &'static str) -> Self {\n        SlotDef::new(slot, \"binaryfunc\")\n            .extract_error_mode(ExtractErrorMode::NotImplemented)\n            .return_self()\n    }\n\n    const fn return_conversion(mut self, return_conversion: TokenGenerator) -> Self {\n        self.return_mode = Some(ReturnMode::Conversion(return_conversion));\n        self\n    }\n\n    const fn return_specialized_conversion(\n        mut self,\n        traits: TokenGenerator,\n        tag: TokenGenerator,\n    ) -> Self {\n        self.return_mode = Some(ReturnMode::SpecializedConversion(traits, tag));\n        self\n    }\n\n    const fn extract_error_mode(mut self, extract_error_mode: ExtractErrorMode) -> Self {\n        self.extract_error_mode = extract_error_mode;\n        self\n    }\n\n    const fn return_self(mut self) -> Self {\n        self.return_mode = Some(ReturnMode::ReturnSelf);\n        self\n    }\n\n    const fn require_unsafe(mut self) -> Self {\n        self.require_unsafe = true;\n        self\n    }\n\n    pub fn generate_type_slot(\n        &self,\n        cls: &syn::Type,\n        spec: &FnSpec<'_>,\n        method_name: &str,\n        ctx: &Ctx,\n    ) -> Result<MethodAndSlotDef> {\n        let Ctx { pyo3_path, .. } = ctx;\n        let SlotDef {\n            slot,\n            func_ty,\n            calling_convention,\n            extract_error_mode,\n            ret_ty,\n            return_mode,\n            require_unsafe,\n        } = self;\n        if *require_unsafe {\n            ensure_spanned!(\n                spec.unsafety.is_some(),\n                spec.name.span() => format!(\"`{}` must be `unsafe fn`\", method_name)\n            );\n        }\n        let wrapper_ident = format_ident!(\"__pymethod_{}__\", method_name);\n        let ret_ty = ret_ty.ffi_type(ctx);\n        let mut holders = Holders::new();\n        let MethodBody {\n            arg_idents,\n            arg_types,\n            body,\n        } = generate_method_body(\n            cls,\n            spec,\n            calling_convention,\n            *extract_error_mode,\n            &mut holders,\n            return_mode.as_ref(),\n            ctx,\n        )?;\n        let name = spec.name;\n        let holders = holders.init_holders(ctx);\n        let associated_method = quote! {\n            #[allow(non_snake_case)]\n            unsafe fn #wrapper_ident(\n                py: #pyo3_path::Python<'_>,\n                #(#arg_idents: #arg_types),*\n            ) -> #pyo3_path::PyResult<#ret_ty> {\n                let function = #cls::#name; // Shadow the method name to avoid #3017\n                #holders\n                #body\n            }\n        };\n        let slot_def = quote! {\n            #pyo3_path::ffi::PyType_Slot {\n                slot: #pyo3_path::ffi::#slot,\n                pfunc: #pyo3_path::impl_::trampoline::get_trampoline_function!(#func_ty, #cls::#wrapper_ident) as #pyo3_path::ffi::#func_ty as _\n            }\n        };\n        Ok(MethodAndSlotDef {\n            associated_method,\n            slot_def,\n        })\n    }\n}\n\nfn generate_method_body(\n    cls: &syn::Type,\n    spec: &FnSpec<'_>,\n    calling_convention: &SlotCallingConvention,\n    extract_error_mode: ExtractErrorMode,\n    holders: &mut Holders,\n    // NB ignored if calling_convention is SlotCallingConvention::TpNew, possibly should merge into that enum\n    return_mode: Option<&ReturnMode>,\n    ctx: &Ctx,\n) -> Result<MethodBody> {\n    let Ctx {\n        pyo3_path,\n        output_span,\n    } = ctx;\n    let self_arg = spec\n        .tp\n        .self_arg(Some(cls), extract_error_mode, holders, ctx);\n    let rust_name = spec.name;\n    let warnings = spec.warnings.build_py_warning(ctx);\n\n    let (arg_idents, arg_types, body) = match calling_convention {\n        SlotCallingConvention::TpNew => {\n            let arg_idents = vec![\n                format_ident!(\"_slf\"),\n                format_ident!(\"_args\"),\n                format_ident!(\"_kwargs\"),\n            ];\n            let arg_types = vec![\n                quote! { *mut #pyo3_path::ffi::PyTypeObject },\n                quote! { *mut #pyo3_path::ffi::PyObject },\n                quote! { *mut #pyo3_path::ffi::PyObject },\n            ];\n            let (arg_convert, args) = impl_arg_params(spec, Some(cls), false, holders, ctx);\n            let args = self_arg.into_iter().chain(args);\n            let call = quote_spanned! {*output_span=> #cls::#rust_name(#(#args),*) };\n\n            // Use just the text_signature_call_signature() because the class' Python name\n            // isn't known to `#[pymethods]` - that has to be attached at runtime from the PyClassImpl\n            // trait implementation created by `#[pyclass]`.\n            let text_signature_impl = spec.text_signature_call_signature().map(|text_signature| {\n                quote! {\n                    #[allow(unknown_lints, non_local_definitions)]\n                    impl #pyo3_path::impl_::pyclass::doc::PyClassNewTextSignature for #cls {\n                        const TEXT_SIGNATURE: &'static str = #text_signature;\n                    }\n                }\n            });\n\n            let output = if let syn::ReturnType::Type(_, ty) = &spec.output {\n                ty\n            } else {\n                &parse_quote!(())\n            };\n            let body = quote! {\n                #text_signature_impl\n\n                use #pyo3_path::impl_::pyclass::Probe as _;\n                #warnings\n                #arg_convert\n                let result = #call;\n                #pyo3_path::impl_::pymethods::tp_new_impl::<\n                    _,\n                    { #pyo3_path::impl_::pyclass::IsPyClass::<#output>::VALUE },\n                    { #pyo3_path::impl_::pyclass::IsInitializerTuple::<#output>::VALUE }\n                >(py, result, _slf)\n            };\n            (arg_idents, arg_types, body)\n        }\n        SlotCallingConvention::TpInit => {\n            let arg_idents = vec![\n                format_ident!(\"_slf\"),\n                format_ident!(\"_args\"),\n                format_ident!(\"_kwargs\"),\n            ];\n            let arg_types = vec![\n                quote! { *mut #pyo3_path::ffi::PyObject },\n                quote! { *mut #pyo3_path::ffi::PyObject },\n                quote! { *mut #pyo3_path::ffi::PyObject },\n            ];\n            let (arg_convert, args) = impl_arg_params(spec, Some(cls), false, holders, ctx);\n            let args = self_arg.into_iter().chain(args);\n            let call = quote! {{\n                let r = #cls::#rust_name(#(#args),*);\n                #pyo3_path::impl_::wrap::converter(&r)\n                    .wrap(r)\n                    .map_err(::core::convert::Into::<#pyo3_path::PyErr>::into)?\n            }};\n            let output = quote_spanned! { *output_span => result.convert(py) };\n\n            let body = quote! {\n                use #pyo3_path::impl_::callback::IntoPyCallbackOutput;\n                #warnings\n                #arg_convert\n                let result = #call;\n                #output\n            };\n            (arg_idents, arg_types, body)\n        }\n        SlotCallingConvention::FixedArguments(arguments) => {\n            let arg_idents: Vec<_> = std::iter::once(format_ident!(\"_slf\"))\n                .chain((0..arguments.len()).map(|i| format_ident!(\"arg{}\", i)))\n                .collect();\n            let arg_types: Vec<_> = std::iter::once(quote! { *mut #pyo3_path::ffi::PyObject })\n                .chain(arguments.iter().map(|arg| arg.ffi_type(ctx)))\n                .collect();\n\n            let args = extract_proto_arguments(spec, arguments, extract_error_mode, holders, ctx)?;\n            let args = self_arg.into_iter().chain(args);\n            let call = quote! { #cls::#rust_name(#(#args),*) };\n            let result = if let Some(return_mode) = return_mode {\n                return_mode.return_call_output(call, ctx)\n            } else {\n                quote! {\n                    let result = #call;\n                    #pyo3_path::impl_::callback::convert(py, result)\n                }\n            };\n            let body = quote! {\n                #warnings\n                #result\n            };\n            (arg_idents, arg_types, body)\n        }\n    };\n\n    Ok(MethodBody {\n        arg_idents,\n        arg_types,\n        body,\n    })\n}\n\nstruct SlotFragmentDef {\n    fragment: &'static str,\n    arguments: &'static [Ty],\n    extract_error_mode: ExtractErrorMode,\n    ret_ty: Ty,\n}\n\nimpl SlotFragmentDef {\n    const fn new(fragment: &'static str, arguments: &'static [Ty]) -> Self {\n        SlotFragmentDef {\n            fragment,\n            arguments,\n            extract_error_mode: ExtractErrorMode::Raise,\n            ret_ty: Ty::Void,\n        }\n    }\n\n    /// Specialized constructor for binary operators (which are a common pattern)\n    const fn binary_operator(fragment: &'static str) -> Self {\n        SlotFragmentDef {\n            fragment,\n            arguments: &[Ty::Object],\n            extract_error_mode: ExtractErrorMode::NotImplemented,\n            ret_ty: Ty::Object,\n        }\n    }\n\n    const fn extract_error_mode(mut self, extract_error_mode: ExtractErrorMode) -> Self {\n        self.extract_error_mode = extract_error_mode;\n        self\n    }\n\n    const fn ret_ty(mut self, ret_ty: Ty) -> Self {\n        self.ret_ty = ret_ty;\n        self\n    }\n\n    fn generate_pyproto_fragment(\n        &self,\n        cls: &syn::Type,\n        spec: &FnSpec<'_>,\n        ctx: &Ctx,\n    ) -> Result<TokenStream> {\n        let Ctx { pyo3_path, .. } = ctx;\n        let SlotFragmentDef {\n            fragment,\n            arguments,\n            extract_error_mode,\n            ret_ty,\n        } = self;\n        let fragment_trait = format_ident!(\"PyClass{}SlotFragment\", fragment);\n        let method = syn::Ident::new(fragment, Span::call_site());\n        let wrapper_ident = format_ident!(\"__pymethod_{}__\", fragment);\n\n        let mut holders = Holders::new();\n        let MethodBody {\n            arg_idents,\n            arg_types,\n            body,\n        } = generate_method_body(\n            cls,\n            spec,\n            &SlotCallingConvention::FixedArguments(arguments),\n            *extract_error_mode,\n            &mut holders,\n            None,\n            ctx,\n        )?;\n        let ret_ty = ret_ty.ffi_type(ctx);\n        let holders = holders.init_holders(ctx);\n        Ok(quote! {\n            impl #cls {\n                #[allow(non_snake_case)]\n                unsafe fn #wrapper_ident(\n                    py: #pyo3_path::Python,\n                    #(#arg_idents: #arg_types),*\n                ) -> #pyo3_path::PyResult<#ret_ty> {\n                    #holders\n                    #body\n                }\n            }\n\n            impl #pyo3_path::impl_::pyclass::#fragment_trait<#cls> for #pyo3_path::impl_::pyclass::PyClassImplCollector<#cls> {\n\n                #[inline]\n                unsafe fn #method(\n                    self,\n                    py: #pyo3_path::Python,\n                    #(#arg_idents: #arg_types),*\n                ) -> #pyo3_path::PyResult<#ret_ty> {\n                    #cls::#wrapper_ident(py, #(#arg_idents),*)\n                }\n            }\n        })\n    }\n}\n\n/// The reusable components of a method body.\npub struct MethodBody {\n    pub arg_idents: Vec<Ident>,\n    pub arg_types: Vec<TokenStream>,\n    pub body: TokenStream,\n}\n\nconst __GETATTRIBUTE__: SlotFragmentDef =\n    SlotFragmentDef::new(\"__getattribute__\", &[Ty::Object]).ret_ty(Ty::Object);\nconst __GETATTR__: SlotFragmentDef =\n    SlotFragmentDef::new(\"__getattr__\", &[Ty::Object]).ret_ty(Ty::Object);\nconst __SETATTR__: SlotFragmentDef =\n    SlotFragmentDef::new(\"__setattr__\", &[Ty::Object, Ty::NonNullObject]);\nconst __DELATTR__: SlotFragmentDef = SlotFragmentDef::new(\"__delattr__\", &[Ty::Object]);\nconst __SET__: SlotFragmentDef = SlotFragmentDef::new(\"__set__\", &[Ty::Object, Ty::NonNullObject]);\nconst __DELETE__: SlotFragmentDef = SlotFragmentDef::new(\"__delete__\", &[Ty::Object]);\nconst __SETITEM__: SlotFragmentDef =\n    SlotFragmentDef::new(\"__setitem__\", &[Ty::Object, Ty::NonNullObject]);\nconst __DELITEM__: SlotFragmentDef = SlotFragmentDef::new(\"__delitem__\", &[Ty::Object]);\n\nconst __ADD__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__add__\");\nconst __RADD__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__radd__\");\nconst __SUB__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__sub__\");\nconst __RSUB__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rsub__\");\nconst __MUL__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__mul__\");\nconst __RMUL__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rmul__\");\nconst __MATMUL__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__matmul__\");\nconst __RMATMUL__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rmatmul__\");\nconst __FLOORDIV__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__floordiv__\");\nconst __RFLOORDIV__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rfloordiv__\");\nconst __TRUEDIV__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__truediv__\");\nconst __RTRUEDIV__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rtruediv__\");\nconst __DIVMOD__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__divmod__\");\nconst __RDIVMOD__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rdivmod__\");\nconst __MOD__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__mod__\");\nconst __RMOD__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rmod__\");\nconst __LSHIFT__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__lshift__\");\nconst __RLSHIFT__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rlshift__\");\nconst __RSHIFT__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rshift__\");\nconst __RRSHIFT__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rrshift__\");\nconst __AND__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__and__\");\nconst __RAND__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rand__\");\nconst __XOR__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__xor__\");\nconst __RXOR__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__rxor__\");\nconst __OR__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__or__\");\nconst __ROR__: SlotFragmentDef = SlotFragmentDef::binary_operator(\"__ror__\");\n\nconst __POW__: SlotFragmentDef = SlotFragmentDef::new(\"__pow__\", &[Ty::Object, Ty::Object])\n    .extract_error_mode(ExtractErrorMode::NotImplemented)\n    .ret_ty(Ty::Object);\nconst __RPOW__: SlotFragmentDef = SlotFragmentDef::new(\"__rpow__\", &[Ty::Object, Ty::Object])\n    .extract_error_mode(ExtractErrorMode::NotImplemented)\n    .ret_ty(Ty::Object);\n\nconst __LT__: SlotFragmentDef = SlotFragmentDef::new(\"__lt__\", &[Ty::Object])\n    .extract_error_mode(ExtractErrorMode::NotImplemented)\n    .ret_ty(Ty::Object);\nconst __LE__: SlotFragmentDef = SlotFragmentDef::new(\"__le__\", &[Ty::Object])\n    .extract_error_mode(ExtractErrorMode::NotImplemented)\n    .ret_ty(Ty::Object);\nconst __EQ__: SlotFragmentDef = SlotFragmentDef::new(\"__eq__\", &[Ty::Object])\n    .extract_error_mode(ExtractErrorMode::NotImplemented)\n    .ret_ty(Ty::Object);\nconst __NE__: SlotFragmentDef = SlotFragmentDef::new(\"__ne__\", &[Ty::Object])\n    .extract_error_mode(ExtractErrorMode::NotImplemented)\n    .ret_ty(Ty::Object);\nconst __GT__: SlotFragmentDef = SlotFragmentDef::new(\"__gt__\", &[Ty::Object])\n    .extract_error_mode(ExtractErrorMode::NotImplemented)\n    .ret_ty(Ty::Object);\nconst __GE__: SlotFragmentDef = SlotFragmentDef::new(\"__ge__\", &[Ty::Object])\n    .extract_error_mode(ExtractErrorMode::NotImplemented)\n    .ret_ty(Ty::Object);\n\nfn extract_proto_arguments(\n    spec: &FnSpec<'_>,\n    proto_args: &[Ty],\n    extract_error_mode: ExtractErrorMode,\n    holders: &mut Holders,\n    ctx: &Ctx,\n) -> Result<Vec<TokenStream>> {\n    let mut args = Vec::with_capacity(spec.signature.arguments.len());\n    let mut non_python_args = 0;\n\n    for arg in &spec.signature.arguments {\n        if let FnArg::Py(..) = arg {\n            args.push(quote! { py });\n        } else {\n            let ident = syn::Ident::new(&format!(\"arg{non_python_args}\"), Span::call_site());\n            let conversions = proto_args.get(non_python_args)\n                .ok_or_else(|| err_spanned!(arg.ty().span() => format!(\"Expected at most {} non-python arguments\", proto_args.len())))?\n                .extract(&ident, arg, extract_error_mode, holders, ctx);\n            non_python_args += 1;\n            args.push(conversions);\n        }\n    }\n\n    if non_python_args != proto_args.len() {\n        bail_spanned!(spec.name.span() => format!(\"Expected {} arguments, got {}\", proto_args.len(), non_python_args));\n    }\n    Ok(args)\n}\n\n#[derive(Clone, Copy)]\nstruct TokenGenerator(fn(&Ctx) -> TokenStream);\n\nstruct TokenGeneratorCtx<'ctx>(TokenGenerator, &'ctx Ctx);\n\nimpl ToTokens for TokenGeneratorCtx<'_> {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        let Self(TokenGenerator(gen), ctx) = self;\n        (gen)(ctx).to_tokens(tokens)\n    }\n}\n\npub fn field_python_name(\n    field: &Field,\n    name_attr: Option<&NameAttribute>,\n    renaming_rule: Option<RenamingRule>,\n) -> Result<String> {\n    if let Some(name_attr) = name_attr {\n        return Ok(name_attr.value.0.to_string());\n    }\n    let Some(ident) = &field.ident else {\n        bail_spanned!(field.span() => \"`get` and `set` with tuple struct fields require `name`\");\n    };\n    let mut name = ident.unraw().to_string();\n    if let Some(rule) = renaming_rule {\n        name = utils::apply_renaming_rule(rule, &name);\n    }\n    Ok(name)\n}\n\nfn doc_to_optional_cstr(doc: Option<&PythonDoc>, ctx: &Ctx) -> Result<TokenStream> {\n    Ok(if let Some(doc) = doc {\n        let doc = doc.to_cstr_stream(ctx)?;\n        quote!(::std::option::Option::Some(#doc))\n    } else {\n        quote!(::std::option::Option::None)\n    })\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/quotes.rs",
    "content": "use crate::utils::Ctx;\nuse proc_macro2::TokenStream;\nuse quote::{quote, quote_spanned};\n\npub(crate) fn some_wrap(obj: TokenStream, ctx: &Ctx) -> TokenStream {\n    let Ctx { pyo3_path, .. } = ctx;\n    quote! {\n        #pyo3_path::impl_::wrap::SomeWrap::wrap(#obj)\n    }\n}\n\npub(crate) fn ok_wrap(obj: TokenStream, ctx: &Ctx) -> TokenStream {\n    let Ctx {\n        pyo3_path,\n        output_span,\n    } = ctx;\n    let pyo3_path = pyo3_path.to_tokens_spanned(*output_span);\n    quote_spanned! { *output_span => {\n        let obj = #obj;\n        #[allow(clippy::useless_conversion, reason = \"needed for Into<PyErr> conversion, may be redundant\")]\n        #pyo3_path::impl_::wrap::converter(&obj).wrap(obj).map_err(::core::convert::Into::<#pyo3_path::PyErr>::into)\n    }}\n}\n\npub(crate) fn map_result_into_ptr(result: TokenStream, ctx: &Ctx) -> TokenStream {\n    let Ctx {\n        pyo3_path,\n        output_span,\n    } = ctx;\n    let pyo3_path = pyo3_path.to_tokens_spanned(*output_span);\n    let py = syn::Ident::new(\"py\", proc_macro2::Span::call_site());\n    quote_spanned! { *output_span => {\n        let result = #result;\n        #pyo3_path::impl_::wrap::converter(&result).map_into_ptr(#py, result)\n    }}\n}\n"
  },
  {
    "path": "pyo3-macros-backend/src/utils.rs",
    "content": "use crate::attributes::{CrateAttribute, RenamingRule};\nuse proc_macro2::{Span, TokenStream, TokenTree};\nuse quote::{quote, ToTokens, TokenStreamExt};\nuse std::ffi::CString;\nuse std::mem::take;\nuse syn::spanned::Spanned;\nuse syn::{Expr, ExprLit, Lit, LitCStr};\n\n/// Macro inspired by `anyhow::anyhow!` to create a compiler error with the given span.\nmacro_rules! err_spanned {\n    ($span:expr => $msg:expr) => {\n        syn::Error::new($span, $msg)\n    };\n}\n\n/// Macro inspired by `anyhow::bail!` to return a compiler error with the given span.\nmacro_rules! bail_spanned {\n    ($span:expr => $msg:expr) => {\n        return Err(err_spanned!($span => $msg))\n    };\n}\n\n/// Macro inspired by `anyhow::ensure!` to return a compiler error with the given span if the\n/// specified condition is not met.\nmacro_rules! ensure_spanned {\n    ($condition:expr, $span:expr => $msg:expr) => {\n        if !($condition) {\n            bail_spanned!($span => $msg);\n        }\n    };\n    ($($condition:expr, $span:expr => $msg:expr;)*) => {\n        if let Some(e) = [$(\n            (!($condition)).then(|| err_spanned!($span => $msg)),\n        )*]\n            .into_iter()\n            .flatten()\n            .reduce(|mut acc, e| {\n                acc.combine(e);\n                acc\n            }) {\n                return Err(e);\n            }\n    };\n}\n\n/// Check if the given type `ty` is `pyo3::Python`.\npub fn is_python(ty: &syn::Type) -> bool {\n    match unwrap_ty_group(ty) {\n        syn::Type::Path(typath) => typath\n            .path\n            .segments\n            .last()\n            .map(|seg| seg.ident == \"Python\")\n            .unwrap_or(false),\n        _ => false,\n    }\n}\n\n/// If `ty` is `Option<T>`, return `Some(T)`, else `None`.\npub fn option_type_argument(ty: &syn::Type) -> Option<&syn::Type> {\n    if let syn::Type::Path(syn::TypePath { path, .. }) = ty {\n        let seg = path.segments.last().filter(|s| s.ident == \"Option\")?;\n        if let syn::PathArguments::AngleBracketed(params) = &seg.arguments {\n            if let syn::GenericArgument::Type(ty) = params.args.first()? {\n                return Some(ty);\n            }\n        }\n    }\n    None\n}\n\n/// A syntax tree which evaluates to a string for Python.\n///\n/// Typically, the tokens will just be that string, but if the original docs included macro\n/// expressions then the tokens will be a concatenation expression of the strings and\n/// macro parts. contents such as parse the string contents.\n#[derive(Clone)]\npub struct PythonDoc {\n    pub parts: Vec<StrOrExpr>,\n}\n\n/// Collects all #[doc = \"...\"] attributes into a TokenStream evaluating to a string.\n///\n/// If this doc is for a callable, the provided `text_signature` can be passed to prepend\n/// this to the documentation suitable for Python to extract this into the `__text_signature__`\n/// attribute.\npub fn get_doc(attrs: &[syn::Attribute], mut text_signature: Option<String>) -> Option<PythonDoc> {\n    // insert special divider between `__text_signature__` and doc\n    // (assume text_signature is itself well-formed)\n    if let Some(text_signature) = &mut text_signature {\n        text_signature.push_str(\"\\n--\\n\\n\");\n    }\n\n    let mut parts = Vec::new();\n    let mut first = true;\n    let mut current_part = text_signature.unwrap_or_default();\n    let mut current_part_span: Option<Span> = None;\n\n    for attr in attrs {\n        if attr.path().is_ident(\"doc\") {\n            if let Ok(nv) = attr.meta.require_name_value() {\n                if !first {\n                    current_part.push('\\n');\n                } else {\n                    first = false;\n                }\n                if let Expr::Lit(ExprLit {\n                    lit: Lit::Str(lit_str),\n                    ..\n                }) = &nv.value\n                {\n                    // Strip single left space from literal strings, if needed.\n                    // e.g. `/// Hello world` expands to #[doc = \" Hello world\"]\n                    let doc_line = lit_str.value();\n                    current_part.push_str(doc_line.strip_prefix(' ').unwrap_or(&doc_line));\n                    current_part_span = current_part_span\n                        .map_or_else(|| Some(lit_str.span()), |s| s.join(lit_str.span()));\n                } else {\n                    // This is probably a macro doc from Rust 1.54, e.g. #[doc = include_str!(...)]\n                    // Reset the string buffer, write that part, and then push this macro part too.\n                    if !current_part.is_empty() {\n                        parts.push(StrOrExpr::Str {\n                            value: take(&mut current_part),\n                            span: take(&mut current_part_span),\n                        });\n                    }\n                    parts.push(StrOrExpr::Expr(nv.value.clone()));\n                }\n            }\n        }\n    }\n    if !current_part.is_empty() {\n        parts.push(StrOrExpr::Str {\n            value: current_part,\n            span: current_part_span,\n        });\n    }\n    if parts.is_empty() {\n        None\n    } else {\n        Some(PythonDoc { parts })\n    }\n}\n\nimpl PythonDoc {\n    pub fn to_cstr_stream(&self, ctx: &Ctx) -> syn::Result<TokenStream> {\n        let parts = &self.parts;\n        if let [StrOrExpr::Str { value, span }] = &parts[..] {\n            // Simple case, a single string. We serialize as such\n            return match CString::new(value.clone()) {\n                Ok(null_terminated_value) => Ok(LitCStr::new(\n                    &null_terminated_value,\n                    span.unwrap_or_else(Span::call_site),\n                )\n                .into_token_stream()),\n                Err(e) => Err(syn::Error::new(\n                    span.unwrap_or_else(Span::call_site),\n                    format!(\n                        \"Python doc may not contain nul byte, found nul at position {}\",\n                        e.nul_position()\n                    ),\n                )),\n            };\n        }\n        let Ctx { pyo3_path, .. } = ctx;\n        Ok(quote!(#pyo3_path::ffi::c_str!(concat!(#(#parts),*))))\n    }\n}\n\n/// A plain string or an expression\n#[derive(Clone)]\npub enum StrOrExpr {\n    Str { value: String, span: Option<Span> },\n    Expr(Expr),\n}\n\nimpl ToTokens for StrOrExpr {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        match self {\n            StrOrExpr::Str { value, .. } => value.to_tokens(tokens),\n            StrOrExpr::Expr(expr) => expr.to_tokens(tokens),\n        }\n    }\n}\n\npub fn unwrap_ty_group(mut ty: &syn::Type) -> &syn::Type {\n    while let syn::Type::Group(g) = ty {\n        ty = &*g.elem;\n    }\n    ty\n}\n\npub struct Ctx {\n    /// Where we can find the pyo3 crate\n    pub pyo3_path: PyO3CratePath,\n\n    /// If we are in a pymethod or pyfunction,\n    /// this will be the span of the return type\n    pub output_span: Span,\n}\n\nimpl Ctx {\n    pub(crate) fn new(attr: &Option<CrateAttribute>, signature: Option<&syn::Signature>) -> Self {\n        let pyo3_path = match attr {\n            Some(attr) => PyO3CratePath::Given(attr.value.0.clone()),\n            None => PyO3CratePath::Default,\n        };\n\n        let output_span = if let Some(syn::Signature {\n            output: syn::ReturnType::Type(_, output_type),\n            ..\n        }) = &signature\n        {\n            output_type.span()\n        } else {\n            Span::call_site()\n        };\n\n        Self {\n            pyo3_path,\n            output_span,\n        }\n    }\n}\n\n#[derive(Clone)]\npub enum PyO3CratePath {\n    Given(syn::Path),\n    Default,\n}\n\nimpl PyO3CratePath {\n    pub fn to_tokens_spanned(&self, span: Span) -> TokenStream {\n        match self {\n            Self::Given(path) => quote::quote_spanned! { span => #path },\n            Self::Default => quote::quote_spanned! {  span => ::pyo3 },\n        }\n    }\n}\n\nimpl quote::ToTokens for PyO3CratePath {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        match self {\n            Self::Given(path) => path.to_tokens(tokens),\n            Self::Default => quote::quote! { ::pyo3 }.to_tokens(tokens),\n        }\n    }\n}\n\npub fn apply_renaming_rule(rule: RenamingRule, name: &str) -> String {\n    use heck::*;\n\n    match rule {\n        RenamingRule::CamelCase => name.to_lower_camel_case(),\n        RenamingRule::KebabCase => name.to_kebab_case(),\n        RenamingRule::Lowercase => name.to_lowercase(),\n        RenamingRule::PascalCase => name.to_upper_camel_case(),\n        RenamingRule::ScreamingKebabCase => name.to_shouty_kebab_case(),\n        RenamingRule::ScreamingSnakeCase => name.to_shouty_snake_case(),\n        RenamingRule::SnakeCase => name.to_snake_case(),\n        RenamingRule::Uppercase => name.to_uppercase(),\n    }\n}\n\npub(crate) enum IdentOrStr<'a> {\n    Str(&'a str),\n    Ident(syn::Ident),\n}\n\npub(crate) fn has_attribute(attrs: &[syn::Attribute], ident: &str) -> bool {\n    has_attribute_with_namespace(attrs, None, &[ident])\n}\n\npub(crate) fn has_attribute_with_namespace(\n    attrs: &[syn::Attribute],\n    crate_path: Option<&PyO3CratePath>,\n    idents: &[&str],\n) -> bool {\n    let mut segments = vec![];\n    if let Some(c) = crate_path {\n        match c {\n            PyO3CratePath::Given(paths) => {\n                for p in &paths.segments {\n                    segments.push(IdentOrStr::Ident(p.ident.clone()));\n                }\n            }\n            PyO3CratePath::Default => segments.push(IdentOrStr::Str(\"pyo3\")),\n        }\n    };\n    for i in idents {\n        segments.push(IdentOrStr::Str(i));\n    }\n\n    attrs.iter().any(|attr| {\n        segments\n            .iter()\n            .eq(attr.path().segments.iter().map(|v| &v.ident))\n    })\n}\n\npub fn expr_to_python(expr: &syn::Expr) -> String {\n    match expr {\n        // literal values\n        syn::Expr::Lit(syn::ExprLit { lit, .. }) => match lit {\n            syn::Lit::Str(s) => s.token().to_string(),\n            syn::Lit::Char(c) => c.token().to_string(),\n            syn::Lit::Int(i) => i.base10_digits().to_string(),\n            syn::Lit::Float(f) => f.base10_digits().to_string(),\n            syn::Lit::Bool(b) => {\n                if b.value() {\n                    \"True\".to_string()\n                } else {\n                    \"False\".to_string()\n                }\n            }\n            _ => \"...\".to_string(),\n        },\n        // None\n        syn::Expr::Path(syn::ExprPath { qself, path, .. })\n            if qself.is_none() && path.is_ident(\"None\") =>\n        {\n            \"None\".to_string()\n        }\n        // others, unsupported yet so defaults to `...`\n        _ => \"...\".to_string(),\n    }\n}\n\n/// Helper struct for hard-coded identifiers used in the macro code.\n#[derive(Clone, Copy)]\npub struct StaticIdent(&'static str);\n\nimpl StaticIdent {\n    pub const fn new(name: &'static str) -> Self {\n        Self(name)\n    }\n}\n\nimpl ToTokens for StaticIdent {\n    fn to_tokens(&self, tokens: &mut TokenStream) {\n        tokens.append(syn::Ident::new(self.0, Span::call_site()));\n    }\n}\n\n/// Adjusts a tokes stream so that the location for the stream comes from `Span`.\n///\n/// This affects where error messages will arise in the compiler output.\npub(crate) fn locate_tokens_at(tokens: TokenStream, span: Span) -> TokenStream {\n    fn set_span_recursively(tokens: TokenStream, span: Span) -> TokenStream {\n        tokens\n            .into_iter()\n            .map(|tt| match tt {\n                TokenTree::Group(g) => {\n                    let inner = set_span_recursively(g.stream(), span);\n                    let mut new_group = proc_macro2::Group::new(g.delimiter(), inner);\n                    new_group.set_span(span);\n                    TokenTree::Group(new_group)\n                }\n                TokenTree::Ident(mut ident) => {\n                    ident.set_span(span);\n                    TokenTree::Ident(ident)\n                }\n                TokenTree::Punct(mut punct) => {\n                    punct.set_span(span);\n                    TokenTree::Punct(punct)\n                }\n                TokenTree::Literal(mut lit) => {\n                    lit.set_span(span);\n                    TokenTree::Literal(lit)\n                }\n            })\n            .collect()\n    }\n\n    let output_span = tokens.span().located_at(span);\n    set_span_recursively(tokens, output_span)\n}\n"
  },
  {
    "path": "pyo3-runtime/README.md",
    "content": "Coming soon!\n"
  },
  {
    "path": "pyo3-runtime/pyproject.toml",
    "content": "[build-system]\nrequires = [\"hatchling\"]\nbuild-backend = \"hatchling.build\"\n\n[project]\nname = \"pyo3-runtime\"\ndynamic = [\"version\"]\ndescription = ''\nreadme = \"README.md\"\nrequires-python = \">=3.7\"\nlicense = \"MIT OR Apache-2.0\"\nkeywords = []\nauthors = [\n  { name = \"David Hewitt\", email = \"1939362+davidhewitt@users.noreply.github.com\" },\n]\nclassifiers = [\n  \"Development Status :: 4 - Beta\",\n  \"Programming Language :: Python\",\n  \"Programming Language :: Python :: 3.7\",\n  \"Programming Language :: Python :: 3.8\",\n  \"Programming Language :: Python :: 3.9\",\n  \"Programming Language :: Python :: 3.10\",\n  \"Programming Language :: Python :: 3.11\",\n  \"Programming Language :: Python :: 3.12\",\n  \"Programming Language :: Python :: Implementation :: CPython\",\n  \"Programming Language :: Python :: Implementation :: PyPy\",\n]\ndependencies = []\n\n[project.urls]\nHomepage = \"https://github.com/PyO3/pyo3\"\n\n[tool.hatch.version]\npath = \"src/pyo3_runtime/__init__.py\"\n"
  },
  {
    "path": "pyo3-runtime/src/pyo3_runtime/__init__.py",
    "content": "__version__ = \"0.0.1\"\n"
  },
  {
    "path": "pyo3-runtime/tests/__init__.py",
    "content": ""
  },
  {
    "path": "pyproject.toml",
    "content": "[project]\nrequires-python = \">=3.7\"\nname = \"pyo3\"\ndynamic = [\"version\"]\n\n[tool.ruff.per-file-target-version]\n# experimental-inspect generates .pyi files that use positional-only `/` marker\n\"*.pyi\" = \"py38\"\n# uses `match` statement\n\"pytests/tests/test_enums_match.py\" = \"py310\"\n\n[tool.ruff.lint.extend-per-file-ignores]\n\"__init__.py\" = [\"F403\"]\n\n[tool.towncrier]\nfilename = \"CHANGELOG.md\"\nversion = \"0.28.2\"\nstart_string = \"<!-- towncrier release notes start -->\\n\"\ntemplate = \".towncrier.template.md\"\ntitle_format = \"## [{version}] - {project_date}\"\nissue_format = \"[#{issue}](https://github.com/PyO3/pyo3/pull/{issue})\"  # Note PyO3 shows pulls, not issues, in the CHANGELOG\nunderlines = [\"\", \"\", \"\"]\ndirectory = \"newsfragments\"\n\n[tool.towncrier.fragment.packaging]\nname = \"Packaging\"\n\n[tool.towncrier.fragment.added]\nname = \"Added\"\n\n[tool.towncrier.fragment.changed]\nname = \"Changed\"\n\n[tool.towncrier.fragment.removed]\nname = \"Removed\"\n\n[tool.towncrier.fragment.fixed]\nname = \"Fixed\"\n\n[tool.rumdl]\n\ndisable = [\n    # TODO: what to do about inline HTML, probably allow?\n    \"MD033\",\n    # TODO: {{#PYO3_DOCS_URL}} placeholder confuses rumdl, change syntax perhaps?\n    \"MD051\"\n]\n\nexclude = [\n    # just has an include to the top-level files\n    \"guide/src/changelog.md\",\n    \"guide/src/contributing.md\"\n]\n\n[tool.rumdl.per-file-ignores]\n\"guide/pyclass-parameters.md\" = [\"MD041\"]\n\n[tool.rumdl.MD004]\nstyle = \"dash\"\n\n[tool.rumdl.MD013]\nline_length = 0\ncode_blocks = false\ntables = false\nheadings = false\nreflow = true\nreflow_mode = \"sentence-per-line\"\n\n[tool.uv]\npackage = false\n\n[dependency-groups]\ndev = [\n  \"rumdl\",\n]\n"
  },
  {
    "path": "pytests/Cargo.toml",
    "content": "[package]\nauthors = [\"PyO3 Authors\"]\nname = \"pyo3-pytests\"\nversion = \"0.1.0\"\ndescription = \"Python-based tests for PyO3\"\nedition = \"2021\"\npublish = false\nrust-version = \"1.83\"\n\n[features]\nexperimental-async = [\"pyo3/experimental-async\"]\nexperimental-inspect = [\"pyo3/experimental-inspect\"]\n\n[dependencies]\npyo3.path = \"../\"\n\n[build-dependencies]\npyo3-build-config = { path = \"../pyo3-build-config\" }\n\n[lib]\nname = \"pyo3_pytests\"\ncrate-type = [\"cdylib\"]\n\n[lints]\nworkspace = true\n"
  },
  {
    "path": "pytests/MANIFEST.in",
    "content": "include pyproject.toml Cargo.toml\nrecursive-include src *\n"
  },
  {
    "path": "pytests/MODULE_DOC.md",
    "content": "This is documentation for the main module of PyO3 integration tests\n\nIt provides multiple modules to do tests"
  },
  {
    "path": "pytests/README.md",
    "content": "# pyo3-pytests\n\nAn extension module built using PyO3, used to test and benchmark PyO3 from Python.\n\nThe `stubs` directory contains Python stubs used to test the automated stubs introspection.\nTo test them run `nox -s test-introspection`.\n\n## Testing\n\nThis package is intended to be built using `maturin`. Once built, you can run the tests using `pytest`:\n\n```shell\npip install maturin\nmaturin develop\npytest\n```\n\nAlternatively, install nox and run the tests inside an isolated environment:\n\n```shell\nnox\n```\n\n## Running benchmarks\n\nYou can install the module in your Python environment and then run the benchmarks with pytest:\n\n```shell\npip install .\npytest --benchmark-enable\n```\n\nOr with nox:\n\n```shell\nnox -s bench\n```\n"
  },
  {
    "path": "pytests/build.rs",
    "content": "fn main() {\n    pyo3_build_config::use_pyo3_cfgs();\n    pyo3_build_config::add_extension_module_link_args();\n}\n"
  },
  {
    "path": "pytests/conftest.py",
    "content": "import sysconfig\nimport sys\nimport pytest\n\nFREE_THREADED_BUILD = bool(sysconfig.get_config_var(\"Py_GIL_DISABLED\"))\n\ngil_enabled_at_start = True\nif FREE_THREADED_BUILD:\n    gil_enabled_at_start = sys._is_gil_enabled()\n\n\ndef pytest_terminal_summary(terminalreporter, exitstatus, config):\n    if FREE_THREADED_BUILD and not gil_enabled_at_start and sys._is_gil_enabled():\n        tr = terminalreporter\n        tr.ensure_newline()\n        tr.section(\"GIL re-enabled\", sep=\"=\", red=True, bold=True)\n        tr.line(\"The GIL was re-enabled at runtime during the tests.\")\n        tr.line(\"\")\n        tr.line(\"Please ensure all new modules declare support for running\")\n        tr.line(\"without the GIL. Any new tests that intentionally imports \")\n        tr.line(\"code that re-enables the GIL should do so in a subprocess.\")\n        pytest.exit(\"GIL re-enabled during tests\", returncode=1)\n"
  },
  {
    "path": "pytests/noxfile.py",
    "content": "import shutil\nfrom pathlib import Path\n\nimport nox\nimport sys\nfrom nox.command import CommandFailed\n\nnox.options.sessions = [\"test\"]\n\n\n@nox.session\ndef test(session: nox.Session):\n    session.env[\"MATURIN_PEP517_ARGS\"] = \"--profile=dev\"\n    session.install(\"-v\", \".[dev]\")\n\n    def try_install_binary(package: str, constraint: str):\n        try:\n            session.install(\"--only-binary=:all:\", f\"{package}{constraint}\")\n        except CommandFailed:\n            # No binary wheel available on this platform\n            pass\n\n    try_install_binary(\"numpy\", \">=1.16\")\n    # https://github.com/zopefoundation/zope.interface/issues/316\n    # - is a dependency of gevent\n    try_install_binary(\"zope.interface\", \"<7\")\n    try_install_binary(\"gevent\", \">=22.10.2\")\n    ignored_paths = []\n    if sys.version_info < (3, 10):\n        # Match syntax is only available in Python >= 3.10\n        ignored_paths.append(\"tests/test_enums_match.py\")\n    ignore_args = [f\"--ignore={path}\" for path in ignored_paths]\n    session.run(\"pytest\", *ignore_args, *session.posargs)\n\n\n@nox.session\ndef bench(session: nox.Session):\n    session.install(\".[dev]\")\n    session.run(\"pytest\", \"--benchmark-enable\", \"--benchmark-only\", *session.posargs)\n\n\n@nox.session\ndef mypy(session: nox.Session):\n    session.env[\"MATURIN_PEP517_ARGS\"] = \"--profile=dev\"\n    try:\n        # We move the stubs where maturin is expecting them to be\n        shutil.copytree(\"stubs\", \"pyo3_pytests\")\n        (Path(\"pyo3_pytests\") / \"py.typed\").touch()\n        session.install(\".[dev]\")\n\n        session.run_always(\n            \"python\",\n            \"-m\",\n            \"mypy\",\n            \"tests\",\n        )\n        # TODO: enable stubtest when previously listed errors will be fixed session.run_always(\"python\", \"-m\", \"mypy.stubtest\", \"pyo3_pytests\")\n    finally:\n        shutil.rmtree(\"pyo3_pytests\")\n"
  },
  {
    "path": "pytests/pyproject.toml",
    "content": "[build-system]\nrequires = [\"maturin>=1.9.4,<2\"]\nbuild-backend = \"maturin\"\n\n[tool.pytest.ini_options]\naddopts = \"--benchmark-disable\"\n\n[project]\nname = \"pyo3_pytests\"\nversion = \"0.1.0\"\nclassifiers = [\n    \"License :: OSI Approved :: MIT License\",\n    \"Development Status :: 3 - Alpha\",\n    \"Intended Audience :: Developers\",\n    \"Programming Language :: Python\",\n    \"Programming Language :: Rust\",\n    \"Operating System :: POSIX\",\n    \"Operating System :: MacOS :: MacOS X\",\n]\n\n[project.optional-dependencies]\ndev = [\n    \"hypothesis>=3.55\",\n    \"mypy~=1.0\",\n    \"pytest-asyncio>=0.21,<2\",\n    \"pytest-benchmark>=3.4\",\n    \"pytest>=7\",\n    \"typing_extensions>=4.0.0\"\n]\n"
  },
  {
    "path": "pytests/src/awaitable.rs",
    "content": "//! The following classes are examples of objects which implement Python's\n//! awaitable protocol.\n//!\n//! Both IterAwaitable and FutureAwaitable will return a value immediately\n//! when awaited, see guide examples related to pyo3-async-runtimes for ways\n//! to suspend tasks and await results.\n\nuse pyo3::prelude::*;\n\n#[pymodule]\npub mod awaitable {\n    use pyo3::exceptions::PyStopIteration;\n    use pyo3::prelude::*;\n\n    #[pyclass]\n    #[derive(Debug)]\n    pub(crate) struct IterAwaitable {\n        result: Option<PyResult<Py<PyAny>>>,\n    }\n\n    #[pymethods]\n    impl IterAwaitable {\n        #[new]\n        fn new(result: Py<PyAny>) -> Self {\n            IterAwaitable {\n                result: Some(Ok(result)),\n            }\n        }\n\n        fn __await__(pyself: PyRef<'_, Self>) -> PyRef<'_, Self> {\n            pyself\n        }\n\n        fn __iter__(pyself: PyRef<'_, Self>) -> PyRef<'_, Self> {\n            pyself\n        }\n\n        fn __next__(&mut self, py: Python<'_>) -> PyResult<Py<PyAny>> {\n            match self.result.take() {\n                Some(res) => match res {\n                    Ok(v) => Err(PyStopIteration::new_err(v)),\n                    Err(err) => Err(err),\n                },\n                _ => Ok(py.None()),\n            }\n        }\n    }\n\n    #[pyclass]\n    pub(crate) struct FutureAwaitable {\n        #[pyo3(get, set, name = \"_asyncio_future_blocking\")]\n        py_block: bool,\n        result: Option<PyResult<Py<PyAny>>>,\n    }\n\n    #[pymethods]\n    impl FutureAwaitable {\n        #[new]\n        fn new(result: Py<PyAny>) -> Self {\n            FutureAwaitable {\n                py_block: false,\n                result: Some(Ok(result)),\n            }\n        }\n\n        fn __await__(pyself: PyRef<'_, Self>) -> PyRef<'_, Self> {\n            pyself\n        }\n\n        fn __iter__(pyself: PyRef<'_, Self>) -> PyRef<'_, Self> {\n            pyself\n        }\n\n        fn __next__(mut pyself: PyRefMut<'_, Self>) -> PyResult<PyRefMut<'_, Self>> {\n            match pyself.result {\n                Some(_) => match pyself.result.take().unwrap() {\n                    Ok(v) => Err(PyStopIteration::new_err(v)),\n                    Err(err) => Err(err),\n                },\n                _ => Ok(pyself),\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "pytests/src/buf_and_str.rs",
    "content": "#![cfg(any(not(Py_LIMITED_API), Py_3_11))]\n\nuse pyo3::prelude::*;\n\n/// Objects related to PyBuffer and PyStr\n#[pymodule]\npub mod buf_and_str {\n    use pyo3::buffer::PyBuffer;\n    use pyo3::prelude::*;\n    use pyo3::types::{PyBytes, PyMemoryView, PyString};\n    use std::borrow::Cow;\n\n    /// This is for confirming that PyBuffer does not cause memory leak\n    #[pyclass]\n    struct BytesExtractor {}\n\n    #[pymethods]\n    impl BytesExtractor {\n        #[new]\n        pub fn __new__() -> Self {\n            BytesExtractor {}\n        }\n\n        #[staticmethod]\n        pub fn from_bytes(bytes: &Bound<'_, PyBytes>) -> PyResult<usize> {\n            let byte_vec: Vec<u8> = bytes.extract()?;\n            Ok(byte_vec.len())\n        }\n\n        #[staticmethod]\n        pub fn from_str(string: &Bound<'_, PyString>) -> PyResult<usize> {\n            let rust_string: String = string.extract()?;\n            Ok(rust_string.len())\n        }\n\n        #[staticmethod]\n        pub fn from_str_lossy(string: &Bound<'_, PyString>) -> usize {\n            let rust_string_lossy: String = string.to_string_lossy().to_string();\n            rust_string_lossy.len()\n        }\n\n        #[staticmethod]\n        pub fn from_buffer(buf: &Bound<'_, PyAny>) -> PyResult<usize> {\n            let buf = PyBuffer::<u8>::get(buf)?;\n            Ok(buf.item_count())\n        }\n    }\n\n    #[pyfunction]\n    fn return_memoryview(py: Python<'_>) -> PyResult<Bound<'_, PyMemoryView>> {\n        let bytes = PyBytes::new(py, b\"hello world\");\n        PyMemoryView::from(&bytes)\n    }\n\n    #[pyfunction]\n    fn map_byte_slice(bytes: &[u8]) -> &[u8] {\n        bytes\n    }\n\n    #[pyfunction]\n    fn map_byte_cow(bytes: Cow<'_, [u8]>) -> Cow<'_, [u8]> {\n        bytes\n    }\n\n    #[pyfunction]\n    fn map_byte_vec(bytes: Vec<u8>) -> Vec<u8> {\n        bytes\n    }\n}\n"
  },
  {
    "path": "pytests/src/comparisons.rs",
    "content": "use pyo3::basic::CompareOp;\nuse pyo3::prelude::*;\nuse std::fmt;\n\n#[pyclass(frozen)]\nstruct Eq(i64);\n\n#[pymethods]\nimpl Eq {\n    #[new]\n    fn new(value: i64) -> Self {\n        Self(value)\n    }\n\n    fn __eq__(&self, other: &Self) -> bool {\n        self.0 == other.0\n    }\n\n    fn __ne__(&self, other: &Self) -> bool {\n        self.0 != other.0\n    }\n}\n\n#[pyclass(frozen)]\nstruct EqDefaultNe(i64);\n\n#[pymethods]\nimpl EqDefaultNe {\n    #[new]\n    fn new(value: i64) -> Self {\n        Self(value)\n    }\n\n    fn __eq__(&self, other: &Self) -> bool {\n        self.0 == other.0\n    }\n}\n\n#[pyclass(eq, frozen)]\n#[derive(PartialEq, Eq)]\nstruct EqDerived(i64);\n\n#[pymethods]\nimpl EqDerived {\n    #[new]\n    fn new(value: i64) -> Self {\n        Self(value)\n    }\n}\n\n#[pyclass(frozen)]\nstruct Ordered(i64);\n\n#[pymethods]\nimpl Ordered {\n    #[new]\n    fn new(value: i64) -> Self {\n        Self(value)\n    }\n\n    fn __lt__(&self, other: &Self) -> bool {\n        self.0 < other.0\n    }\n\n    fn __le__(&self, other: &Self) -> bool {\n        self.0 <= other.0\n    }\n\n    fn __eq__(&self, other: &Self) -> bool {\n        self.0 == other.0\n    }\n\n    fn __ne__(&self, other: &Self) -> bool {\n        self.0 != other.0\n    }\n\n    fn __gt__(&self, other: &Self) -> bool {\n        self.0 > other.0\n    }\n\n    fn __ge__(&self, other: &Self) -> bool {\n        self.0 >= other.0\n    }\n}\n\n#[pyclass(frozen)]\nstruct OrderedRichCmp(i64);\n\n#[pymethods]\nimpl OrderedRichCmp {\n    #[new]\n    fn new(value: i64) -> Self {\n        Self(value)\n    }\n\n    fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool {\n        op.matches(self.0.cmp(&other.0))\n    }\n}\n\n#[pyclass(eq, ord, hash, str, frozen)]\n#[derive(PartialEq, Eq, Ord, PartialOrd, Hash)]\nstruct OrderedDerived(i64);\n\nimpl fmt::Display for OrderedDerived {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        self.0.fmt(f)\n    }\n}\n\n#[pymethods]\nimpl OrderedDerived {\n    #[new]\n    fn new(value: i64) -> Self {\n        Self(value)\n    }\n}\n\n#[pyclass(frozen)]\nstruct OrderedDefaultNe(i64);\n\n#[pymethods]\nimpl OrderedDefaultNe {\n    #[new]\n    fn new(value: i64) -> Self {\n        Self(value)\n    }\n\n    fn __lt__(&self, other: &Self) -> bool {\n        self.0 < other.0\n    }\n\n    fn __le__(&self, other: &Self) -> bool {\n        self.0 <= other.0\n    }\n\n    fn __eq__(&self, other: &Self) -> bool {\n        self.0 == other.0\n    }\n\n    fn __gt__(&self, other: &Self) -> bool {\n        self.0 > other.0\n    }\n\n    fn __ge__(&self, other: &Self) -> bool {\n        self.0 >= other.0\n    }\n}\n\n#[pymodule]\npub mod comparisons {\n    #[pymodule_export]\n    use super::{\n        Eq, EqDefaultNe, EqDerived, Ordered, OrderedDefaultNe, OrderedDerived, OrderedRichCmp,\n    };\n}\n"
  },
  {
    "path": "pytests/src/consts.rs",
    "content": "use pyo3::pymodule;\n\n#[pymodule]\npub mod consts {\n    use pyo3::{pyclass, pymethods};\n\n    /// Exports PI constant as part of the module\n    #[pymodule_export]\n    pub const PI: f64 = std::f64::consts::PI;\n\n    /// We experiment with \"escaping\"\n    #[pymodule_export]\n    pub const ESCAPING: &str = \"S\\0\\x01\\t\\n\\r\\\"'\\\\\";\n\n    #[pyclass]\n    struct ClassWithConst {}\n\n    #[pymethods]\n    impl ClassWithConst {\n        /// A constant\n        #[classattr]\n        const INSTANCE: Self = ClassWithConst {};\n    }\n}\n"
  },
  {
    "path": "pytests/src/datetime.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::{\n    PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess, PyTuple,\n    PyTzInfo, PyTzInfoAccess,\n};\n\n#[pyfunction]\nfn make_date(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult<Bound<'_, PyDate>> {\n    PyDate::new(py, year, month, day)\n}\n\n#[pyfunction]\nfn get_date_tuple<'py>(d: &Bound<'py, PyDate>) -> PyResult<Bound<'py, PyTuple>> {\n    PyTuple::new(\n        d.py(),\n        [d.get_year(), d.get_month() as i32, d.get_day() as i32],\n    )\n}\n\n#[pyfunction]\nfn date_from_timestamp(py: Python<'_>, timestamp: f64) -> PyResult<Bound<'_, PyDate>> {\n    PyDate::from_timestamp(py, timestamp)\n}\n\n#[pyfunction]\n#[pyo3(signature=(hour, minute, second, microsecond, tzinfo=None))]\nfn make_time<'py>(\n    py: Python<'py>,\n    hour: u8,\n    minute: u8,\n    second: u8,\n    microsecond: u32,\n    tzinfo: Option<&Bound<'py, PyTzInfo>>,\n) -> PyResult<Bound<'py, PyTime>> {\n    PyTime::new(py, hour, minute, second, microsecond, tzinfo)\n}\n\n#[pyfunction]\n#[pyo3(signature = (hour, minute, second, microsecond, tzinfo, fold))]\nfn time_with_fold<'py>(\n    py: Python<'py>,\n    hour: u8,\n    minute: u8,\n    second: u8,\n    microsecond: u32,\n    tzinfo: Option<&Bound<'py, PyTzInfo>>,\n    fold: bool,\n) -> PyResult<Bound<'py, PyTime>> {\n    PyTime::new_with_fold(py, hour, minute, second, microsecond, tzinfo, fold)\n}\n\n#[pyfunction]\nfn get_time_tuple<'py>(dt: &Bound<'py, PyTime>) -> PyResult<Bound<'py, PyTuple>> {\n    PyTuple::new(\n        dt.py(),\n        [\n            dt.get_hour() as u32,\n            dt.get_minute() as u32,\n            dt.get_second() as u32,\n            dt.get_microsecond(),\n        ],\n    )\n}\n\n#[pyfunction]\nfn get_time_tuple_fold<'py>(dt: &Bound<'py, PyTime>) -> PyResult<Bound<'py, PyTuple>> {\n    PyTuple::new(\n        dt.py(),\n        [\n            dt.get_hour() as u32,\n            dt.get_minute() as u32,\n            dt.get_second() as u32,\n            dt.get_microsecond(),\n            dt.get_fold() as u32,\n        ],\n    )\n}\n\n#[pyfunction]\nfn make_delta(\n    py: Python<'_>,\n    days: i32,\n    seconds: i32,\n    microseconds: i32,\n) -> PyResult<Bound<'_, PyDelta>> {\n    PyDelta::new(py, days, seconds, microseconds, true)\n}\n\n#[pyfunction]\nfn get_delta_tuple<'py>(delta: &Bound<'py, PyDelta>) -> PyResult<Bound<'py, PyTuple>> {\n    PyTuple::new(\n        delta.py(),\n        [\n            delta.get_days(),\n            delta.get_seconds(),\n            delta.get_microseconds(),\n        ],\n    )\n}\n\n#[expect(clippy::too_many_arguments)]\n#[pyfunction]\n#[pyo3(signature=(year, month, day, hour, minute, second, microsecond, tzinfo=None))]\nfn make_datetime<'py>(\n    py: Python<'py>,\n    year: i32,\n    month: u8,\n    day: u8,\n    hour: u8,\n    minute: u8,\n    second: u8,\n    microsecond: u32,\n    tzinfo: Option<&Bound<'py, PyTzInfo>>,\n) -> PyResult<Bound<'py, PyDateTime>> {\n    PyDateTime::new(\n        py,\n        year,\n        month,\n        day,\n        hour,\n        minute,\n        second,\n        microsecond,\n        tzinfo,\n    )\n}\n\n#[pyfunction]\nfn get_datetime_tuple<'py>(dt: &Bound<'py, PyDateTime>) -> PyResult<Bound<'py, PyTuple>> {\n    PyTuple::new(\n        dt.py(),\n        [\n            dt.get_year(),\n            dt.get_month() as i32,\n            dt.get_day() as i32,\n            dt.get_hour() as i32,\n            dt.get_minute() as i32,\n            dt.get_second() as i32,\n            dt.get_microsecond() as i32,\n        ],\n    )\n}\n\n#[pyfunction]\nfn get_datetime_tuple_fold<'py>(dt: &Bound<'py, PyDateTime>) -> PyResult<Bound<'py, PyTuple>> {\n    PyTuple::new(\n        dt.py(),\n        [\n            dt.get_year(),\n            dt.get_month() as i32,\n            dt.get_day() as i32,\n            dt.get_hour() as i32,\n            dt.get_minute() as i32,\n            dt.get_second() as i32,\n            dt.get_microsecond() as i32,\n            dt.get_fold() as i32,\n        ],\n    )\n}\n\n#[pyfunction]\n#[pyo3(signature=(ts, tz=None))]\nfn datetime_from_timestamp<'py>(\n    py: Python<'py>,\n    ts: f64,\n    tz: Option<&Bound<'py, PyTzInfo>>,\n) -> PyResult<Bound<'py, PyDateTime>> {\n    PyDateTime::from_timestamp(py, ts, tz)\n}\n\n#[pyfunction]\nfn get_datetime_tzinfo<'py>(dt: &Bound<'py, PyDateTime>) -> Option<Bound<'py, PyTzInfo>> {\n    dt.get_tzinfo()\n}\n\n#[pyfunction]\nfn get_time_tzinfo<'py>(dt: &Bound<'py, PyTime>) -> Option<Bound<'py, PyTzInfo>> {\n    dt.get_tzinfo()\n}\n\n#[pyclass(extends=PyTzInfo)]\npub struct TzClass {}\n\n#[pymethods]\nimpl TzClass {\n    #[new]\n    fn new() -> Self {\n        TzClass {}\n    }\n\n    #[pyo3(signature = (_dt, /))]\n    fn utcoffset<'py>(\n        &self,\n        _dt: Option<&Bound<'_, PyDateTime>>,\n        py: Python<'py>,\n    ) -> PyResult<Bound<'py, PyDelta>> {\n        PyDelta::new(py, 0, 3600, 0, true)\n    }\n\n    #[pyo3(signature = (_dt, /))]\n    fn tzname(&self, _dt: Option<&Bound<'_, PyDateTime>>) -> String {\n        String::from(\"+01:00\")\n    }\n\n    #[pyo3(signature = (_dt, /))]\n    fn dst(&self, _dt: Option<&Bound<'_, PyDateTime>>) -> Option<Bound<'static, PyDelta>> {\n        None\n    }\n}\n\n#[pymodule]\npub mod datetime {\n    #[pymodule_export]\n    use super::{\n        date_from_timestamp, datetime_from_timestamp, get_date_tuple, get_datetime_tuple,\n        get_datetime_tuple_fold, get_datetime_tzinfo, get_delta_tuple, get_time_tuple,\n        get_time_tuple_fold, get_time_tzinfo, make_date, make_datetime, make_delta, make_time,\n        time_with_fold, TzClass,\n    };\n}\n"
  },
  {
    "path": "pytests/src/dict_iter.rs",
    "content": "use pyo3::prelude::*;\n\n#[pymodule]\npub mod dict_iter {\n    use pyo3::exceptions::PyRuntimeError;\n    use pyo3::prelude::*;\n    use pyo3::types::PyDict;\n\n    #[pyclass]\n    pub struct DictSize {\n        expected: u32,\n    }\n\n    #[pymethods]\n    impl DictSize {\n        #[new]\n        fn new(expected: u32) -> Self {\n            DictSize { expected }\n        }\n\n        fn iter_dict(&mut self, _py: Python<'_>, dict: &Bound<'_, PyDict>) -> PyResult<u32> {\n            let mut seen = 0u32;\n            for (sym, values) in dict {\n                seen += 1;\n                println!(\n                    \"{:4}/{:4} iterations:{}=>{}\",\n                    seen, self.expected, sym, values\n                );\n            }\n\n            if seen == self.expected {\n                Ok(seen)\n            } else {\n                Err(PyErr::new::<PyRuntimeError, _>(format!(\n                    \"Expected {} iterations - performed {}\",\n                    self.expected, seen\n                )))\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "pytests/src/enums.rs",
    "content": "use pyo3::{pyclass, pyfunction, pymodule};\n\n#[pymodule]\npub mod enums {\n    #[pymodule_export]\n    use super::{\n        do_complex_stuff, do_mixed_complex_stuff, do_simple_stuff, do_tuple_stuff, ComplexEnum,\n        MixedComplexEnum, SimpleEnum, SimpleEnumWithoutDerive, SimpleTupleEnum, TupleEnum,\n    };\n}\n\n#[pyclass(eq, eq_int)]\n#[derive(PartialEq)]\npub enum SimpleEnum {\n    /// A variant\n    Sunday,\n    Monday,\n    Tuesday,\n    Wednesday,\n    Thursday,\n    Friday,\n    Saturday,\n}\n\n#[pyclass]\npub enum SimpleEnumWithoutDerive {\n    A,\n    B,\n}\n\n#[pyfunction]\npub fn do_simple_stuff(thing: &SimpleEnum) -> SimpleEnum {\n    match thing {\n        SimpleEnum::Sunday => SimpleEnum::Monday,\n        SimpleEnum::Monday => SimpleEnum::Tuesday,\n        SimpleEnum::Tuesday => SimpleEnum::Wednesday,\n        SimpleEnum::Wednesday => SimpleEnum::Thursday,\n        SimpleEnum::Thursday => SimpleEnum::Friday,\n        SimpleEnum::Friday => SimpleEnum::Saturday,\n        SimpleEnum::Saturday => SimpleEnum::Sunday,\n    }\n}\n\n#[pyclass]\npub enum ComplexEnum {\n    /// A struct variant\n    Int {\n        /// An integer\n        i: i32,\n    },\n    Float {\n        f: f64,\n    },\n    Str {\n        s: String,\n    },\n    EmptyStruct {},\n    MultiFieldStruct {\n        a: i32,\n        b: f64,\n        c: bool,\n    },\n    #[pyo3(constructor = (a = 42, b = None))]\n    VariantWithDefault {\n        a: i32,\n        b: Option<String>,\n    },\n}\n\n#[pyfunction]\npub fn do_complex_stuff(thing: &ComplexEnum) -> ComplexEnum {\n    match thing {\n        ComplexEnum::Int { i } => ComplexEnum::Str { s: i.to_string() },\n        ComplexEnum::Float { f } => ComplexEnum::Float { f: f * f },\n        ComplexEnum::Str { s } => ComplexEnum::Int { i: s.len() as i32 },\n        ComplexEnum::EmptyStruct {} => ComplexEnum::EmptyStruct {},\n        ComplexEnum::MultiFieldStruct { a, b, c } => ComplexEnum::MultiFieldStruct {\n            a: *a,\n            b: *b,\n            c: *c,\n        },\n        ComplexEnum::VariantWithDefault { a, b } => ComplexEnum::VariantWithDefault {\n            a: 2 * a,\n            b: b.as_ref().map(|s| s.to_uppercase()),\n        },\n    }\n}\n\n#[pyclass]\nenum SimpleTupleEnum {\n    Int(i32),\n    Str(String),\n}\n\n#[pyclass]\npub enum TupleEnum {\n    /// A tuple variant\n    #[pyo3(constructor = (_0 = 1, _1 = 1.0, _2 = true))]\n    FullWithDefault(i32, f64, bool),\n    Full(i32, f64, bool),\n    EmptyTuple(),\n}\n\n#[pyfunction]\npub fn do_tuple_stuff(thing: &TupleEnum) -> TupleEnum {\n    match thing {\n        TupleEnum::FullWithDefault(a, b, c) => TupleEnum::FullWithDefault(*a, *b, *c),\n        TupleEnum::Full(a, b, c) => TupleEnum::Full(*a, *b, *c),\n        TupleEnum::EmptyTuple() => TupleEnum::EmptyTuple(),\n    }\n}\n\n#[pyclass]\npub enum MixedComplexEnum {\n    Nothing {},\n    Empty(),\n}\n\n#[pyfunction]\npub fn do_mixed_complex_stuff(thing: &MixedComplexEnum) -> MixedComplexEnum {\n    match thing {\n        MixedComplexEnum::Nothing {} => MixedComplexEnum::Empty(),\n        MixedComplexEnum::Empty() => MixedComplexEnum::Nothing {},\n    }\n}\n"
  },
  {
    "path": "pytests/src/exception.rs",
    "content": "use pyo3::create_exception;\nuse pyo3::exceptions::PyValueError;\nuse pyo3::prelude::*;\n\ncreate_exception!(pytests.exception, MyValueError, PyValueError);\n\n#[pymodule(gil_used = false)]\npub mod exception {\n    use pyo3::exceptions::PyValueError;\n    use pyo3::prelude::*;\n\n    #[pymodule_export]\n    use super::MyValueError;\n\n    #[pyfunction]\n    fn raise_my_value_error() -> PyResult<()> {\n        Err(MyValueError::new_err(\"error\"))\n    }\n\n    #[pyfunction]\n    fn return_value_error<'py>(py: Python<'py>) -> PyResult<Bound<'py, PyValueError>> {\n        Ok(PyValueError::new_err(\"error\")\n            .into_pyobject(py)?\n            .cast_into()?)\n    }\n\n    #[pyfunction]\n    fn return_my_value_error<'py>(py: Python<'py>) -> PyResult<Bound<'py, MyValueError>> {\n        Ok(MyValueError::new_err(\"error\")\n            .into_pyobject(py)?\n            .cast_into()?)\n    }\n\n    #[pyfunction]\n    fn return_pyerr() -> PyErr {\n        MyValueError::new_err(\"error\")\n    }\n}\n"
  },
  {
    "path": "pytests/src/lib.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::PyDict;\n\nmod awaitable;\nmod buf_and_str;\nmod comparisons;\nmod consts;\n#[cfg(not(Py_LIMITED_API))]\nmod datetime;\nmod dict_iter;\nmod enums;\nmod exception;\nmod misc;\nmod objstore;\nmod othermod;\nmod path;\nmod pyclasses;\nmod pyfunctions;\nmod sequence;\nmod subclassing;\n\n#[doc = include_str!(\"../MODULE_DOC.md\")]\n#[pymodule]\nmod pyo3_pytests {\n    use super::*;\n\n    #[cfg(any(not(Py_LIMITED_API), Py_3_11))]\n    #[pymodule_export]\n    use buf_and_str::buf_and_str;\n\n    #[cfg(not(Py_LIMITED_API))]\n    #[pymodule_export]\n    use datetime::datetime;\n\n    #[pymodule_export]\n    use {\n        awaitable::awaitable, comparisons::comparisons, consts::consts, dict_iter::dict_iter,\n        enums::enums, exception::exception, misc::misc, objstore::objstore, othermod::othermod,\n        path::path, pyclasses::pyclasses, pyfunctions::pyfunctions, sequence::sequence,\n        subclassing::subclassing,\n    };\n\n    // Inserting to sys.modules allows importing submodules nicely from Python\n    // e.g. import pyo3_pytests.buf_and_str as bas\n    #[pymodule_init]\n    fn init(m: &Bound<'_, PyModule>) -> PyResult<()> {\n        let sys = PyModule::import(m.py(), \"sys\")?;\n        let sys_modules = sys.getattr(\"modules\")?.cast_into::<PyDict>()?;\n        sys_modules.set_item(\"pyo3_pytests.awaitable\", m.getattr(\"awaitable\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.buf_and_str\", m.getattr(\"buf_and_str\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.comparisons\", m.getattr(\"comparisons\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.datetime\", m.getattr(\"datetime\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.dict_iter\", m.getattr(\"dict_iter\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.enums\", m.getattr(\"enums\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.misc\", m.getattr(\"misc\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.objstore\", m.getattr(\"objstore\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.othermod\", m.getattr(\"othermod\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.path\", m.getattr(\"path\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.pyclasses\", m.getattr(\"pyclasses\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.pyfunctions\", m.getattr(\"pyfunctions\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.sequence\", m.getattr(\"sequence\")?)?;\n        sys_modules.set_item(\"pyo3_pytests.subclassing\", m.getattr(\"subclassing\")?)?;\n\n        Ok(())\n    }\n}\n"
  },
  {
    "path": "pytests/src/misc.rs",
    "content": "use pyo3::{\n    prelude::*,\n    types::{PyDict, PyString},\n};\n\n#[pyfunction]\nfn issue_219() {\n    // issue 219: attaching inside #[pyfunction] deadlocks.\n    Python::attach(|_| {});\n}\n\n#[pyclass]\nstruct LockHolder {\n    #[expect(unused, reason = \"used to block until sender is dropped\")]\n    sender: std::sync::mpsc::Sender<()>,\n}\n\n// This will repeatedly attach and detach from the Python interpreter\n// once the LockHolder is dropped.\n#[pyfunction]\nfn hammer_attaching_in_thread() -> LockHolder {\n    let (sender, receiver) = std::sync::mpsc::channel();\n    std::thread::spawn(move || {\n        receiver.recv().ok();\n        // now the interpreter has shut down, so hammer the attach API. In buggy\n        // versions of PyO3 this will cause a crash.\n        loop {\n            Python::try_attach(|_py| ());\n        }\n    });\n    LockHolder { sender }\n}\n\n#[pyfunction]\nfn get_type_fully_qualified_name<'py>(obj: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyString>> {\n    obj.get_type().fully_qualified_name()\n}\n\n#[pyfunction]\nfn accepts_bool(val: bool) -> bool {\n    val\n}\n\n#[pyfunction]\nfn get_item_and_run_callback(dict: Bound<'_, PyDict>, callback: Bound<'_, PyAny>) -> PyResult<()> {\n    // This function gives the opportunity to run a pure-Python callback so that\n    // gevent can instigate a context switch. This had problematic interactions\n    // with PyO3's removed \"GIL Pool\".\n    // For context, see https://github.com/PyO3/pyo3/issues/3668\n    let item = dict.get_item(\"key\")?.expect(\"key not found in dict\");\n    let string = item.to_string();\n    callback.call0()?;\n    assert_eq!(item.to_string(), string);\n    Ok(())\n}\n\n#[pymodule]\npub mod misc {\n    #[pymodule_export]\n    use super::{\n        accepts_bool, get_item_and_run_callback, get_type_fully_qualified_name,\n        hammer_attaching_in_thread, issue_219,\n    };\n}\n"
  },
  {
    "path": "pytests/src/objstore.rs",
    "content": "use pyo3::prelude::*;\n\n#[pymodule]\npub mod objstore {\n    use pyo3::prelude::*;\n\n    #[pyclass]\n    #[derive(Default)]\n    pub struct ObjStore {\n        obj: Vec<Py<PyAny>>,\n    }\n\n    #[pymethods]\n    impl ObjStore {\n        #[new]\n        fn new() -> Self {\n            ObjStore::default()\n        }\n\n        fn push(&mut self, obj: &Bound<'_, PyAny>) {\n            self.obj.push(obj.clone().unbind());\n        }\n    }\n}\n"
  },
  {
    "path": "pytests/src/othermod.rs",
    "content": "//! <https://github.com/PyO3/pyo3/issues/233>\n//!\n//! The code below just tries to use the most important code generation paths\n\nuse pyo3::prelude::*;\n\n#[pymodule]\npub mod othermod {\n    use pyo3::prelude::*;\n\n    #[pyclass]\n    pub struct ModClass {\n        _somefield: String,\n    }\n\n    #[pymethods]\n    impl ModClass {\n        #[new]\n        fn new() -> Self {\n            ModClass {\n                _somefield: String::from(\"contents\"),\n            }\n        }\n\n        fn noop(&self, x: usize) -> usize {\n            x\n        }\n    }\n\n    #[pyfunction]\n    fn double(x: i32) -> i32 {\n        x * 2\n    }\n\n    #[pymodule_export]\n    pub const USIZE_MIN: usize = usize::MIN;\n    #[pymodule_export]\n    pub const USIZE_MAX: usize = usize::MAX;\n}\n"
  },
  {
    "path": "pytests/src/path.rs",
    "content": "use pyo3::prelude::*;\n\n#[pymodule]\npub mod path {\n    use pyo3::prelude::*;\n    use std::path::{Path, PathBuf};\n\n    #[pyfunction]\n    fn make_path() -> PathBuf {\n        Path::new(\"/root\").to_owned()\n    }\n\n    #[pyfunction]\n    fn take_pathbuf(path: PathBuf) -> PathBuf {\n        path\n    }\n}\n"
  },
  {
    "path": "pytests/src/pyclasses.rs",
    "content": "use std::{thread, time};\n\nuse pyo3::basic::CompareOp;\nuse pyo3::exceptions::{PyAttributeError, PyStopIteration, PyValueError};\nuse pyo3::prelude::*;\nuse pyo3::types::{PyComplex, PyType};\n#[cfg(not(any(Py_LIMITED_API, GraalPy)))]\nuse pyo3::types::{PyDict, PyTuple};\n\n#[pyclass(from_py_object)]\n#[derive(Clone, Default)]\nstruct EmptyClass {}\n\n#[pymethods]\nimpl EmptyClass {\n    #[new]\n    fn new() -> Self {\n        EmptyClass {}\n    }\n\n    fn method(&self) {}\n\n    fn __len__(&self) -> usize {\n        0\n    }\n}\n\n/// This is for demonstrating how to return a value from __next__\n#[pyclass]\n#[derive(Default)]\nstruct PyClassIter {\n    count: usize,\n}\n\n#[pymethods]\nimpl PyClassIter {\n    /// A constructor\n    #[new]\n    pub fn new() -> Self {\n        Default::default()\n    }\n\n    fn __next__(&mut self) -> PyResult<usize> {\n        if self.count < 5 {\n            self.count += 1;\n            Ok(self.count)\n        } else {\n            Err(PyStopIteration::new_err(\"Ended\"))\n        }\n    }\n}\n\n#[pyclass]\n#[derive(Default)]\nstruct PyClassThreadIter {\n    count: usize,\n}\n\n#[pymethods]\nimpl PyClassThreadIter {\n    #[new]\n    pub fn new() -> Self {\n        Default::default()\n    }\n\n    fn __next__(&mut self, py: Python<'_>) -> usize {\n        let current_count = self.count;\n        self.count += 1;\n        if current_count == 0 {\n            py.detach(|| thread::sleep(time::Duration::from_millis(100)));\n        }\n        self.count\n    }\n}\n\n/// Demonstrates a base class which can operate on the relevant subclass in its constructor.\n#[pyclass(subclass, skip_from_py_object)]\n#[derive(Clone, Debug)]\nstruct AssertingBaseClass;\n\n#[pymethods]\nimpl AssertingBaseClass {\n    #[new]\n    #[classmethod]\n    fn new(cls: &Bound<'_, PyType>, expected_type: Bound<'_, PyType>) -> PyResult<Self> {\n        if !cls.is(&expected_type) {\n            return Err(PyValueError::new_err(format!(\n                \"{cls:?} != {expected_type:?}\"\n            )));\n        }\n        Ok(Self)\n    }\n}\n\n#[pyclass]\nstruct ClassWithoutConstructor;\n\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n#[pyclass(dict)]\nstruct ClassWithDict;\n\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n#[pymethods]\nimpl ClassWithDict {\n    #[new]\n    fn new() -> Self {\n        ClassWithDict\n    }\n}\n\n#[cfg(not(any(Py_LIMITED_API, GraalPy)))] // Can't subclass native types on abi3 yet\n#[pyclass(extends = PyDict)]\nstruct SubClassWithInit;\n\n#[cfg(not(any(Py_LIMITED_API, GraalPy)))]\n#[pymethods]\nimpl SubClassWithInit {\n    #[new]\n    #[pyo3(signature = (*args, **kwargs))]\n    #[allow(unused_variables)]\n    fn __new__(args: &Bound<'_, PyTuple>, kwargs: Option<&Bound<'_, PyDict>>) -> Self {\n        Self\n    }\n\n    #[pyo3(signature = (*args, **kwargs))]\n    fn __init__(\n        self_: &Bound<'_, Self>,\n        args: &Bound<'_, PyTuple>,\n        kwargs: Option<&Bound<'_, PyDict>>,\n    ) -> PyResult<()> {\n        self_\n            .py_super()?\n            .call_method(\"__init__\", args.to_owned(), kwargs)?;\n        self_.as_super().set_item(\"__init__\", true)?;\n        Ok(())\n    }\n}\n\n#[pyclass(skip_from_py_object)]\n#[derive(Clone)]\nstruct ClassWithDecorators {\n    attr: Option<usize>,\n}\n\n#[pymethods]\nimpl ClassWithDecorators {\n    #[new]\n    #[classmethod]\n    fn new(_cls: Bound<'_, PyType>) -> Self {\n        Self { attr: Some(0) }\n    }\n\n    /// A getter\n    #[getter]\n    fn get_attr(&self) -> PyResult<usize> {\n        self.attr\n            .ok_or_else(|| PyAttributeError::new_err(\"attr is not set\"))\n    }\n\n    /// A setter\n    #[setter]\n    fn set_attr(&mut self, value: usize) {\n        self.attr = Some(value);\n    }\n\n    /// A deleter\n    #[deleter]\n    fn delete_attr(&mut self) {\n        self.attr = None;\n    }\n\n    /// A class method\n    #[classmethod]\n    fn cls_method(_cls: &Bound<'_, PyType>) -> usize {\n        1\n    }\n\n    /// A static method\n    #[staticmethod]\n    fn static_method() -> usize {\n        2\n    }\n\n    /// A class attribute\n    #[classattr]\n    fn cls_attribute() -> usize {\n        3\n    }\n}\n\n#[pyclass(get_all, set_all)]\nstruct PlainObject {\n    /// Foo\n    foo: String,\n    /// Bar\n    bar: usize,\n}\n\n#[derive(FromPyObject, IntoPyObject)]\nenum AClass {\n    NewType(EmptyClass),\n    Tuple(EmptyClass, EmptyClass),\n    Struct {\n        f: EmptyClass,\n        #[pyo3(item(42))]\n        g: EmptyClass,\n        #[pyo3(default)]\n        h: EmptyClass,\n    },\n}\n\n#[pyfunction]\nfn map_a_class(cls: AClass) -> AClass {\n    cls\n}\n\n#[pyclass]\nstruct Number(u64);\n\n// TODO: Implementations are just for the example and often not correct\n#[pymethods]\nimpl Number {\n    #[new]\n    fn new(value: u64) -> Self {\n        Self(value)\n    }\n\n    fn __str__(&self) -> String {\n        self.0.to_string()\n    }\n\n    fn __repr__(&self) -> String {\n        format!(\"{:?}\", self.0)\n    }\n\n    fn __hash__(&self) -> u64 {\n        self.0\n    }\n\n    fn __richcmp__(&self, other: &Self, op: CompareOp) -> bool {\n        op.matches(self.0.cmp(&other.0))\n    }\n\n    fn __add__(&self, other: &Self) -> Self {\n        Self(self.0 + other.0)\n    }\n\n    fn __sub__(&self, other: &Self) -> Self {\n        Self(self.0 - other.0)\n    }\n\n    fn __mul__(&self, other: &Self) -> Self {\n        Self(self.0 * other.0)\n    }\n\n    fn __matmul__(&self, other: &Self) -> Self {\n        Self(self.0 * other.0)\n    }\n\n    fn __truediv__(&self, other: &Self) -> Self {\n        Self(self.0 / other.0)\n    }\n\n    fn __floordiv__(&self, other: &Self) -> Self {\n        Self(self.0 / other.0)\n    }\n\n    fn __mod__(&self, other: &Self) -> Self {\n        Self(self.0 % other.0)\n    }\n\n    fn __divmod__(&self, other: &Self) -> (Self, Self) {\n        (Self(self.0 / other.0), Self(self.0 % other.0))\n    }\n\n    fn __pow__(&self, other: &Self, modulo: Option<&Self>) -> Self {\n        Self(self.0.pow(other.0 as u32) % modulo.map_or(1, |m| m.0))\n    }\n\n    fn __rshift__(&self, other: &Self) -> Self {\n        Self(self.0 >> other.0)\n    }\n\n    fn __lshift__(&self, other: &Self) -> Self {\n        Self(self.0 << other.0)\n    }\n\n    fn __and__(&self, other: &Self) -> Self {\n        Self(self.0 & other.0)\n    }\n\n    fn __or__(&self, other: &Self) -> Self {\n        Self(self.0 | other.0)\n    }\n\n    fn __xor__(&self, other: &Self) -> Self {\n        Self(self.0 ^ other.0)\n    }\n\n    fn __pos__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {\n        slf\n    }\n\n    fn __neg__(&self) -> PyResult<Self> {\n        if self.0 == 0 {\n            Ok(Self(0))\n        } else {\n            Err(PyValueError::new_err(\"not zero\"))\n        }\n    }\n\n    fn __abs__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {\n        slf\n    }\n\n    fn __invert__(&self) -> Self {\n        Self(!self.0)\n    }\n\n    fn __int__(&self) -> u64 {\n        self.0\n    }\n\n    fn __float__(&self) -> f64 {\n        self.0 as f64\n    }\n\n    fn __complex__<'py>(&self, py: Python<'py>) -> Bound<'py, PyComplex> {\n        PyComplex::from_doubles(py, self.0 as f64, 0.)\n    }\n}\n\n#[pymodule]\npub mod pyclasses {\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    #[pymodule_export]\n    use super::ClassWithDict;\n    #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\n    #[pymodule_export]\n    use super::SubClassWithInit;\n    #[pymodule_export]\n    use super::{\n        map_a_class, AssertingBaseClass, ClassWithDecorators, ClassWithoutConstructor, EmptyClass,\n        Number, PlainObject, PyClassIter, PyClassThreadIter,\n    };\n}\n"
  },
  {
    "path": "pytests/src/pyfunctions.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::{PyDict, PyTuple};\n\n#[pyfunction(signature = ())]\nfn none() {}\n\ntype Any<'py> = Bound<'py, PyAny>;\ntype Dict<'py> = Bound<'py, PyDict>;\ntype Tuple<'py> = Bound<'py, PyTuple>;\n\n#[pyfunction(signature = (a, b = None, *, c = None))]\nfn simple<'py>(\n    a: Any<'py>,\n    b: Option<Any<'py>>,\n    c: Option<Any<'py>>,\n) -> (Any<'py>, Option<Any<'py>>, Option<Any<'py>>) {\n    (a, b, c)\n}\n\n#[pyfunction(signature = (a, b = None, *args, c = None))]\nfn simple_args<'py>(\n    a: Any<'py>,\n    b: Option<Any<'py>>,\n    args: Tuple<'py>,\n    c: Option<Any<'py>>,\n) -> (Any<'py>, Option<Any<'py>>, Tuple<'py>, Option<Any<'py>>) {\n    (a, b, args, c)\n}\n\n#[pyfunction(signature = (a, b = None, c = None, **kwargs))]\nfn simple_kwargs<'py>(\n    a: Any<'py>,\n    b: Option<Any<'py>>,\n    c: Option<Any<'py>>,\n    kwargs: Option<Dict<'py>>,\n) -> (\n    Any<'py>,\n    Option<Any<'py>>,\n    Option<Any<'py>>,\n    Option<Dict<'py>>,\n) {\n    (a, b, c, kwargs)\n}\n\n#[pyfunction(signature = (a, b = None, *args, c = None, **kwargs))]\nfn simple_args_kwargs<'py>(\n    a: Any<'py>,\n    b: Option<Any<'py>>,\n    args: Tuple<'py>,\n    c: Option<Any<'py>>,\n    kwargs: Option<Dict<'py>>,\n) -> (\n    Any<'py>,\n    Option<Any<'py>>,\n    Tuple<'py>,\n    Option<Any<'py>>,\n    Option<Dict<'py>>,\n) {\n    (a, b, args, c, kwargs)\n}\n\n#[pyfunction(signature = (*args, **kwargs))]\nfn args_kwargs<'py>(\n    args: Tuple<'py>,\n    kwargs: Option<Dict<'py>>,\n) -> (Tuple<'py>, Option<Dict<'py>>) {\n    (args, kwargs)\n}\n\n#[pyfunction(signature = (a, /, b))]\nfn positional_only<'py>(a: Any<'py>, b: Any<'py>) -> (Any<'py>, Any<'py>) {\n    (a, b)\n}\n\n#[pyfunction(signature = (a = false, b = 0, c = 0.0, d = \"\"))]\nfn with_typed_args(a: bool, b: u64, c: f64, d: &str) -> (bool, u64, f64, &str) {\n    (a, b, c, d)\n}\n\n#[cfg(feature = \"experimental-inspect\")]\n#[pyfunction(signature = (a: \"int\", *_args: \"str\", _b: \"int | None\" = None, **_kwargs: \"bool\") -> \"int\")]\nfn with_custom_type_annotations<'py>(\n    a: Any<'py>,\n    _args: Tuple<'py>,\n    _b: Option<Any<'py>>,\n    _kwargs: Option<Dict<'py>>,\n) -> Any<'py> {\n    a\n}\n\n#[cfg(feature = \"experimental-async\")]\n#[pyfunction]\nasync fn with_async() {}\n\n#[expect(clippy::too_many_arguments)]\n#[pyfunction(\n    signature = (\n        *,\n        ant = None,\n        bear = None,\n        cat = None,\n        dog = None,\n        elephant = None,\n        fox = None,\n        goat = None,\n        horse = None,\n        iguana = None,\n        jaguar = None,\n        koala = None,\n        lion = None,\n        monkey = None,\n        newt = None,\n        owl = None,\n        penguin = None\n    )\n)]\nfn many_keyword_arguments<'py>(\n    ant: Option<&'_ Bound<'py, PyAny>>,\n    bear: Option<&'_ Bound<'py, PyAny>>,\n    cat: Option<&'_ Bound<'py, PyAny>>,\n    dog: Option<&'_ Bound<'py, PyAny>>,\n    elephant: Option<&'_ Bound<'py, PyAny>>,\n    fox: Option<&'_ Bound<'py, PyAny>>,\n    goat: Option<&'_ Bound<'py, PyAny>>,\n    horse: Option<&'_ Bound<'py, PyAny>>,\n    iguana: Option<&'_ Bound<'py, PyAny>>,\n    jaguar: Option<&'_ Bound<'py, PyAny>>,\n    koala: Option<&'_ Bound<'py, PyAny>>,\n    lion: Option<&'_ Bound<'py, PyAny>>,\n    monkey: Option<&'_ Bound<'py, PyAny>>,\n    newt: Option<&'_ Bound<'py, PyAny>>,\n    owl: Option<&'_ Bound<'py, PyAny>>,\n    penguin: Option<&'_ Bound<'py, PyAny>>,\n) {\n    std::hint::black_box((\n        ant, bear, cat, dog, elephant, fox, goat, horse, iguana, jaguar, koala, lion, monkey, newt,\n        owl, penguin,\n    ));\n}\n\n#[pymodule]\npub mod pyfunctions {\n    #[cfg(feature = \"experimental-async\")]\n    #[pymodule_export]\n    use super::with_async;\n    #[cfg(feature = \"experimental-inspect\")]\n    #[pymodule_export]\n    use super::with_custom_type_annotations;\n    #[pymodule_export]\n    use super::{\n        args_kwargs, many_keyword_arguments, none, positional_only, simple, simple_args,\n        simple_args_kwargs, simple_kwargs, with_typed_args,\n    };\n}\n"
  },
  {
    "path": "pytests/src/sequence.rs",
    "content": "use pyo3::prelude::*;\n\n#[pymodule]\npub mod sequence {\n    use pyo3::prelude::*;\n    use pyo3::types::PyString;\n\n    #[pyfunction]\n    fn vec_to_vec_i32(vec: Vec<i32>) -> Vec<i32> {\n        vec\n    }\n\n    #[pyfunction]\n    fn array_to_array_i32(arr: [i32; 3]) -> [i32; 3] {\n        arr\n    }\n\n    #[pyfunction]\n    fn vec_to_vec_pystring(vec: Vec<Bound<'_, PyString>>) -> Vec<Bound<'_, PyString>> {\n        vec\n    }\n}\n"
  },
  {
    "path": "pytests/src/subclassing.rs",
    "content": "//! Test for [#220](https://github.com/PyO3/pyo3/issues/220)\n\nuse pyo3::prelude::*;\n\n#[pymodule(gil_used = false)]\npub mod subclassing {\n    use pyo3::prelude::*;\n    #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\n    use pyo3::types::PyDict;\n\n    #[pyclass(subclass)]\n    pub struct Subclassable {}\n\n    #[pymethods]\n    impl Subclassable {\n        #[new]\n        fn new() -> Self {\n            Subclassable {}\n        }\n\n        fn __str__(&self) -> &'static str {\n            \"Subclassable\"\n        }\n    }\n\n    #[pyclass(extends = Subclassable)]\n    pub struct Subclass {}\n\n    #[pymethods]\n    impl Subclass {\n        #[new]\n        fn new() -> (Self, Subclassable) {\n            (Subclass {}, Subclassable::new())\n        }\n\n        fn __str__(&self) -> &'static str {\n            \"Subclass\"\n        }\n    }\n\n    #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\n    #[pyclass(extends = PyDict)]\n    pub struct SubDict {}\n\n    #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\n    #[pymethods]\n    impl SubDict {\n        #[new]\n        fn new() -> Self {\n            Self {}\n        }\n\n        fn __str__(&self) -> &'static str {\n            \"SubDict\"\n        }\n    }\n}\n"
  },
  {
    "path": "pytests/stubs/__init__.pyi",
    "content": "\"\"\"\nThis is documentation for the main module of PyO3 integration tests\n\nIt provides multiple modules to do tests\n\"\"\"\n\nfrom _typeshed import Incomplete\n\ndef __getattr__(name: str) -> Incomplete: ...\n"
  },
  {
    "path": "pytests/stubs/awaitable.pyi",
    "content": "from typing import Any, final\n\n@final\nclass FutureAwaitable:\n    def __await__(self, /) -> FutureAwaitable: ...\n    def __iter__(self, /) -> FutureAwaitable: ...\n    def __new__(cls, /, result: Any) -> FutureAwaitable: ...\n    def __next__(self, /) -> FutureAwaitable: ...\n    @property\n    def _asyncio_future_blocking(self, /) -> bool: ...\n    @_asyncio_future_blocking.setter\n    def _asyncio_future_blocking(self, /, value: bool) -> None: ...\n\n@final\nclass IterAwaitable:\n    def __await__(self, /) -> IterAwaitable: ...\n    def __iter__(self, /) -> IterAwaitable: ...\n    def __new__(cls, /, result: Any) -> IterAwaitable: ...\n    def __next__(self, /) -> Any: ...\n"
  },
  {
    "path": "pytests/stubs/buf_and_str.pyi",
    "content": "\"\"\"\nObjects related to PyBuffer and PyStr\n\"\"\"\n\nfrom collections.abc import Sequence\nfrom typing import Any, final\n\n@final\nclass BytesExtractor:\n    \"\"\"\n    This is for confirming that PyBuffer does not cause memory leak\n    \"\"\"\n    def __new__(cls, /) -> BytesExtractor: ...\n    @staticmethod\n    def from_buffer(buf: Any) -> int: ...\n    @staticmethod\n    def from_bytes(bytes: bytes) -> int: ...\n    @staticmethod\n    def from_str(string: str) -> int: ...\n    @staticmethod\n    def from_str_lossy(string: str) -> int: ...\n\ndef map_byte_cow(bytes: Sequence[int]) -> bytes: ...\ndef map_byte_slice(bytes: bytes) -> bytes: ...\ndef map_byte_vec(bytes: Sequence[int]) -> bytes: ...\ndef return_memoryview() -> memoryview: ...\n"
  },
  {
    "path": "pytests/stubs/comparisons.pyi",
    "content": "from typing import final\n\n@final\nclass Eq:\n    def __eq__(self, /, other: object) -> bool: ...\n    def __ne__(self, /, other: object) -> bool: ...\n    def __new__(cls, /, value: int) -> Eq: ...\n\n@final\nclass EqDefaultNe:\n    def __eq__(self, /, other: object) -> bool: ...\n    def __new__(cls, /, value: int) -> EqDefaultNe: ...\n\n@final\nclass EqDerived:\n    def __eq__(self, /, other: object) -> bool: ...\n    def __ne__(self, /, other: object) -> bool: ...\n    def __new__(cls, /, value: int) -> EqDerived: ...\n\n@final\nclass Ordered:\n    def __eq__(self, /, other: object) -> bool: ...\n    def __ge__(self, /, other: object) -> bool: ...\n    def __gt__(self, /, other: object) -> bool: ...\n    def __le__(self, /, other: object) -> bool: ...\n    def __lt__(self, /, other: object) -> bool: ...\n    def __ne__(self, /, other: object) -> bool: ...\n    def __new__(cls, /, value: int) -> Ordered: ...\n\n@final\nclass OrderedDefaultNe:\n    def __eq__(self, /, other: object) -> bool: ...\n    def __ge__(self, /, other: object) -> bool: ...\n    def __gt__(self, /, other: object) -> bool: ...\n    def __le__(self, /, other: object) -> bool: ...\n    def __lt__(self, /, other: object) -> bool: ...\n    def __new__(cls, /, value: int) -> OrderedDefaultNe: ...\n\n@final\nclass OrderedDerived:\n    def __eq__(self, /, other: object) -> bool: ...\n    def __ge__(self, /, other: object) -> bool: ...\n    def __gt__(self, /, other: object) -> bool: ...\n    def __hash__(self, /) -> int: ...\n    def __le__(self, /, other: object) -> bool: ...\n    def __lt__(self, /, other: object) -> bool: ...\n    def __ne__(self, /, other: object) -> bool: ...\n    def __new__(cls, /, value: int) -> OrderedDerived: ...\n    def __str__(self, /) -> str: ...\n\n@final\nclass OrderedRichCmp:\n    def __eq__(self, /, other: object) -> bool: ...\n    def __ge__(self, /, other: object) -> bool: ...\n    def __gt__(self, /, other: object) -> bool: ...\n    def __le__(self, /, other: object) -> bool: ...\n    def __lt__(self, /, other: object) -> bool: ...\n    def __ne__(self, /, other: object) -> bool: ...\n    def __new__(cls, /, value: int) -> OrderedRichCmp: ...\n"
  },
  {
    "path": "pytests/stubs/consts.pyi",
    "content": "from typing import Final, final\n\nESCAPING: Final = \"S\\0\\x01\\t\\n\\r\\\"'\\\\\"\n\"\"\"\nWe experiment with \"escaping\"\n\"\"\"\n\nPI: Final[float]\n\"\"\"\nExports PI constant as part of the module\n\"\"\"\n\n@final\nclass ClassWithConst:\n    INSTANCE: Final[ClassWithConst]\n    \"\"\"\n    A constant\n    \"\"\"\n"
  },
  {
    "path": "pytests/stubs/datetime.pyi",
    "content": "from datetime import date, datetime, time, timedelta, tzinfo\nfrom typing import final\n\n@final\nclass TzClass(tzinfo):\n    def __new__(cls, /) -> TzClass: ...\n    def dst(self, _dt: datetime | None, /) -> timedelta | None: ...\n    def tzname(self, _dt: datetime | None, /) -> str: ...\n    def utcoffset(self, _dt: datetime | None, /) -> timedelta: ...\n\ndef date_from_timestamp(timestamp: float) -> date: ...\ndef datetime_from_timestamp(ts: float, tz: tzinfo | None = None) -> datetime: ...\ndef get_date_tuple(d: date) -> tuple: ...\ndef get_datetime_tuple(dt: datetime) -> tuple: ...\ndef get_datetime_tuple_fold(dt: datetime) -> tuple: ...\ndef get_datetime_tzinfo(dt: datetime) -> tzinfo | None: ...\ndef get_delta_tuple(delta: timedelta) -> tuple: ...\ndef get_time_tuple(dt: time) -> tuple: ...\ndef get_time_tuple_fold(dt: time) -> tuple: ...\ndef get_time_tzinfo(dt: time) -> tzinfo | None: ...\ndef make_date(year: int, month: int, day: int) -> date: ...\ndef make_datetime(\n    year: int,\n    month: int,\n    day: int,\n    hour: int,\n    minute: int,\n    second: int,\n    microsecond: int,\n    tzinfo: tzinfo | None = None,\n) -> datetime: ...\ndef make_delta(days: int, seconds: int, microseconds: int) -> timedelta: ...\ndef make_time(\n    hour: int, minute: int, second: int, microsecond: int, tzinfo: tzinfo | None = None\n) -> time: ...\ndef time_with_fold(\n    hour: int,\n    minute: int,\n    second: int,\n    microsecond: int,\n    tzinfo: tzinfo | None,\n    fold: bool,\n) -> time: ...\n"
  },
  {
    "path": "pytests/stubs/dict_iter.pyi",
    "content": "from typing import final\n\n@final\nclass DictSize:\n    def __new__(cls, /, expected: int) -> DictSize: ...\n    def iter_dict(self, /, dict: dict) -> int: ...\n"
  },
  {
    "path": "pytests/stubs/enums.pyi",
    "content": "from typing import Any, Final, final\n\nclass ComplexEnum:\n    @final\n    class EmptyStruct(ComplexEnum):\n        __match_args__: Final = ()\n        def __new__(cls, /) -> ComplexEnum.EmptyStruct: ...\n\n    @final\n    class Float(ComplexEnum):\n        __match_args__: Final = (\"f\",)\n        def __new__(cls, /, f: float) -> ComplexEnum.Float: ...\n        @property\n        def f(self, /) -> float: ...\n\n    @final\n    class Int(ComplexEnum):\n        \"\"\"\n        A struct variant\n        \"\"\"\n\n        __match_args__: Final = (\"i\",)\n        def __new__(cls, /, i: int) -> ComplexEnum.Int: ...\n        @property\n        def i(self, /) -> int:\n            \"\"\"\n            An integer\n            \"\"\"\n\n    @final\n    class MultiFieldStruct(ComplexEnum):\n        __match_args__: Final = (\"a\", \"b\", \"c\")\n        def __new__(\n            cls, /, a: int, b: float, c: bool\n        ) -> ComplexEnum.MultiFieldStruct: ...\n        @property\n        def a(self, /) -> int: ...\n        @property\n        def b(self, /) -> float: ...\n        @property\n        def c(self, /) -> bool: ...\n\n    @final\n    class Str(ComplexEnum):\n        __match_args__: Final = (\"s\",)\n        def __new__(cls, /, s: str) -> ComplexEnum.Str: ...\n        @property\n        def s(self, /) -> str: ...\n\n    @final\n    class VariantWithDefault(ComplexEnum):\n        __match_args__: Final = (\"a\", \"b\")\n        def __new__(\n            cls, /, a: int = 42, b: str | None = None\n        ) -> ComplexEnum.VariantWithDefault: ...\n        @property\n        def a(self, /) -> int: ...\n        @property\n        def b(self, /) -> str | None: ...\n\nclass MixedComplexEnum:\n    @final\n    class Empty(MixedComplexEnum):\n        __match_args__: Final = ()\n        def __getitem__(self, /, key: int) -> Any: ...\n        def __len__(self, /) -> int: ...\n        def __new__(cls, /) -> MixedComplexEnum.Empty: ...\n\n    @final\n    class Nothing(MixedComplexEnum):\n        __match_args__: Final = ()\n        def __new__(cls, /) -> MixedComplexEnum.Nothing: ...\n\n@final\nclass SimpleEnum:\n    Friday: Final[SimpleEnum]\n    Monday: Final[SimpleEnum]\n    Saturday: Final[SimpleEnum]\n    Sunday: Final[SimpleEnum]\n    \"\"\"\n    A variant\n    \"\"\"\n    Thursday: Final[SimpleEnum]\n    Tuesday: Final[SimpleEnum]\n    Wednesday: Final[SimpleEnum]\n    def __eq__(self, /, other: object) -> bool: ...\n    def __int__(self, /) -> int: ...\n    def __ne__(self, /, other: object) -> bool: ...\n    def __repr__(self, /) -> str: ...\n\n@final\nclass SimpleEnumWithoutDerive:\n    A: Final[SimpleEnumWithoutDerive]\n    B: Final[SimpleEnumWithoutDerive]\n    def __int__(self, /) -> int: ...\n    def __repr__(self, /) -> str: ...\n\nclass SimpleTupleEnum:\n    @final\n    class Int(SimpleTupleEnum):\n        __match_args__: Final = (\"_0\",)\n        @property\n        def _0(self, /) -> int: ...\n        def __getitem__(self, /, key: int) -> Any: ...\n        def __len__(self, /) -> int: ...\n        def __new__(cls, /, _0: int) -> SimpleTupleEnum.Int: ...\n\n    @final\n    class Str(SimpleTupleEnum):\n        __match_args__: Final = (\"_0\",)\n        @property\n        def _0(self, /) -> str: ...\n        def __getitem__(self, /, key: int) -> Any: ...\n        def __len__(self, /) -> int: ...\n        def __new__(cls, /, _0: str) -> SimpleTupleEnum.Str: ...\n\nclass TupleEnum:\n    @final\n    class EmptyTuple(TupleEnum):\n        __match_args__: Final = ()\n        def __getitem__(self, /, key: int) -> Any: ...\n        def __len__(self, /) -> int: ...\n        def __new__(cls, /) -> TupleEnum.EmptyTuple: ...\n\n    @final\n    class Full(TupleEnum):\n        __match_args__: Final = (\"_0\", \"_1\", \"_2\")\n        @property\n        def _0(self, /) -> int: ...\n        @property\n        def _1(self, /) -> float: ...\n        @property\n        def _2(self, /) -> bool: ...\n        def __getitem__(self, /, key: int) -> Any: ...\n        def __len__(self, /) -> int: ...\n        def __new__(cls, /, _0: int, _1: float, _2: bool) -> TupleEnum.Full: ...\n\n    @final\n    class FullWithDefault(TupleEnum):\n        \"\"\"\n        A tuple variant\n        \"\"\"\n\n        __match_args__: Final = (\"_0\", \"_1\", \"_2\")\n        @property\n        def _0(self, /) -> int: ...\n        @property\n        def _1(self, /) -> float: ...\n        @property\n        def _2(self, /) -> bool: ...\n        def __getitem__(self, /, key: int) -> Any: ...\n        def __len__(self, /) -> int: ...\n        def __new__(\n            cls, /, _0: int = 1, _1: float = 1.0, _2: bool = True\n        ) -> TupleEnum.FullWithDefault: ...\n\ndef do_complex_stuff(thing: ComplexEnum) -> ComplexEnum: ...\ndef do_mixed_complex_stuff(thing: MixedComplexEnum) -> MixedComplexEnum: ...\ndef do_simple_stuff(thing: SimpleEnum) -> SimpleEnum: ...\ndef do_tuple_stuff(thing: TupleEnum) -> TupleEnum: ...\n"
  },
  {
    "path": "pytests/stubs/exception.pyi",
    "content": "from _typeshed import Incomplete\nfrom typing import Any\n\ndef raise_my_value_error() -> None: ...\ndef return_my_value_error() -> Any: ...\ndef return_pyerr() -> BaseException: ...\ndef return_value_error() -> ValueError: ...\ndef __getattr__(name: str) -> Incomplete: ...\n"
  },
  {
    "path": "pytests/stubs/misc.pyi",
    "content": "from typing import Any\n\ndef accepts_bool(val: bool) -> bool: ...\ndef get_item_and_run_callback(dict: dict, callback: Any) -> None: ...\ndef get_type_fully_qualified_name(obj: Any) -> str: ...\ndef hammer_attaching_in_thread() -> Any: ...\ndef issue_219() -> None: ...\n"
  },
  {
    "path": "pytests/stubs/objstore.pyi",
    "content": "from typing import Any, final\n\n@final\nclass ObjStore:\n    def __new__(cls, /) -> ObjStore: ...\n    def push(self, /, obj: Any) -> None: ...\n"
  },
  {
    "path": "pytests/stubs/othermod.pyi",
    "content": "from typing import Final, final\n\nUSIZE_MAX: Final[int]\nUSIZE_MIN: Final[int]\n\n@final\nclass ModClass:\n    def __new__(cls, /) -> ModClass: ...\n    def noop(self, /, x: int) -> int: ...\n\ndef double(x: int) -> int: ...\n"
  },
  {
    "path": "pytests/stubs/path.pyi",
    "content": "from os import PathLike\nfrom pathlib import Path\n\ndef make_path() -> Path: ...\ndef take_pathbuf(path: str | PathLike[str]) -> Path: ...\n"
  },
  {
    "path": "pytests/stubs/pyclasses.pyi",
    "content": "from _typeshed import Incomplete\nfrom typing import Final, final\n\nclass AssertingBaseClass:\n    \"\"\"\n    Demonstrates a base class which can operate on the relevant subclass in its constructor.\n    \"\"\"\n    def __new__(cls, /, expected_type: type) -> AssertingBaseClass: ...\n\n@final\nclass ClassWithDecorators:\n    cls_attribute: Final[int]\n    \"\"\"\n    A class attribute\n    \"\"\"\n    def __new__(cls, /) -> ClassWithDecorators: ...\n    @property\n    def attr(self, /) -> int:\n        \"\"\"\n        A getter\n        \"\"\"\n    @attr.deleter\n    def attr(self, /) -> None:\n        \"\"\"\n        A deleter\n        \"\"\"\n    @attr.setter\n    def attr(self, /, value: int) -> None:\n        \"\"\"\n        A setter\n        \"\"\"\n    @classmethod\n    def cls_method(cls, /) -> int:\n        \"\"\"\n        A class method\n        \"\"\"\n    @staticmethod\n    def static_method() -> int:\n        \"\"\"\n        A static method\n        \"\"\"\n\n@final\nclass ClassWithDict:\n    def __new__(cls, /) -> ClassWithDict: ...\n\n@final\nclass ClassWithoutConstructor: ...\n\n@final\nclass EmptyClass:\n    def __len__(self, /) -> int: ...\n    def __new__(cls, /) -> EmptyClass: ...\n    def method(self, /) -> None: ...\n\n@final\nclass Number:\n    def __abs__(self, /) -> Number: ...\n    def __add__(self, /, other: object) -> Number: ...\n    def __and__(self, /, other: object) -> Number: ...\n    def __complex__(self, /) -> complex: ...\n    def __divmod__(self, /, other: object) -> tuple[Number, Number]: ...\n    def __eq__(self, /, other: object) -> bool: ...\n    def __float__(self, /) -> float: ...\n    def __floordiv__(self, /, other: object) -> Number: ...\n    def __ge__(self, /, other: object) -> bool: ...\n    def __gt__(self, /, other: object) -> bool: ...\n    def __hash__(self, /) -> int: ...\n    def __int__(self, /) -> int: ...\n    def __invert__(self, /) -> Number: ...\n    def __le__(self, /, other: object) -> bool: ...\n    def __lshift__(self, /, other: object) -> Number: ...\n    def __lt__(self, /, other: object) -> bool: ...\n    def __matmul__(self, /, other: object) -> Number: ...\n    def __mod__(self, /, other: object) -> Number: ...\n    def __mul__(self, /, other: object) -> Number: ...\n    def __ne__(self, /, other: object) -> bool: ...\n    def __neg__(self, /) -> Number: ...\n    def __new__(cls, /, value: int) -> Number: ...\n    def __or__(self, /, other: object) -> Number: ...\n    def __pos__(self, /) -> Number: ...\n    def __pow__(self, /, other: object, modulo: object) -> Number: ...\n    def __repr__(self, /) -> str: ...\n    def __rshift__(self, /, other: object) -> Number: ...\n    def __str__(self, /) -> str: ...\n    def __sub__(self, /, other: object) -> Number: ...\n    def __truediv__(self, /, other: object) -> Number: ...\n    def __xor__(self, /, other: object) -> Number: ...\n\n@final\nclass PlainObject:\n    @property\n    def bar(self, /) -> int:\n        \"\"\"\n        Bar\n        \"\"\"\n    @bar.setter\n    def bar(self, /, value: int) -> None:\n        \"\"\"\n        Bar\n        \"\"\"\n    @property\n    def foo(self, /) -> str:\n        \"\"\"\n        Foo\n        \"\"\"\n    @foo.setter\n    def foo(self, /, value: str) -> None:\n        \"\"\"\n        Foo\n        \"\"\"\n\n@final\nclass PyClassIter:\n    \"\"\"\n    This is for demonstrating how to return a value from __next__\n    \"\"\"\n    def __new__(cls, /) -> PyClassIter:\n        \"\"\"\n        A constructor\n        \"\"\"\n    def __next__(self, /) -> int: ...\n\n@final\nclass PyClassThreadIter:\n    def __new__(cls, /) -> PyClassThreadIter: ...\n    def __next__(self, /) -> int: ...\n\n@final\nclass SubClassWithInit(dict):\n    def __init__(self, /, *args, **kwargs) -> None: ...\n    def __new__(cls, /, *args, **kwargs) -> SubClassWithInit: ...\n\ndef map_a_class(\n    cls: EmptyClass | tuple[EmptyClass, EmptyClass] | Incomplete,\n) -> EmptyClass | tuple[EmptyClass, EmptyClass] | Incomplete: ...\n"
  },
  {
    "path": "pytests/stubs/pyfunctions.pyi",
    "content": "from typing import Any\n\ndef args_kwargs(*args, **kwargs) -> tuple[tuple, dict | None]: ...\ndef many_keyword_arguments(\n    *,\n    ant: Any | None = None,\n    bear: Any | None = None,\n    cat: Any | None = None,\n    dog: Any | None = None,\n    elephant: Any | None = None,\n    fox: Any | None = None,\n    goat: Any | None = None,\n    horse: Any | None = None,\n    iguana: Any | None = None,\n    jaguar: Any | None = None,\n    koala: Any | None = None,\n    lion: Any | None = None,\n    monkey: Any | None = None,\n    newt: Any | None = None,\n    owl: Any | None = None,\n    penguin: Any | None = None,\n) -> None: ...\ndef none() -> None: ...\ndef positional_only(a: Any, /, b: Any) -> tuple[Any, Any]: ...\ndef simple(\n    a: Any, b: Any | None = None, *, c: Any | None = None\n) -> tuple[Any, Any | None, Any | None]: ...\ndef simple_args(\n    a: Any, b: Any | None = None, *args, c: Any | None = None\n) -> tuple[Any, Any | None, tuple, Any | None]: ...\ndef simple_args_kwargs(\n    a: Any, b: Any | None = None, *args, c: Any | None = None, **kwargs\n) -> tuple[Any, Any | None, tuple, Any | None, dict | None]: ...\ndef simple_kwargs(\n    a: Any, b: Any | None = None, c: Any | None = None, **kwargs\n) -> tuple[Any, Any | None, Any | None, dict | None]: ...\nasync def with_async() -> None: ...\ndef with_custom_type_annotations(\n    a: \"int\", *_args: \"str\", _b: \"int | None\" = None, **_kwargs: \"bool\"\n) -> \"int\": ...\ndef with_typed_args(\n    a: bool = False, b: int = 0, c: float = 0.0, d: str = \"\"\n) -> tuple[bool, int, float, str]: ...\n"
  },
  {
    "path": "pytests/stubs/sequence.pyi",
    "content": "from collections.abc import Sequence\n\ndef array_to_array_i32(arr: Sequence[int]) -> list[int]: ...\ndef vec_to_vec_i32(vec: Sequence[int]) -> list[int]: ...\ndef vec_to_vec_pystring(vec: Sequence[str]) -> list[str]: ...\n"
  },
  {
    "path": "pytests/stubs/subclassing.pyi",
    "content": "from typing import final\n\n@final\nclass SubDict(dict):\n    def __new__(cls, /) -> SubDict: ...\n    def __str__(self, /) -> str: ...\n\n@final\nclass Subclass(Subclassable):\n    def __new__(cls, /) -> Subclass: ...\n    def __str__(self, /) -> str: ...\n\nclass Subclassable:\n    def __new__(cls, /) -> Subclassable: ...\n    def __str__(self, /) -> str: ...\n"
  },
  {
    "path": "pytests/tests/test_awaitable.py",
    "content": "import pytest\nimport sys\n\nfrom pyo3_pytests.awaitable import IterAwaitable, FutureAwaitable\n\n\n@pytest.mark.skipif(\n    sys.implementation.name == \"graalpy\",\n    reason=\"GraalPy's asyncio module has a bug with native classes, see oracle/graalpython#365\",\n)\n@pytest.mark.asyncio\nasync def test_iter_awaitable():\n    assert await IterAwaitable(5) == 5\n\n\n@pytest.mark.skipif(\n    sys.implementation.name == \"graalpy\",\n    reason=\"GraalPy's asyncio module has a bug with native classes, see oracle/graalpython#365\",\n)\n@pytest.mark.asyncio\nasync def test_future_awaitable():\n    assert await FutureAwaitable(5) == 5\n"
  },
  {
    "path": "pytests/tests/test_buf_and_str.py",
    "content": "from pyo3_pytests.buf_and_str import BytesExtractor, return_memoryview\n\n\ndef test_extract_bytes():\n    extractor = BytesExtractor()\n    message = b'\\\\(-\"-;) A message written in bytes'\n    assert extractor.from_bytes(message) == len(message)\n\n\ndef test_extract_str():\n    extractor = BytesExtractor()\n    message = '\\\\(-\"-;) A message written as a string'\n    assert extractor.from_str(message) == len(message)\n\n\ndef test_extract_str_lossy():\n    extractor = BytesExtractor()\n    message = '\\\\(-\"-;) A message written with a trailing surrogate \\ud800'\n    rust_surrogate_len = extractor.from_str_lossy(\"\\ud800\")\n    assert extractor.from_str_lossy(message) == len(message) - 1 + rust_surrogate_len\n\n\ndef test_extract_buffer():\n    extractor = BytesExtractor()\n    message = b'\\\\(-\"-;) A message written in bytes'\n    assert extractor.from_buffer(message) == len(message)\n\n    arr = bytearray(b'\\\\(-\"-;) A message written in bytes')\n    assert extractor.from_buffer(arr) == len(arr)\n\n\ndef test_return_memoryview():\n    view = return_memoryview()\n    assert view.readonly\n    assert view.contiguous\n    assert view.tobytes() == b\"hello world\"\n"
  },
  {
    "path": "pytests/tests/test_comparisons.py",
    "content": "from typing import Type, TypeVar\n\nimport sys\nimport pytest\nfrom pyo3_pytests.comparisons import (\n    Eq,\n    EqDefaultNe,\n    EqDerived,\n    Ordered,\n    OrderedDefaultNe,\n    OrderedDerived,\n    OrderedRichCmp,\n)\nfrom typing_extensions import Self\n\n\nclass PyEq:\n    def __init__(self, x: int) -> None:\n        self.x = x\n\n    def __eq__(self, other: object) -> bool:\n        if isinstance(other, self.__class__):\n            return self.x == other.x\n        else:\n            return NotImplemented\n\n    def __ne__(self, other: object) -> bool:\n        if isinstance(other, self.__class__):\n            return self.x != other.x\n        else:\n            return NotImplemented\n\n\nEqType = TypeVar(\"EqType\", Eq, EqDerived, PyEq)\n\n\n@pytest.mark.skipif(\n    sys.implementation.name == \"graalpy\"\n    and __graalpython__.get_graalvm_version().startswith(\"24.1\"),  # type: ignore[name-defined] # noqa: F821\n    reason=\"Bug in GraalPy 24.1\",\n)\n@pytest.mark.parametrize(\n    \"ty\", (Eq, EqDerived, PyEq), ids=(\"rust\", \"rust-derived\", \"python\")\n)\ndef test_eq(ty: Type[EqType]):\n    a = ty(0)\n    b = ty(0)\n    c = ty(1)\n\n    assert a == b\n    assert not (a != b)\n    assert a != c\n    assert not (a == c)\n\n    assert b == a\n    assert not (a != b)\n    assert b != c\n    assert not (b == c)\n\n    assert not a == 0\n    assert a != 0\n    assert not b == 0\n    assert b != 1\n    assert not c == 1\n    assert c != 1\n\n    with pytest.raises(TypeError):\n        assert a <= b  # type: ignore[operator]\n\n    with pytest.raises(TypeError):\n        assert a >= b  # type: ignore[operator]\n\n    with pytest.raises(TypeError):\n        assert a < c  # type: ignore[operator]\n\n    with pytest.raises(TypeError):\n        assert c > a  # type: ignore[operator]\n\n\nclass PyEqDefaultNe:\n    def __init__(self, x: int) -> None:\n        self.x = x\n\n    def __eq__(self, other: object) -> bool:\n        return isinstance(other, self.__class__) and self.x == other.x\n\n\nEqDefaultType = TypeVar(\"EqDefaultType\", EqDefaultNe, PyEqDefaultNe)\n\n\n@pytest.mark.parametrize(\"ty\", (EqDefaultNe, PyEqDefaultNe), ids=(\"rust\", \"python\"))\ndef test_eq_default_ne(ty: Type[EqDefaultType]):\n    a = ty(0)\n    b = ty(0)\n    c = ty(1)\n\n    assert a == b\n    assert not (a != b)\n    assert a != c\n    assert not (a == c)\n\n    assert b == a\n    assert not (a != b)\n    assert b != c\n    assert not (b == c)\n\n    with pytest.raises(TypeError):\n        assert a <= b  # type: ignore[operator]\n\n    with pytest.raises(TypeError):\n        assert a >= b  # type: ignore[operator]\n\n    with pytest.raises(TypeError):\n        assert a < c  # type: ignore[operator]\n\n    with pytest.raises(TypeError):\n        assert c > a  # type: ignore[operator]\n\n\nclass PyOrdered:\n    def __init__(self, x: int) -> None:\n        self.x = x\n\n    def __lt__(self, other: Self) -> bool:\n        return self.x < other.x\n\n    def __le__(self, other: Self) -> bool:\n        return self.x <= other.x\n\n    def __eq__(self, other: object) -> bool:\n        if not isinstance(other, self.__class__):\n            return NotImplemented\n        return self.x == other.x\n\n    def __ne__(self, other: object) -> bool:\n        if not isinstance(other, self.__class__):\n            return NotImplemented\n        return self.x != other.x\n\n    def __gt__(self, other: Self) -> bool:\n        return self.x >= other.x\n\n    def __ge__(self, other: Self) -> bool:\n        return self.x >= other.x\n\n\nOrderedType = TypeVar(\"OrderedType\", Ordered, OrderedDerived, OrderedRichCmp, PyOrdered)\n\n\n@pytest.mark.parametrize(\n    \"ty\",\n    (Ordered, OrderedDerived, OrderedRichCmp, PyOrdered),\n    ids=(\"rust\", \"rust-derived\", \"rust-richcmp\", \"python\"),\n)\ndef test_ordered(ty: Type[OrderedType]):\n    a = ty(0)\n    b = ty(0)\n    c = ty(1)\n\n    assert a == b\n    assert a <= b\n    assert a >= b\n    assert a != c\n    assert a <= c\n\n    assert b == a\n    assert b <= a\n    assert b >= a\n    assert b != c\n    assert b <= c\n\n    assert c != a\n    assert c != b\n    assert c > a\n    assert c >= a\n    assert c > b\n    assert c >= b\n\n\nclass PyOrderedDefaultNe:\n    def __init__(self, x: int) -> None:\n        self.x = x\n\n    def __lt__(self, other: Self) -> bool:\n        return self.x < other.x\n\n    def __le__(self, other: Self) -> bool:\n        return self.x <= other.x\n\n    def __eq__(self, other: object) -> bool:\n        if not isinstance(other, self.__class__):\n            return NotImplemented\n        return self.x == other.x\n\n    def __gt__(self, other: Self) -> bool:\n        return self.x >= other.x\n\n    def __ge__(self, other: Self) -> bool:\n        return self.x >= other.x\n\n\nOrderedDefaultType = TypeVar(\"OrderedDefaultType\", OrderedDefaultNe, PyOrderedDefaultNe)\n\n\n@pytest.mark.parametrize(\n    \"ty\", (OrderedDefaultNe, PyOrderedDefaultNe), ids=(\"rust\", \"python\")\n)\ndef test_ordered_default_ne(ty: Type[OrderedDefaultType]):\n    a = ty(0)\n    b = ty(0)\n    c = ty(1)\n\n    assert a == b\n    assert not (a != b)\n    assert a <= b\n    assert a >= b\n    assert a != c\n    assert not (a == c)\n    assert a <= c\n\n    assert b == a\n    assert not (b != a)\n    assert b <= a\n    assert b >= a\n    assert b != c\n    assert not (b == c)\n    assert b <= c\n\n    assert c != a\n    assert not (c == a)\n    assert c != b\n    assert not (c == b)\n    assert c > a\n    assert c >= a\n    assert c > b\n    assert c >= b\n"
  },
  {
    "path": "pytests/tests/test_datetime.py",
    "content": "import datetime as pdt\nimport platform\nimport re\nimport struct\nimport sys\n\nimport pyo3_pytests.datetime as rdt\nimport pytest\nfrom hypothesis import example, given\nfrom hypothesis import strategies as st\n\n\n# Constants\ndef _get_utc():\n    timezone = getattr(pdt, \"timezone\", None)\n    if timezone:\n        return timezone.utc\n    else:\n\n        class UTC(pdt.tzinfo):\n            def utcoffset(self, dt):\n                return pdt.timedelta(0)\n\n            def dst(self, dt):\n                return pdt.timedelta(0)\n\n            def tzname(self, dt):\n                return \"UTC\"\n\n        return UTC()\n\n\nUTC = _get_utc()\n\nMAX_SECONDS = int(pdt.timedelta.max.total_seconds())\nMIN_SECONDS = int(pdt.timedelta.min.total_seconds())\n\nMAX_DAYS = pdt.timedelta.max // pdt.timedelta(days=1)\nMIN_DAYS = pdt.timedelta.min // pdt.timedelta(days=1)\n\nMAX_MICROSECONDS = int(pdt.timedelta.max.total_seconds() * 1e6)\nMIN_MICROSECONDS = int(pdt.timedelta.min.total_seconds() * 1e6)\n\n# The reason we don't use platform.architecture() here is that it's not\n# reliable on macOS. See https://stackoverflow.com/a/1405971/823869. Similarly,\n# sys.maxsize is not reliable on Windows. See\n# https://stackoverflow.com/questions/1405913/how-do-i-determine-if-my-python-shell-is-executing-in-32bit-or-64bit-mode-on-os/1405971#comment6209952_1405971\n# and https://stackoverflow.com/a/3411134/823869.\n_pointer_size = struct.calcsize(\"P\")\nif _pointer_size == 8:\n    IS_32_BIT = False\nelif _pointer_size == 4:\n    IS_32_BIT = True\nelse:\n    raise RuntimeError(\"unexpected pointer size: \" + repr(_pointer_size))\nIS_WINDOWS = sys.platform == \"win32\"\n\nif IS_WINDOWS:\n    MIN_DATETIME = pdt.datetime(1970, 1, 1, 0, 0, 0)\n    if IS_32_BIT:\n        MAX_DATETIME = pdt.datetime(2038, 1, 18, 23, 59, 59)\n    else:\n        MAX_DATETIME = pdt.datetime(3000, 12, 31, 23, 59, 59)\nelse:\n    if IS_32_BIT:\n        # TS ±2147483648 (2**31)\n        MIN_DATETIME = pdt.datetime(1901, 12, 13, 20, 45, 52)\n        MAX_DATETIME = pdt.datetime(2038, 1, 19, 3, 14, 8)\n    else:\n        MIN_DATETIME = pdt.datetime(1, 1, 2, 0, 0)\n        MAX_DATETIME = pdt.datetime(9999, 12, 31, 18, 59, 59)\n\nPYPY = platform.python_implementation() == \"PyPy\"\n\n\n# Tests\ndef test_date():\n    assert rdt.make_date(2017, 9, 1) == pdt.date(2017, 9, 1)\n\n\n@given(d=st.dates())\ndef test_date_accessors(d):\n    act = rdt.get_date_tuple(d)\n    exp = (d.year, d.month, d.day)\n\n    assert act == exp\n\n\ndef test_invalid_date_fails():\n    with pytest.raises(ValueError):\n        rdt.make_date(2017, 2, 30)\n\n\n@given(d=st.dates(MIN_DATETIME.date(), MAX_DATETIME.date()))\ndef test_date_from_timestamp(d):\n    try:\n        ts = pdt.datetime.timestamp(d)\n    except Exception:\n        # out of range for timestamp\n        return\n\n    try:\n        expected = pdt.date.fromtimestamp(ts)\n    except Exception as pdt_fail:\n        # date from timestamp failed; expect the same from Rust binding\n        with pytest.raises(type(pdt_fail)) as exc_info:\n            rdt.date_from_timestamp(ts)\n        assert str(exc_info.value) == str(pdt_fail)\n    else:\n        assert rdt.date_from_timestamp(int(ts)) == expected\n\n\n@pytest.mark.parametrize(\n    \"args, kwargs\",\n    [\n        ((0, 0, 0, 0, None), {}),\n        ((1, 12, 14, 124731), {}),\n        ((1, 12, 14, 124731), {\"tzinfo\": UTC}),\n    ],\n)\ndef test_time(args, kwargs):\n    act = rdt.make_time(*args, **kwargs)\n    exp = pdt.time(*args, **kwargs)\n\n    assert act == exp\n    assert act.tzinfo is exp.tzinfo\n    assert rdt.get_time_tzinfo(act) == exp.tzinfo\n\n\n@given(t=st.times())\ndef test_time_hypothesis(t):\n    act = rdt.get_time_tuple(t)\n    exp = (t.hour, t.minute, t.second, t.microsecond)\n\n    assert act == exp\n\n\n@given(t=st.times())\ndef test_time_tuple_fold(t):\n    t_nofold = t.replace(fold=0)\n    t_fold = t.replace(fold=1)\n\n    for t in (t_nofold, t_fold):\n        act = rdt.get_time_tuple_fold(t)\n        exp = (t.hour, t.minute, t.second, t.microsecond, t.fold)\n\n        assert act == exp\n\n\n@pytest.mark.parametrize(\"fold\", [False, True])\ndef test_time_with_fold(fold):\n    t = rdt.time_with_fold(0, 0, 0, 0, None, fold)\n    assert t.fold == fold\n\n\n@pytest.mark.parametrize(\n    \"args\", [(-1, 0, 0, 0), (0, -1, 0, 0), (0, 0, -1, 0), (0, 0, 0, -1)]\n)\ndef test_invalid_time_fails_overflow(args):\n    with pytest.raises(OverflowError):\n        rdt.make_time(*args)\n\n\n@pytest.mark.parametrize(\n    \"args\",\n    [\n        (24, 0, 0, 0),\n        (25, 0, 0, 0),\n        (0, 60, 0, 0),\n        (0, 61, 0, 0),\n        (0, 0, 60, 0),\n        (0, 0, 61, 0),\n        (0, 0, 0, 1000000),\n    ],\n)\ndef test_invalid_time_fails(args):\n    with pytest.raises(ValueError):\n        rdt.make_time(*args)\n\n\n@pytest.mark.parametrize(\n    \"args\",\n    [\n        (\"0\", 0, 0, 0),\n        (0, \"0\", 0, 0),\n        (0, 0, \"0\", 0),\n        (0, 0, 0, \"0\"),\n        (0, 0, 0, 0, \"UTC\"),\n    ],\n)\ndef test_time_typeerror(args):\n    with pytest.raises(TypeError):\n        rdt.make_time(*args)\n\n\n@pytest.mark.parametrize(\n    \"args, kwargs\",\n    [((2017, 9, 1, 12, 45, 30, 0), {}), ((2017, 9, 1, 12, 45, 30, 0), {\"tzinfo\": UTC})],\n)\ndef test_datetime(args, kwargs):\n    act = rdt.make_datetime(*args, **kwargs)\n    exp = pdt.datetime(*args, **kwargs)\n\n    assert act == exp\n    assert act.tzinfo is exp.tzinfo\n    assert rdt.get_datetime_tzinfo(act) == exp.tzinfo\n\n\n@given(dt=st.datetimes())\ndef test_datetime_tuple(dt):\n    act = rdt.get_datetime_tuple(dt)\n    exp = dt.timetuple()[0:6] + (dt.microsecond,)\n\n    assert act == exp\n\n\n@given(dt=st.datetimes())\ndef test_datetime_tuple_fold(dt):\n    dt_fold = dt.replace(fold=1)\n    dt_nofold = dt.replace(fold=0)\n\n    for dt in (dt_fold, dt_nofold):\n        act = rdt.get_datetime_tuple_fold(dt)\n        exp = dt.timetuple()[0:6] + (dt.microsecond, dt.fold)\n\n        assert act == exp\n\n\ndef test_invalid_datetime_fails():\n    with pytest.raises(ValueError):\n        rdt.make_datetime(2011, 1, 42, 0, 0, 0, 0)\n\n\ndef test_datetime_typeerror():\n    with pytest.raises(TypeError):\n        rdt.make_datetime(\"2011\", 1, 1, 0, 0, 0, 0)\n\n\n@given(dt=st.datetimes(MIN_DATETIME, MAX_DATETIME))\n@example(dt=pdt.datetime(1971, 1, 2, 0, 0))\ndef test_datetime_from_timestamp(dt):\n    try:\n        ts = pdt.datetime.timestamp(dt)\n    except Exception:\n        # out of range for timestamp\n        return\n\n    try:\n        expected = pdt.datetime.fromtimestamp(ts)\n    except Exception as pdt_fail:\n        # datetime from timestamp failed; expect the same from Rust binding\n        with pytest.raises(type(pdt_fail)) as exc_info:\n            rdt.datetime_from_timestamp(ts)\n        assert str(exc_info.value) == str(pdt_fail)\n    else:\n        assert rdt.datetime_from_timestamp(ts) == expected\n\n\ndef test_datetime_from_timestamp_tzinfo():\n    d1 = rdt.datetime_from_timestamp(0, tz=UTC)\n    d2 = rdt.datetime_from_timestamp(0, tz=UTC)\n\n    assert d1 == d2\n    assert d1.tzinfo is d2.tzinfo\n\n\n@pytest.mark.parametrize(\n    \"args\",\n    [\n        (0, 0, 0),\n        (1, 0, 0),\n        (-1, 0, 0),\n        (0, 1, 0),\n        (0, -1, 0),\n        (1, -1, 0),\n        (-1, 1, 0),\n        (0, 0, 123456),\n        (0, 0, -123456),\n    ],\n)\ndef test_delta(args):\n    act = pdt.timedelta(*args)\n    exp = rdt.make_delta(*args)\n\n    assert act == exp\n\n\n@given(td=st.timedeltas())\ndef test_delta_accessors(td):\n    act = rdt.get_delta_tuple(td)\n    exp = (td.days, td.seconds, td.microseconds)\n\n    assert act == exp\n\n\n@pytest.mark.parametrize(\n    \"args,err_type\",\n    [\n        ((MAX_DAYS + 1, 0, 0), OverflowError),\n        ((MIN_DAYS - 1, 0, 0), OverflowError),\n        ((0, MAX_SECONDS + 1, 0), OverflowError),\n        ((0, MIN_SECONDS - 1, 0), OverflowError),\n        ((0, 0, MAX_MICROSECONDS + 1), OverflowError),\n        ((0, 0, MIN_MICROSECONDS - 1), OverflowError),\n        ((\"0\", 0, 0), TypeError),\n        ((0, \"0\", 0), TypeError),\n        ((0, 0, \"0\"), TypeError),\n    ],\n)\ndef test_delta_err(args, err_type):\n    with pytest.raises(err_type):\n        rdt.make_delta(*args)\n\n\ndef test_tz_class():\n    tzi = rdt.TzClass()\n\n    dt = pdt.datetime(2018, 1, 1, tzinfo=tzi)\n\n    assert dt.tzname() == \"+01:00\"\n    assert dt.utcoffset() == pdt.timedelta(hours=1)\n    assert dt.dst() is None\n\n\ndef test_tz_class_introspection():\n    tzi = rdt.TzClass()\n\n    assert tzi.__class__ == rdt.TzClass\n    # PyPy generates <importlib.bootstrap.TzClass ...> for some reason.\n    assert re.match(r\"^<[\\w\\.]*TzClass object at\", repr(tzi))\n"
  },
  {
    "path": "pytests/tests/test_dict_iter.py",
    "content": "import pytest\nfrom pyo3_pytests.dict_iter import DictSize\n\n\n@pytest.mark.parametrize(\"size\", [64, 128, 256])\ndef test_size(size):\n    d = {}\n    for i in range(size):\n        d[i] = str(i)\n    assert DictSize(len(d)).iter_dict(d) == size\n"
  },
  {
    "path": "pytests/tests/test_enums.py",
    "content": "import pytest\nfrom pyo3_pytests import enums\n\n\ndef test_complex_enum_variant_constructors():\n    int_variant = enums.ComplexEnum.Int(42)\n    assert isinstance(int_variant, enums.ComplexEnum.Int)\n\n    float_variant = enums.ComplexEnum.Float(3.14)\n    assert isinstance(float_variant, enums.ComplexEnum.Float)\n\n    str_variant = enums.ComplexEnum.Str(\"hello\")\n    assert isinstance(str_variant, enums.ComplexEnum.Str)\n\n    empty_struct_variant = enums.ComplexEnum.EmptyStruct()\n    assert isinstance(empty_struct_variant, enums.ComplexEnum.EmptyStruct)\n\n    multi_field_struct_variant = enums.ComplexEnum.MultiFieldStruct(42, 3.14, True)\n    assert isinstance(multi_field_struct_variant, enums.ComplexEnum.MultiFieldStruct)\n\n    variant_with_default_1 = enums.ComplexEnum.VariantWithDefault()\n    assert isinstance(variant_with_default_1, enums.ComplexEnum.VariantWithDefault)\n\n    variant_with_default_2 = enums.ComplexEnum.VariantWithDefault(25, \"Hello\")\n    assert isinstance(variant_with_default_2, enums.ComplexEnum.VariantWithDefault)\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.ComplexEnum.Int(42),\n        enums.ComplexEnum.Float(3.14),\n        enums.ComplexEnum.Str(\"hello\"),\n        enums.ComplexEnum.EmptyStruct(),\n        enums.ComplexEnum.MultiFieldStruct(42, 3.14, True),\n        enums.ComplexEnum.VariantWithDefault(),\n    ],\n)\ndef test_complex_enum_variant_subclasses(variant: enums.ComplexEnum):\n    assert isinstance(variant, enums.ComplexEnum)\n\n\ndef test_complex_enum_field_getters():\n    int_variant = enums.ComplexEnum.Int(42)\n    assert int_variant.i == 42\n\n    float_variant = enums.ComplexEnum.Float(3.14)\n    assert float_variant.f == 3.14\n\n    str_variant = enums.ComplexEnum.Str(\"hello\")\n    assert str_variant.s == \"hello\"\n\n    multi_field_struct_variant = enums.ComplexEnum.MultiFieldStruct(42, 3.14, True)\n    assert multi_field_struct_variant.a == 42\n    assert multi_field_struct_variant.b == 3.14\n    assert multi_field_struct_variant.c is True\n\n    variant_with_default = enums.ComplexEnum.VariantWithDefault()\n    assert variant_with_default.a == 42\n    assert variant_with_default.b is None\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.ComplexEnum.Int(42),\n        enums.ComplexEnum.Float(3.14),\n        enums.ComplexEnum.Str(\"hello\"),\n        enums.ComplexEnum.EmptyStruct(),\n        enums.ComplexEnum.MultiFieldStruct(42, 3.14, True),\n        enums.ComplexEnum.VariantWithDefault(),\n    ],\n)\ndef test_complex_enum_desugared_match(variant: enums.ComplexEnum):\n    if isinstance(variant, enums.ComplexEnum.Int):\n        assert variant.i == 42\n    elif isinstance(variant, enums.ComplexEnum.Float):\n        assert variant.f == 3.14\n    elif isinstance(variant, enums.ComplexEnum.Str):\n        assert variant.s == \"hello\"\n    elif isinstance(variant, enums.ComplexEnum.EmptyStruct):\n        assert True\n    elif isinstance(variant, enums.ComplexEnum.MultiFieldStruct):\n        assert variant.a == 42\n        assert variant.b == 3.14\n        assert variant.c is True\n    elif isinstance(variant, enums.ComplexEnum.VariantWithDefault):\n        assert variant.a == 42\n        assert variant.b is None\n    else:\n        assert False\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.ComplexEnum.Int(42),\n        enums.ComplexEnum.Float(3.14),\n        enums.ComplexEnum.Str(\"hello\"),\n        enums.ComplexEnum.EmptyStruct(),\n        enums.ComplexEnum.MultiFieldStruct(42, 3.14, True),\n        enums.ComplexEnum.VariantWithDefault(b=\"hello\"),\n    ],\n)\ndef test_complex_enum_pyfunction_in_out_desugared_match(variant: enums.ComplexEnum):\n    variant = enums.do_complex_stuff(variant)\n    if isinstance(variant, enums.ComplexEnum.Int):\n        assert variant.i == 5\n    elif isinstance(variant, enums.ComplexEnum.Float):\n        assert variant.f == 9.8596\n    elif isinstance(variant, enums.ComplexEnum.Str):\n        assert variant.s == \"42\"\n    elif isinstance(variant, enums.ComplexEnum.EmptyStruct):\n        assert True\n    elif isinstance(variant, enums.ComplexEnum.MultiFieldStruct):\n        assert variant.a == 42\n        assert variant.b == 3.14\n        assert variant.c is True\n    elif isinstance(variant, enums.ComplexEnum.VariantWithDefault):\n        assert variant.a == 84\n        assert variant.b == \"HELLO\"\n    else:\n        assert False\n\n\ndef test_tuple_enum_variant_constructors():\n    tuple_variant = enums.TupleEnum.Full(42, 3.14, False)\n    assert isinstance(tuple_variant, enums.TupleEnum.Full)\n\n    empty_tuple_variant = enums.TupleEnum.EmptyTuple()\n    assert isinstance(empty_tuple_variant, enums.TupleEnum.EmptyTuple)\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.TupleEnum.FullWithDefault(),\n        enums.TupleEnum.Full(42, 3.14, False),\n        enums.TupleEnum.EmptyTuple(),\n    ],\n)\ndef test_tuple_enum_variant_subclasses(variant: enums.TupleEnum):\n    assert isinstance(variant, enums.TupleEnum)\n\n\ndef test_tuple_enum_defaults():\n    variant = enums.TupleEnum.FullWithDefault()\n    assert variant._0 == 1\n    assert variant._1 == 1.0\n    assert variant._2 is True\n\n\ndef test_tuple_enum_field_getters():\n    tuple_variant = enums.TupleEnum.Full(42, 3.14, False)\n    assert tuple_variant._0 == 42\n    assert tuple_variant._1 == 3.14\n    assert tuple_variant._2 is False\n\n\ndef test_tuple_enum_index_getter():\n    tuple_variant = enums.TupleEnum.Full(42, 3.14, False)\n    assert len(tuple_variant) == 3\n    assert tuple_variant[0] == 42\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [enums.MixedComplexEnum.Nothing()],\n)\ndef test_mixed_complex_enum_pyfunction_instance_nothing(\n    variant: enums.MixedComplexEnum,\n):\n    assert isinstance(variant, enums.MixedComplexEnum.Nothing)\n    assert isinstance(\n        enums.do_mixed_complex_stuff(variant), enums.MixedComplexEnum.Empty\n    )\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [enums.MixedComplexEnum.Empty()],\n)\ndef test_mixed_complex_enum_pyfunction_instance_empty(variant: enums.MixedComplexEnum):\n    assert isinstance(variant, enums.MixedComplexEnum.Empty)\n    assert isinstance(\n        enums.do_mixed_complex_stuff(variant), enums.MixedComplexEnum.Nothing\n    )\n"
  },
  {
    "path": "pytests/tests/test_enums_match.py",
    "content": "# This file is only collected when Python >= 3.10, because it tests match syntax.\nimport pytest\nfrom pyo3_pytests import enums\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.ComplexEnum.Int(42),\n        enums.ComplexEnum.Float(3.14),\n        enums.ComplexEnum.Str(\"hello\"),\n        enums.ComplexEnum.EmptyStruct(),\n        enums.ComplexEnum.MultiFieldStruct(42, 3.14, True),\n    ],\n)\ndef test_complex_enum_match_statement(variant: enums.ComplexEnum):\n    match variant:\n        case enums.ComplexEnum.Int(i=x):\n            assert x == 42\n        case enums.ComplexEnum.Float(f=x):\n            assert x == 3.14\n        case enums.ComplexEnum.Str(s=x):\n            assert x == \"hello\"\n        case enums.ComplexEnum.EmptyStruct():\n            assert True\n        case enums.ComplexEnum.MultiFieldStruct(a=x, b=y, c=z):\n            assert x == 42\n            assert y == 3.14\n            assert z is True\n        case _:\n            assert False\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.ComplexEnum.Int(42),\n        enums.ComplexEnum.Float(3.14),\n        enums.ComplexEnum.Str(\"hello\"),\n        enums.ComplexEnum.EmptyStruct(),\n        enums.ComplexEnum.MultiFieldStruct(42, 3.14, True),\n    ],\n)\ndef test_complex_enum_pyfunction_in_out(variant: enums.ComplexEnum):\n    match enums.do_complex_stuff(variant):\n        case enums.ComplexEnum.Int(i=x):\n            assert x == 5\n        case enums.ComplexEnum.Float(f=x):\n            assert x == 9.8596\n        case enums.ComplexEnum.Str(s=x):\n            assert x == \"42\"\n        case enums.ComplexEnum.EmptyStruct():\n            assert True\n        case enums.ComplexEnum.MultiFieldStruct(a=x, b=y, c=z):\n            assert x == 42\n            assert y == 3.14\n            assert z is True\n        case _:\n            assert False\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.ComplexEnum.MultiFieldStruct(42, 3.14, True),\n    ],\n)\ndef test_complex_enum_partial_match(variant: enums.ComplexEnum):\n    match variant:\n        case enums.ComplexEnum.MultiFieldStruct(a):\n            assert a == 42\n        case _:\n            assert False\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.TupleEnum.Full(42, 3.14, True),\n        enums.TupleEnum.EmptyTuple(),\n    ],\n)\ndef test_tuple_enum_match_statement(variant: enums.TupleEnum):\n    match variant:\n        case enums.TupleEnum.Full(_0=x, _1=y, _2=z):\n            assert x == 42\n            assert y == 3.14\n            assert z is True\n        case enums.TupleEnum.EmptyTuple():\n            assert True\n        case _:\n            print(variant)\n            assert False\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.SimpleTupleEnum.Int(42),\n        enums.SimpleTupleEnum.Str(\"hello\"),\n    ],\n)\ndef test_simple_tuple_enum_match_statement(variant: enums.SimpleTupleEnum):\n    match variant:\n        case enums.SimpleTupleEnum.Int(x):\n            assert x == 42\n        case enums.SimpleTupleEnum.Str(x):\n            assert x == \"hello\"\n        case _:\n            assert False\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.TupleEnum.Full(42, 3.14, True),\n    ],\n)\ndef test_tuple_enum_match_match_args(variant: enums.TupleEnum):\n    match variant:\n        case enums.TupleEnum.Full(x, y, z):\n            assert x == 42\n            assert y == 3.14\n            assert z is True\n            assert True\n        case _:\n            assert False\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.TupleEnum.Full(42, 3.14, True),\n    ],\n)\ndef test_tuple_enum_partial_match(variant: enums.TupleEnum):\n    match variant:\n        case enums.TupleEnum.Full(a):\n            assert a == 42\n        case _:\n            assert False\n\n\n@pytest.mark.parametrize(\n    \"variant\",\n    [\n        enums.MixedComplexEnum.Nothing(),\n        enums.MixedComplexEnum.Empty(),\n    ],\n)\ndef test_mixed_complex_enum_match_statement(variant: enums.MixedComplexEnum):\n    match variant:\n        case enums.MixedComplexEnum.Nothing():\n            assert True\n        case enums.MixedComplexEnum.Empty():\n            assert True\n        case _:\n            assert False\n"
  },
  {
    "path": "pytests/tests/test_hammer_attaching_in_thread.py",
    "content": "import sysconfig\n\nimport pytest\n\nfrom pyo3_pytests import misc\n\n\ndef make_loop():\n    # create a reference loop that will only be destroyed when the GC is called at the end\n    # of execution\n    start = []\n    cur = [start]\n    for _ in range(1000 * 1000 * 10):\n        cur = [cur]\n    start.append(cur)\n    return start\n\n\n# set a bomb that will explode when modules are cleaned up\nloopy = [make_loop()]\n\n\n@pytest.mark.skipif(\n    sysconfig.get_config_var(\"Py_DEBUG\"),\n    reason=\"causes a crash on debug builds, see discussion in https://github.com/PyO3/pyo3/pull/4874\",\n)\ndef test_hammer_attaching_in_thread():\n    loopy.append(misc.hammer_attaching_in_thread())\n"
  },
  {
    "path": "pytests/tests/test_misc.py",
    "content": "import importlib\nimport platform\nimport sys\n\nimport pyo3_pytests.misc\nimport pytest\n\nif sys.version_info >= (3, 13):\n    subinterpreters = pytest.importorskip(\"_interpreters\")\nelse:\n    subinterpreters = pytest.importorskip(\"_xxsubinterpreters\")\n\n\ndef test_issue_219():\n    # Should not deadlock\n    pyo3_pytests.misc.issue_219()\n\n\n@pytest.mark.xfail(\n    platform.python_implementation() == \"CPython\" and sys.version_info < (3, 9),\n    reason=\"Cannot identify subinterpreters on Python older than 3.9\",\n)\ndef test_multiple_imports_same_interpreter_ok():\n    spec = importlib.util.find_spec(\"pyo3_pytests.pyo3_pytests\")\n\n    module = importlib.util.module_from_spec(spec)\n    spec.loader.exec_module(module)\n    assert dir(module) == dir(pyo3_pytests.pyo3_pytests)\n\n\n@pytest.mark.xfail(\n    platform.python_implementation() == \"CPython\" and sys.version_info < (3, 9),\n    reason=\"Cannot identify subinterpreters on Python older than 3.9\",\n)\n@pytest.mark.skipif(\n    platform.python_implementation() in (\"PyPy\", \"GraalVM\"),\n    reason=\"PyPy and GraalPy do not support subinterpreters\",\n)\ndef test_import_in_subinterpreter_forbidden():\n    sub_interpreter = subinterpreters.create()\n    if sys.version_info < (3, 12):\n        expected_error = \"PyO3 modules do not yet support subinterpreters, see https://github.com/PyO3/pyo3/issues/576\"\n    else:\n        expected_error = \"module pyo3_pytests.pyo3_pytests does not support loading in subinterpreters\"\n\n    if sys.version_info < (3, 13):\n        # Python 3.12 subinterpreters had a special error for this\n        with pytest.raises(\n            subinterpreters.RunFailedError,\n            match=expected_error,\n        ):\n            subinterpreters.run_string(\n                sub_interpreter, \"import pyo3_pytests.pyo3_pytests\"\n            )\n    else:\n        res = subinterpreters.run_string(\n            sub_interpreter, \"import pyo3_pytests.pyo3_pytests\"\n        )\n        assert res.type.__name__ == \"ImportError\"\n        assert res.msg == expected_error\n\n    subinterpreters.destroy(sub_interpreter)\n\n\ndef test_type_fully_qualified_name_includes_module():\n    numpy = pytest.importorskip(\"numpy\")\n\n    # For numpy 1.x and 2.x\n    assert pyo3_pytests.misc.get_type_fully_qualified_name(numpy.bool_(True)) in [\n        \"numpy.bool\",\n        \"numpy.bool_\",\n    ]\n\n\ndef test_accepts_numpy_bool():\n    # binary numpy wheel not available on all platforms\n    numpy = pytest.importorskip(\"numpy\")\n\n    assert pyo3_pytests.misc.accepts_bool(True) is True\n    assert pyo3_pytests.misc.accepts_bool(False) is False\n    assert pyo3_pytests.misc.accepts_bool(numpy.bool_(True)) is True\n    assert pyo3_pytests.misc.accepts_bool(numpy.bool_(False)) is False\n\n\nclass ArbitraryClass:\n    worker_id: int\n    iteration: int\n\n    def __init__(self, worker_id: int, iteration: int):\n        self.worker_id = worker_id\n        self.iteration = iteration\n\n    def __repr__(self):\n        return f\"ArbitraryClass({self.worker_id}, {self.iteration})\"\n\n    def __del__(self):\n        print(\"del\", self.worker_id, self.iteration)\n\n\ndef test_gevent():\n    gevent = pytest.importorskip(\"gevent\")\n\n    def worker(worker_id: int) -> None:\n        for iteration in range(2):\n            d = {\"key\": ArbitraryClass(worker_id, iteration)}\n\n            def arbitrary_python_code():\n                # remove the dictionary entry so that the class value can be\n                # garbage collected\n                del d[\"key\"]\n                print(\"gevent sleep\", worker_id, iteration)\n                gevent.sleep(0)\n                print(\"after gevent sleep\", worker_id, iteration)\n\n            print(\"start\", worker_id, iteration)\n            pyo3_pytests.misc.get_item_and_run_callback(d, arbitrary_python_code)\n            print(\"end\", worker_id, iteration)\n\n    workers = [gevent.spawn(worker, i) for i in range(2)]\n    gevent.joinall(workers)\n"
  },
  {
    "path": "pytests/tests/test_objstore.py",
    "content": "import gc\nimport sys\n\nfrom pyo3_pytests.objstore import ObjStore\n\n\ndef test_objstore_doesnot_leak_memory():\n    N = 10000\n    message = b'\\\\(-\"-;) Praying that memory leak would not happen..'\n\n    # PyPy does not have sys.getrefcount, provide a no-op lambda and don't\n    # check refcount on PyPy\n    getrefcount = getattr(sys, \"getrefcount\", lambda obj: 0)\n\n    if sys.implementation.name == \"graalpy\":\n        # GraalPy has an incomplete sys.getrefcount implementation\n        def getrefcount(obj):\n            return 0\n\n    before = getrefcount(message)\n    store = ObjStore()\n    for _ in range(N):\n        store.push(message)\n    del store\n    gc.collect()\n    after = getrefcount(message)\n\n    assert after - before == 0\n"
  },
  {
    "path": "pytests/tests/test_othermod.py",
    "content": "from hypothesis import given, assume\nfrom hypothesis import strategies as st\n\nfrom pyo3_pytests import othermod\n\nINTEGER31_ST = st.integers(min_value=(-(2**30)), max_value=(2**30 - 1))\nUSIZE_ST = st.integers(min_value=othermod.USIZE_MIN, max_value=othermod.USIZE_MAX)\n\n\n# If the full 32 bits are used here, then you can get failures that look like this:\n# hypothesis.errors.FailedHealthCheck: It looks like your strategy is filtering out a lot of data.\n# Health check found 50 filtered examples but only 7 good ones.\n#\n# Limit the range to 31 bits to avoid this problem.\n@given(x=INTEGER31_ST)\ndef test_double(x):\n    expected = x * 2\n    assume(-(2**31) <= expected <= (2**31 - 1))\n    assert othermod.double(x) == expected\n\n\ndef test_modclass():\n    # Test that the repr of the class itself doesn't crash anything\n    repr(othermod.ModClass)\n\n    assert isinstance(othermod.ModClass, type)\n\n\ndef test_modclass_instance():\n    mi = othermod.ModClass()\n\n    repr(mi)\n    repr(mi.__class__)\n\n    assert isinstance(mi, othermod.ModClass)\n    assert isinstance(mi, object)\n\n\n@given(x=USIZE_ST)\ndef test_modclas_noop(x):\n    mi = othermod.ModClass()\n\n    assert mi.noop(x) == x\n"
  },
  {
    "path": "pytests/tests/test_path.py",
    "content": "import pathlib\n\nimport pytest\n\nimport pyo3_pytests.path as rpath\n\n\ndef test_make_path():\n    p = rpath.make_path()\n    assert p == pathlib.Path(\"/root\")\n\n\ndef test_take_pathbuf():\n    p = \"/root\"\n    assert rpath.take_pathbuf(p) == pathlib.Path(p)\n\n\ndef test_take_pathlib():\n    p = pathlib.Path(\"/root\")\n    assert rpath.take_pathbuf(p) == p\n\n\ndef test_take_pathlike():\n    assert rpath.take_pathbuf(PathLike(\"/root\")) == pathlib.Path(\"/root\")\n\n\ndef test_take_invalid_pathlike():\n    with pytest.raises(TypeError):\n        assert rpath.take_pathbuf(PathLike(1))\n\n\ndef test_take_invalid():\n    with pytest.raises(TypeError):\n        assert rpath.take_pathbuf(3)\n\n\nclass PathLike:\n    def __init__(self, path):\n        self._path = path\n\n    def __fspath__(self):\n        return self._path\n"
  },
  {
    "path": "pytests/tests/test_pyclasses.py",
    "content": "import platform\nimport sys\nfrom typing import Type\n\nimport pytest\nfrom pyo3_pytests import pyclasses\n\n\ndef test_empty_class_init(benchmark):\n    benchmark(pyclasses.EmptyClass)\n\n\ndef test_method_call(benchmark):\n    obj = pyclasses.EmptyClass()\n    assert benchmark(obj.method) is None\n\n\ndef test_proto_call(benchmark):\n    obj = pyclasses.EmptyClass()\n    assert benchmark(len, obj) == 0\n\n\nclass EmptyClassPy:\n    def method(self):\n        pass\n\n    def __len__(self) -> int:\n        return 0\n\n\ndef test_empty_class_init_py(benchmark):\n    benchmark(EmptyClassPy)\n\n\ndef test_method_call_py(benchmark):\n    obj = EmptyClassPy()\n    assert benchmark(obj.method) == pyclasses.EmptyClass().method()\n\n\ndef test_proto_call_py(benchmark):\n    obj = EmptyClassPy()\n    assert benchmark(len, obj) == len(pyclasses.EmptyClass())\n\n\ndef test_iter():\n    i = pyclasses.PyClassIter()\n    assert next(i) == 1\n    assert next(i) == 2\n    assert next(i) == 3\n    assert next(i) == 4\n    assert next(i) == 5\n\n    with pytest.raises(StopIteration) as excinfo:\n        next(i)\n    assert excinfo.value.value == \"Ended\"\n\n\n@pytest.mark.skipif(\n    platform.machine() in [\"wasm32\", \"wasm64\"],\n    reason=\"not supporting threads in CI for WASM yet\",\n)\ndef test_parallel_iter():\n    import concurrent.futures\n    import threading\n\n    thread_iter = pyclasses.PyClassThreadIter()\n    max_workers = 2\n    b = threading.Barrier(max_workers)\n    error_happened = threading.Event()\n\n    # the second thread attempts to borrow a reference to the instance's\n    # state while the first thread is still sleeping, so we trigger a\n    # runtime borrow-check error\n    def closure(i):\n        b.wait()\n        # should never reach 100 iterations, the borrow error should\n        # happen relatively quickly because the loops are synchronized\n        for j in range(100):\n            if not error_happened.is_set():\n                try:\n                    next(thread_iter)\n                except RuntimeError as e:\n                    assert \"Already borrowed\" in str(e), str(e)\n                    error_happened.set()\n            else:\n                break\n        else:\n            assert False, \"Should not be able to complete loop\"\n\n    with concurrent.futures.ThreadPoolExecutor(max_workers=max_workers) as tpe:\n        for _ in tpe.map(closure, range(max_workers)):\n            pass\n\n\nclass AssertingSubClass(pyclasses.AssertingBaseClass):\n    pass\n\n\ndef test_new_classmethod():\n    # The `AssertingBaseClass` constructor errors if it is not passed the\n    # relevant subclass.\n    _ = AssertingSubClass(expected_type=AssertingSubClass)\n    with pytest.raises(ValueError):\n        _ = AssertingSubClass(expected_type=str)\n\n\nclass ClassWithoutConstructor:\n    def __new__(cls):\n        raise TypeError(\n            f\"cannot create '{cls.__module__}.{cls.__qualname__}' instances\"\n        )\n\n\n@pytest.mark.xfail(\n    platform.python_implementation() == \"PyPy\" and sys.version_info[:2] == (3, 11),\n    reason=\"broken on PyPy 3.11 due to https://github.com/pypy/pypy/issues/5319, waiting for next release\",\n)\n@pytest.mark.parametrize(\n    \"cls, exc_message\",\n    [\n        (\n            pyclasses.ClassWithoutConstructor,\n            \"cannot create 'builtins.ClassWithoutConstructor' instances\",\n        ),\n        (\n            ClassWithoutConstructor,\n            \"cannot create 'test_pyclasses.ClassWithoutConstructor' instances\",\n        ),\n    ],\n)\ndef test_no_constructor_defined_propagates_cause(cls: Type, exc_message: str):\n    original_error = ValueError(\"Original message\")\n    with pytest.raises(Exception) as exc_info:\n        try:\n            raise original_error\n        except Exception:\n            cls()  # should raise TypeError(\"No constructor defined for ...\")\n\n    assert exc_info.type is TypeError\n    assert exc_info.value.args == (exc_message,)\n    assert exc_info.value.__context__ is original_error\n\n\ndef test_dict():\n    try:\n        ClassWithDict = pyclasses.ClassWithDict\n    except AttributeError:\n        pytest.skip(\"not defined using abi3 < 3.9\")\n\n    d = ClassWithDict()\n    assert d.__dict__ == {}\n\n    d.foo = 42\n    assert d.__dict__ == {\"foo\": 42}\n\n\ndef test_getter(benchmark):\n    obj = pyclasses.ClassWithDecorators()\n    benchmark(lambda: obj.attr)\n\n\ndef test_setter(benchmark):\n    obj = pyclasses.ClassWithDecorators()\n\n    def set_attr():\n        obj.attr = 42\n\n    benchmark(set_attr)\n\n\ndef test_deleter():\n    obj = pyclasses.ClassWithDecorators()\n    del obj.attr\n    with pytest.raises(AttributeError):\n        _ = obj.attr\n    obj.attr = 42\n    assert obj.attr == 42\n\n\ndef test_class_attribute(benchmark):\n    cls = pyclasses.ClassWithDecorators\n    benchmark(lambda: cls.cls_attribute)\n\n\ndef test_class_method(benchmark):\n    cls = pyclasses.ClassWithDecorators\n    benchmark(lambda: cls.cls_method())\n\n\ndef test_static_method(benchmark):\n    cls = pyclasses.ClassWithDecorators\n    benchmark(lambda: cls.static_method())\n\n\ndef test_class_init_method():\n    try:\n        SubClassWithInit = pyclasses.SubClassWithInit\n    except AttributeError:\n        pytest.skip(\"not defined using abi3\")\n\n    d = SubClassWithInit()\n    assert d == {\"__init__\": True}\n\n    d = SubClassWithInit({\"a\": 1}, b=2)\n    assert d == {\"__init__\": True, \"a\": 1, \"b\": 2}\n"
  },
  {
    "path": "pytests/tests/test_pyfunctions.py",
    "content": "from typing import Any, Tuple\n\nfrom pyo3_pytests import pyfunctions\n\n\ndef none_py():\n    return None\n\n\ndef test_none_py(benchmark):\n    benchmark(none_py)\n\n\ndef test_none_rs(benchmark):\n    rust = benchmark(pyfunctions.none)\n    py = none_py()\n    assert rust == py\n\n\ndef simple_py(a, b=None, *, c=None):\n    return a, b, c\n\n\ndef test_simple_py(benchmark):\n    benchmark(simple_py, 1, \"foo\", c={1: 2})\n\n\ndef test_simple_rs(benchmark):\n    rust = benchmark(pyfunctions.simple, 1, \"foo\", c={1: 2})\n    py = simple_py(1, \"foo\", c={1: 2})\n    assert rust == py\n\n\ndef simple_args_py(a, b=None, *args, c=None):\n    return a, b, args, c\n\n\ndef test_simple_args_py(benchmark):\n    benchmark(simple_args_py, 1, \"foo\", 4, 5, 6, c={1: 2})\n\n\ndef test_simple_args_rs(benchmark):\n    rust = benchmark(pyfunctions.simple_args, 1, \"foo\", 4, 5, 6, c={1: 2})\n    py = simple_args_py(1, \"foo\", 4, 5, 6, c={1: 2})\n    assert rust == py\n\n\ndef simple_kwargs_py(a, b=None, c=None, **kwargs):\n    return a, b, c, kwargs\n\n\ndef test_simple_kwargs_py(benchmark):\n    benchmark(simple_kwargs_py, 1, \"foo\", c={1: 2}, bar=4, foo=10)\n\n\ndef test_simple_kwargs_rs(benchmark):\n    rust = benchmark(pyfunctions.simple_kwargs, 1, \"foo\", c={1: 2}, bar=4, foo=10)\n    py = simple_kwargs_py(1, \"foo\", c={1: 2}, bar=4, foo=10)\n    assert rust == py\n\n\ndef simple_args_kwargs_py(a, b=None, *args, c=None, **kwargs):\n    return a, b, args, c, kwargs\n\n\ndef test_simple_args_kwargs_py(benchmark):\n    benchmark(simple_args_kwargs_py, 1, \"foo\", \"baz\", bar=4, foo=10)\n\n\ndef test_simple_args_kwargs_rs(benchmark):\n    rust = benchmark(pyfunctions.simple_args_kwargs, 1, \"foo\", \"baz\", bar=4, foo=10)\n    py = simple_args_kwargs_py(1, \"foo\", \"baz\", bar=4, foo=10)\n    assert rust == py\n\n\ndef args_kwargs_py(*args, **kwargs):\n    return args, kwargs\n\n\ndef test_args_kwargs_py(benchmark):\n    benchmark(args_kwargs_py, 1, \"foo\", {1: 2}, bar=4, foo=10)\n\n\ndef test_args_kwargs_rs(benchmark):\n    rust = benchmark(pyfunctions.args_kwargs, 1, \"foo\", {1: 2}, bar=4, foo=10)\n    py = args_kwargs_py(1, \"foo\", {1: 2}, bar=4, foo=10)\n    assert rust == py\n\n\n# TODO: the second argument should be positional-only\n# but can't be without breaking tests on Python 3.7.\n# See gh-5095.\ndef positional_only_py(a, b):\n    return a, b\n\n\ndef test_positional_only_py(benchmark):\n    benchmark(positional_only_py, 1, \"foo\")\n\n\ndef test_positional_only_rs(benchmark):\n    rust = benchmark(pyfunctions.positional_only, 1, \"foo\")\n    py = positional_only_py(1, \"foo\")\n    assert rust == py\n\n\ndef with_typed_args_py(\n    a: bool, b: int, c: float, d: str\n) -> Tuple[bool, int, float, str]:\n    return a, b, c, d\n\n\ndef test_with_typed_args_py(benchmark):\n    benchmark(with_typed_args_py, True, 1, 1.2, \"foo\")\n\n\ndef test_with_typed_args_rs(benchmark):\n    rust = benchmark(pyfunctions.with_typed_args, True, 1, 1.2, \"foo\")\n    py = with_typed_args_py(True, 1, 1.2, \"foo\")\n    assert rust == py\n\n\ndef many_keyword_arguments_py(\n    *,\n    ant: Any = None,\n    bear: Any = None,\n    cat: Any = None,\n    dog: Any = None,\n    elephant: Any = None,\n    fox: Any = None,\n    goat: Any = None,\n    horse: Any = None,\n    iguana: Any = None,\n    jaguar: Any = None,\n    koala: Any = None,\n    lion: Any = None,\n    monkey: Any = None,\n    newt: Any = None,\n    owl: Any = None,\n    penguin: Any = None,\n): ...\n\n\ndef call_with_many_keyword_arguments(f) -> Any:\n    return f(\n        ant=True,\n        bear=1,\n        cat=1.2,\n        dog=\"foo\",\n        elephant=None,\n        fox=8,\n        goat=9,\n        horse=10,\n        iguana=None,\n        jaguar=None,\n        koala=None,\n        lion=11,\n        owl=None,\n        penguin=None,\n    )\n\n\ndef test_many_keyword_arguments_py(benchmark):\n    benchmark(call_with_many_keyword_arguments, many_keyword_arguments_py)\n\n\ndef test_many_keyword_arguments_rs(benchmark):\n    rust = benchmark(\n        call_with_many_keyword_arguments, pyfunctions.many_keyword_arguments\n    )\n    py = call_with_many_keyword_arguments(many_keyword_arguments_py)\n    assert rust == py\n"
  },
  {
    "path": "pytests/tests/test_sequence.py",
    "content": "import pytest\n\nfrom pyo3_pytests import sequence\n\n\ndef test_vec_from_list_i32():\n    assert sequence.vec_to_vec_i32([1, 2, 3]) == [1, 2, 3]\n\n\ndef test_vec_from_list_pystring():\n    assert sequence.vec_to_vec_pystring([\"1\", \"2\", \"3\"]) == [\"1\", \"2\", \"3\"]\n\n\ndef test_vec_from_bytes():\n    assert sequence.vec_to_vec_i32(b\"123\") == [49, 50, 51]\n\n\ndef test_vec_from_str():\n    with pytest.raises(TypeError):\n        sequence.vec_to_vec_pystring(\"123\")\n\n\ndef test_vec_from_array():\n    # binary numpy wheel not available on all platforms\n    numpy = pytest.importorskip(\"numpy\")\n\n    assert sequence.vec_to_vec_i32(numpy.array([1, 2, 3])) == [1, 2, 3]\n\n\ndef test_rust_array_from_array():\n    # binary numpy wheel not available on all platforms\n    numpy = pytest.importorskip(\"numpy\")\n\n    assert sequence.array_to_array_i32(numpy.array([1, 2, 3])) == [1, 2, 3]\n"
  },
  {
    "path": "pytests/tests/test_subclassing.py",
    "content": "from pyo3_pytests.subclassing import Subclassable, Subclass\n\n\nclass SomeSubClass(Subclassable):\n    def __str__(self):\n        return \"SomeSubclass\"\n\n\ndef test_python_subclassing():\n    a = SomeSubClass()\n    assert str(a) == \"SomeSubclass\"\n    assert type(a) is SomeSubClass\n\n\ndef test_rust_subclassing():\n    a = Subclass()\n    assert str(a) == \"Subclass\"\n    assert type(a) is Subclass\n"
  },
  {
    "path": "src/buffer.rs",
    "content": "#![cfg(any(not(Py_LIMITED_API), Py_3_11))]\n// Copyright (c) 2017 Daniel Grunwald\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this\n// software and associated documentation files (the \"Software\"), to deal in the Software\n// without restriction, including without limitation the rights to use, copy, modify, merge,\n// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons\n// to whom the Software is furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in all copies or\n// substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,\n// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR\n// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE\n// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n// DEALINGS IN THE SOFTWARE.\n\n//! `PyBuffer` implementation\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_identifier, PyStaticExpr};\nuse crate::{err, exceptions::PyBufferError, ffi, FromPyObject, PyAny, PyResult, Python};\nuse crate::{Borrowed, Bound, PyErr};\nuse std::ffi::{\n    c_char, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint, c_ulong, c_ulonglong,\n    c_ushort, c_void,\n};\nuse std::marker::{PhantomData, PhantomPinned};\nuse std::pin::Pin;\nuse std::ptr::NonNull;\nuse std::{cell, mem, ptr, slice};\nuse std::{ffi::CStr, fmt::Debug};\n\n/// A typed form of [`PyUntypedBuffer`].\n#[repr(transparent)]\npub struct PyBuffer<T>(PyUntypedBuffer, PhantomData<[T]>);\n\n/// Allows access to the underlying buffer used by a python object such as `bytes`, `bytearray` or `array.array`.\n#[repr(transparent)]\npub struct PyUntypedBuffer(\n    // It is common for exporters filling `Py_buffer` struct to make it self-referential, e.g. see\n    // implementation of\n    // [`PyBuffer_FillInfo`](https://github.com/python/cpython/blob/2fd43a1ffe4ff1f6c46f6045bc327d6085c40fbf/Objects/abstract.c#L798-L802).\n    //\n    // Therefore we use `Pin<Box<...>>` to document for ourselves that the memory address of the `Py_buffer` is expected to be stable\n    Pin<Box<RawBuffer>>,\n);\n\n/// Wrapper around `ffi::Py_buffer` to be `!Unpin`.\n#[repr(transparent)]\nstruct RawBuffer(ffi::Py_buffer, PhantomPinned);\n\n// PyBuffer send & sync guarantees are upheld by Python.\nunsafe impl Send for PyUntypedBuffer {}\nunsafe impl Sync for PyUntypedBuffer {}\n\nimpl<T> Debug for PyBuffer<T> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        debug_buffer(\"PyBuffer\", &self.0, f)\n    }\n}\n\nimpl Debug for PyUntypedBuffer {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        debug_buffer(\"PyUntypedBuffer\", self, f)\n    }\n}\n\nfn debug_buffer(\n    name: &str,\n    b: &PyUntypedBuffer,\n    f: &mut std::fmt::Formatter<'_>,\n) -> std::fmt::Result {\n    let raw = b.raw();\n    f.debug_struct(name)\n        .field(\"buf\", &raw.buf)\n        .field(\"obj\", &raw.obj)\n        .field(\"len\", &raw.len)\n        .field(\"itemsize\", &raw.itemsize)\n        .field(\"readonly\", &raw.readonly)\n        .field(\"ndim\", &raw.ndim)\n        .field(\"format\", &b.format())\n        .field(\"shape\", &b.shape())\n        .field(\"strides\", &b.strides())\n        .field(\"suboffsets\", &b.suboffsets())\n        .field(\"internal\", &raw.internal)\n        .finish()\n}\n\n/// Represents the type of a Python buffer element.\n#[derive(Copy, Clone, Debug, Eq, PartialEq)]\npub enum ElementType {\n    /// A signed integer type.\n    SignedInteger {\n        /// The width of the signed integer in bytes.\n        bytes: usize,\n    },\n    /// An unsigned integer type.\n    UnsignedInteger {\n        /// The width of the unsigned integer in bytes.\n        bytes: usize,\n    },\n    /// A boolean type.\n    Bool,\n    /// A float type.\n    Float {\n        /// The width of the float in bytes.\n        bytes: usize,\n    },\n    /// An unknown type. This may occur when parsing has failed.\n    Unknown,\n}\n\nimpl ElementType {\n    /// Determines the `ElementType` from a Python `struct` module format string.\n    ///\n    /// See <https://docs.python.org/3/library/struct.html#format-strings> for more information\n    /// about struct format strings.\n    pub fn from_format(format: &CStr) -> ElementType {\n        match format.to_bytes() {\n            [size] | [b'@', size] => native_element_type_from_type_char(*size),\n            [b'=' | b'<' | b'>' | b'!', size] => standard_element_type_from_type_char(*size),\n            _ => ElementType::Unknown,\n        }\n    }\n}\n\nfn native_element_type_from_type_char(type_char: u8) -> ElementType {\n    use self::ElementType::*;\n    match type_char {\n        b'c' => UnsignedInteger {\n            bytes: mem::size_of::<c_char>(),\n        },\n        b'b' => SignedInteger {\n            bytes: mem::size_of::<c_schar>(),\n        },\n        b'B' => UnsignedInteger {\n            bytes: mem::size_of::<c_uchar>(),\n        },\n        b'?' => Bool,\n        b'h' => SignedInteger {\n            bytes: mem::size_of::<c_short>(),\n        },\n        b'H' => UnsignedInteger {\n            bytes: mem::size_of::<c_ushort>(),\n        },\n        b'i' => SignedInteger {\n            bytes: mem::size_of::<c_int>(),\n        },\n        b'I' => UnsignedInteger {\n            bytes: mem::size_of::<c_uint>(),\n        },\n        b'l' => SignedInteger {\n            bytes: mem::size_of::<c_long>(),\n        },\n        b'L' => UnsignedInteger {\n            bytes: mem::size_of::<c_ulong>(),\n        },\n        b'q' => SignedInteger {\n            bytes: mem::size_of::<c_longlong>(),\n        },\n        b'Q' => UnsignedInteger {\n            bytes: mem::size_of::<c_ulonglong>(),\n        },\n        b'n' => SignedInteger {\n            bytes: mem::size_of::<libc::ssize_t>(),\n        },\n        b'N' => UnsignedInteger {\n            bytes: mem::size_of::<libc::size_t>(),\n        },\n        b'e' => Float { bytes: 2 },\n        b'f' => Float { bytes: 4 },\n        b'd' => Float { bytes: 8 },\n        _ => Unknown,\n    }\n}\n\nfn standard_element_type_from_type_char(type_char: u8) -> ElementType {\n    use self::ElementType::*;\n    match type_char {\n        b'c' | b'B' => UnsignedInteger { bytes: 1 },\n        b'b' => SignedInteger { bytes: 1 },\n        b'?' => Bool,\n        b'h' => SignedInteger { bytes: 2 },\n        b'H' => UnsignedInteger { bytes: 2 },\n        b'i' | b'l' => SignedInteger { bytes: 4 },\n        b'I' | b'L' => UnsignedInteger { bytes: 4 },\n        b'q' => SignedInteger { bytes: 8 },\n        b'Q' => UnsignedInteger { bytes: 8 },\n        b'e' => Float { bytes: 2 },\n        b'f' => Float { bytes: 4 },\n        b'd' => Float { bytes: 8 },\n        _ => Unknown,\n    }\n}\n\n#[cfg(target_endian = \"little\")]\nfn is_matching_endian(c: u8) -> bool {\n    c == b'@' || c == b'=' || c == b'>'\n}\n\n#[cfg(target_endian = \"big\")]\nfn is_matching_endian(c: u8) -> bool {\n    c == b'@' || c == b'=' || c == b'>' || c == b'!'\n}\n\n/// Trait implemented for possible element types of `PyBuffer`.\n///\n/// # Safety\n///\n/// This trait must only be implemented for types which represent valid elements of Python buffers.\npub unsafe trait Element: Copy {\n    /// Gets whether the element specified in the format string is potentially compatible.\n    /// Alignment and size are checked separately from this function.\n    fn is_compatible_format(format: &CStr) -> bool;\n}\n\nimpl<T: Element> FromPyObject<'_, '_> for PyBuffer<T> {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"collections.abc\", \"Buffer\");\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<PyBuffer<T>, Self::Error> {\n        Self::get(&obj)\n    }\n}\n\nimpl<T: Element> PyBuffer<T> {\n    /// Gets the underlying buffer from the specified python object.\n    pub fn get(obj: &Bound<'_, PyAny>) -> PyResult<Self> {\n        PyUntypedBuffer::get(obj)?.into_typed()\n    }\n\n    /// Gets the buffer memory as a slice.\n    ///\n    /// This function succeeds if:\n    /// * the buffer format is compatible with `T`\n    /// * alignment and size of buffer elements is matching the expectations for type `T`\n    /// * the buffer is C-style contiguous\n    ///\n    /// The returned slice uses type `Cell<T>` because it's theoretically possible for any call into the Python runtime\n    /// to modify the values in the slice.\n    pub fn as_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [ReadOnlyCell<T>]> {\n        if self.is_c_contiguous() {\n            unsafe {\n                Some(slice::from_raw_parts(\n                    self.raw().buf.cast(),\n                    self.item_count(),\n                ))\n            }\n        } else {\n            None\n        }\n    }\n\n    /// Gets the buffer memory as a slice.\n    ///\n    /// This function succeeds if:\n    /// * the buffer is not read-only\n    /// * the buffer format is compatible with `T`\n    /// * alignment and size of buffer elements is matching the expectations for type `T`\n    /// * the buffer is C-style contiguous\n    ///\n    /// The returned slice uses type `Cell<T>` because it's theoretically possible for any call into the Python runtime\n    /// to modify the values in the slice.\n    pub fn as_mut_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [cell::Cell<T>]> {\n        if !self.readonly() && self.is_c_contiguous() {\n            unsafe {\n                Some(slice::from_raw_parts(\n                    self.raw().buf.cast(),\n                    self.item_count(),\n                ))\n            }\n        } else {\n            None\n        }\n    }\n\n    /// Gets the buffer memory as a slice.\n    ///\n    /// This function succeeds if:\n    /// * the buffer format is compatible with `T`\n    /// * alignment and size of buffer elements is matching the expectations for type `T`\n    /// * the buffer is Fortran-style contiguous\n    ///\n    /// The returned slice uses type `Cell<T>` because it's theoretically possible for any call into the Python runtime\n    /// to modify the values in the slice.\n    pub fn as_fortran_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [ReadOnlyCell<T>]> {\n        if mem::size_of::<T>() == self.item_size() && self.is_fortran_contiguous() {\n            unsafe {\n                Some(slice::from_raw_parts(\n                    self.raw().buf.cast(),\n                    self.item_count(),\n                ))\n            }\n        } else {\n            None\n        }\n    }\n\n    /// Gets the buffer memory as a slice.\n    ///\n    /// This function succeeds if:\n    /// * the buffer is not read-only\n    /// * the buffer format is compatible with `T`\n    /// * alignment and size of buffer elements is matching the expectations for type `T`\n    /// * the buffer is Fortran-style contiguous\n    ///\n    /// The returned slice uses type `Cell<T>` because it's theoretically possible for any call into the Python runtime\n    /// to modify the values in the slice.\n    pub fn as_fortran_mut_slice<'a>(&'a self, _py: Python<'a>) -> Option<&'a [cell::Cell<T>]> {\n        if !self.readonly() && self.is_fortran_contiguous() {\n            unsafe {\n                Some(slice::from_raw_parts(\n                    self.raw().buf.cast(),\n                    self.item_count(),\n                ))\n            }\n        } else {\n            None\n        }\n    }\n\n    /// Copies the buffer elements to the specified slice.\n    /// If the buffer is multi-dimensional, the elements are written in C-style order.\n    ///\n    ///  * Fails if the slice does not have the correct length (`buf.item_count()`).\n    ///  * Fails if the buffer format is not compatible with type `T`.\n    ///\n    /// To check whether the buffer format is compatible before calling this method,\n    /// you can use `<T as buffer::Element>::is_compatible_format(buf.format())`.\n    /// Alternatively, `match buffer::ElementType::from_format(buf.format())`.\n    pub fn copy_to_slice(&self, py: Python<'_>, target: &mut [T]) -> PyResult<()> {\n        self._copy_to_slice(py, target, b'C')\n    }\n\n    /// Copies the buffer elements to the specified slice.\n    /// If the buffer is multi-dimensional, the elements are written in Fortran-style order.\n    ///\n    ///  * Fails if the slice does not have the correct length (`buf.item_count()`).\n    ///  * Fails if the buffer format is not compatible with type `T`.\n    ///\n    /// To check whether the buffer format is compatible before calling this method,\n    /// you can use `<T as buffer::Element>::is_compatible_format(buf.format())`.\n    /// Alternatively, `match buffer::ElementType::from_format(buf.format())`.\n    pub fn copy_to_fortran_slice(&self, py: Python<'_>, target: &mut [T]) -> PyResult<()> {\n        self._copy_to_slice(py, target, b'F')\n    }\n\n    fn _copy_to_slice(&self, py: Python<'_>, target: &mut [T], fort: u8) -> PyResult<()> {\n        if mem::size_of_val(target) != self.len_bytes() {\n            return Err(PyBufferError::new_err(format!(\n                \"slice to copy to (of length {}) does not match buffer length of {}\",\n                target.len(),\n                self.item_count()\n            )));\n        }\n\n        err::error_on_minusone(py, unsafe {\n            ffi::PyBuffer_ToContiguous(\n                target.as_mut_ptr().cast(),\n                #[cfg(Py_3_11)]\n                self.raw(),\n                #[cfg(not(Py_3_11))]\n                ptr::from_ref(self.raw()).cast_mut(),\n                self.raw().len,\n                fort as std::ffi::c_char,\n            )\n        })\n    }\n\n    /// Copies the buffer elements to a newly allocated vector.\n    /// If the buffer is multi-dimensional, the elements are written in C-style order.\n    ///\n    /// Fails if the buffer format is not compatible with type `T`.\n    pub fn to_vec(&self, py: Python<'_>) -> PyResult<Vec<T>> {\n        self._to_vec(py, b'C')\n    }\n\n    /// Copies the buffer elements to a newly allocated vector.\n    /// If the buffer is multi-dimensional, the elements are written in Fortran-style order.\n    ///\n    /// Fails if the buffer format is not compatible with type `T`.\n    pub fn to_fortran_vec(&self, py: Python<'_>) -> PyResult<Vec<T>> {\n        self._to_vec(py, b'F')\n    }\n\n    fn _to_vec(&self, py: Python<'_>, fort: u8) -> PyResult<Vec<T>> {\n        let item_count = self.item_count();\n        let mut vec: Vec<T> = Vec::with_capacity(item_count);\n\n        // Copy the buffer into the uninitialized space in the vector.\n        // Due to T:Copy, we don't need to be concerned with Drop impls.\n        err::error_on_minusone(py, unsafe {\n            ffi::PyBuffer_ToContiguous(\n                vec.as_mut_ptr().cast(),\n                #[cfg(Py_3_11)]\n                self.raw(),\n                #[cfg(not(Py_3_11))]\n                ptr::from_ref(self.raw()).cast_mut(),\n                self.raw().len,\n                fort as std::ffi::c_char,\n            )\n        })?;\n        // set vector length to mark the now-initialized space as usable\n        unsafe { vec.set_len(item_count) };\n        Ok(vec)\n    }\n\n    /// Copies the specified slice into the buffer.\n    /// If the buffer is multi-dimensional, the elements in the slice are expected to be in C-style order.\n    ///\n    ///  * Fails if the buffer is read-only.\n    ///  * Fails if the slice does not have the correct length (`buf.item_count()`).\n    ///  * Fails if the buffer format is not compatible with type `T`.\n    ///\n    /// To check whether the buffer format is compatible before calling this method,\n    /// use `<T as buffer::Element>::is_compatible_format(buf.format())`.\n    /// Alternatively, `match buffer::ElementType::from_format(buf.format())`.\n    pub fn copy_from_slice(&self, py: Python<'_>, source: &[T]) -> PyResult<()> {\n        self._copy_from_slice(py, source, b'C')\n    }\n\n    /// Copies the specified slice into the buffer.\n    /// If the buffer is multi-dimensional, the elements in the slice are expected to be in Fortran-style order.\n    ///\n    ///  * Fails if the buffer is read-only.\n    ///  * Fails if the slice does not have the correct length (`buf.item_count()`).\n    ///  * Fails if the buffer format is not compatible with type `T`.\n    ///\n    /// To check whether the buffer format is compatible before calling this method,\n    /// use `<T as buffer::Element>::is_compatible_format(buf.format())`.\n    /// Alternatively, `match buffer::ElementType::from_format(buf.format())`.\n    pub fn copy_from_fortran_slice(&self, py: Python<'_>, source: &[T]) -> PyResult<()> {\n        self._copy_from_slice(py, source, b'F')\n    }\n\n    fn _copy_from_slice(&self, py: Python<'_>, source: &[T], fort: u8) -> PyResult<()> {\n        if self.readonly() {\n            return Err(PyBufferError::new_err(\"cannot write to read-only buffer\"));\n        } else if mem::size_of_val(source) != self.len_bytes() {\n            return Err(PyBufferError::new_err(format!(\n                \"slice to copy from (of length {}) does not match buffer length of {}\",\n                source.len(),\n                self.item_count()\n            )));\n        }\n\n        err::error_on_minusone(py, unsafe {\n            ffi::PyBuffer_FromContiguous(\n                #[cfg(Py_3_11)]\n                self.raw(),\n                #[cfg(not(Py_3_11))]\n                ptr::from_ref(self.raw()).cast_mut(),\n                #[cfg(Py_3_11)]\n                {\n                    source.as_ptr().cast()\n                },\n                #[cfg(not(Py_3_11))]\n                {\n                    source.as_ptr().cast::<c_void>().cast_mut()\n                },\n                self.raw().len,\n                fort as std::ffi::c_char,\n            )\n        })\n    }\n}\n\nimpl<T> std::ops::Deref for PyBuffer<T> {\n    type Target = PyUntypedBuffer;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl PyUntypedBuffer {\n    /// Gets the underlying buffer from the specified python object.\n    pub fn get(obj: &Bound<'_, PyAny>) -> PyResult<Self> {\n        let buf = {\n            let mut buf = Box::<RawBuffer>::new_uninit();\n            // SAFETY: RawBuffer is `#[repr(transparent)]` around FFI struct\n            err::error_on_minusone(obj.py(), unsafe {\n                ffi::PyObject_GetBuffer(\n                    obj.as_ptr(),\n                    buf.as_mut_ptr().cast::<ffi::Py_buffer>(),\n                    ffi::PyBUF_FULL_RO,\n                )\n            })?;\n            // Safety: buf is initialized by PyObject_GetBuffer.\n            unsafe { buf.assume_init() }\n        };\n        // Create PyBuffer immediately so that if validation checks fail, the PyBuffer::drop code\n        // will call PyBuffer_Release (thus avoiding any leaks).\n        let buf = Self(Pin::from(buf));\n        let raw = buf.raw();\n\n        if raw.shape.is_null() {\n            Err(PyBufferError::new_err(\"shape is null\"))\n        } else if raw.strides.is_null() {\n            Err(PyBufferError::new_err(\"strides is null\"))\n        } else {\n            Ok(buf)\n        }\n    }\n\n    /// Returns a `[PyBuffer]` instance if the buffer can be interpreted as containing elements of type `T`.\n    pub fn into_typed<T: Element>(self) -> PyResult<PyBuffer<T>> {\n        self.ensure_compatible_with::<T>()?;\n        Ok(PyBuffer(self, PhantomData))\n    }\n\n    /// Non-owning equivalent of [`into_typed()`][Self::into_typed].\n    pub fn as_typed<T: Element>(&self) -> PyResult<&PyBuffer<T>> {\n        self.ensure_compatible_with::<T>()?;\n        // SAFETY: PyBuffer<T> is repr(transparent) around PyUntypedBuffer\n        Ok(unsafe { NonNull::from(self).cast::<PyBuffer<T>>().as_ref() })\n    }\n\n    fn ensure_compatible_with<T: Element>(&self) -> PyResult<()> {\n        if mem::size_of::<T>() != self.item_size() || !T::is_compatible_format(self.format()) {\n            Err(PyBufferError::new_err(format!(\n                \"buffer contents are not compatible with {}\",\n                std::any::type_name::<T>()\n            )))\n        } else if self.raw().buf.align_offset(mem::align_of::<T>()) != 0 {\n            Err(PyBufferError::new_err(format!(\n                \"buffer contents are insufficiently aligned for {}\",\n                std::any::type_name::<T>()\n            )))\n        } else {\n            Ok(())\n        }\n    }\n\n    /// Releases the buffer object, freeing the reference to the Python object\n    /// which owns the buffer.\n    ///\n    /// This will automatically be called on drop.\n    pub fn release(self, _py: Python<'_>) {\n        // First move self into a ManuallyDrop, so that PyBuffer::drop will\n        // never be called. (It would attach to the interpreter and call PyBuffer_Release\n        // again.)\n        let mut mdself = mem::ManuallyDrop::new(self);\n        unsafe {\n            // Next, make the actual PyBuffer_Release call.\n            // Fine to get a mutable reference to the inner ffi::Py_buffer here, as we're destroying it.\n            mdself.0.release();\n\n            // Finally, drop the contained Pin<Box<_>> in place, to free the\n            // Box memory.\n            ptr::drop_in_place::<Pin<Box<RawBuffer>>>(&mut mdself.0);\n        }\n    }\n\n    /// Gets the pointer to the start of the buffer memory.\n    ///\n    /// Warning: the buffer memory can be mutated by other code (including\n    /// other Python functions, if the GIL is released, or other extension\n    /// modules even if the GIL is held). You must either access memory\n    /// atomically, or ensure there are no data races yourself. See\n    /// [this blog post] for more details.\n    ///\n    /// [this blog post]: https://alexgaynor.net/2022/oct/23/buffers-on-the-edge/\n    #[inline]\n    pub fn buf_ptr(&self) -> *mut c_void {\n        self.raw().buf\n    }\n\n    /// Gets a pointer to the specified item.\n    ///\n    /// If `indices.len() < self.dimensions()`, returns the start address of the sub-array at the specified dimension.\n    pub fn get_ptr(&self, indices: &[usize]) -> *mut c_void {\n        let shape = &self.shape()[..indices.len()];\n        for i in 0..indices.len() {\n            assert!(indices[i] < shape[i]);\n        }\n        unsafe {\n            ffi::PyBuffer_GetPointer(\n                #[cfg(Py_3_11)]\n                self.raw(),\n                #[cfg(not(Py_3_11))]\n                ptr::from_ref(self.raw()).cast_mut(),\n                #[cfg(Py_3_11)]\n                indices.as_ptr().cast(),\n                #[cfg(not(Py_3_11))]\n                indices.as_ptr().cast_mut().cast(),\n            )\n        }\n    }\n\n    /// Gets whether the underlying buffer is read-only.\n    #[inline]\n    pub fn readonly(&self) -> bool {\n        self.raw().readonly != 0\n    }\n\n    /// Gets the size of a single element, in bytes.\n    /// Important exception: when requesting an unformatted buffer, item_size still has the value\n    #[inline]\n    pub fn item_size(&self) -> usize {\n        self.raw().itemsize as usize\n    }\n\n    /// Gets the total number of items.\n    #[inline]\n    pub fn item_count(&self) -> usize {\n        (self.raw().len as usize) / (self.raw().itemsize as usize)\n    }\n\n    /// `item_size() * item_count()`.\n    /// For contiguous arrays, this is the length of the underlying memory block.\n    /// For non-contiguous arrays, it is the length that the logical structure would have if it were copied to a contiguous representation.\n    #[inline]\n    pub fn len_bytes(&self) -> usize {\n        self.raw().len as usize\n    }\n\n    /// Gets the number of dimensions.\n    ///\n    /// May be 0 to indicate a single scalar value.\n    #[inline]\n    pub fn dimensions(&self) -> usize {\n        self.raw().ndim as usize\n    }\n\n    /// Returns an array of length `dimensions`. `shape()[i]` is the length of the array in dimension number `i`.\n    ///\n    /// May return None for single-dimensional arrays or scalar values (`dimensions() <= 1`);\n    /// You can call `item_count()` to get the length of the single dimension.\n    ///\n    /// Despite Python using an array of signed integers, the values are guaranteed to be non-negative.\n    /// However, dimensions of length 0 are possible and might need special attention.\n    #[inline]\n    pub fn shape(&self) -> &[usize] {\n        unsafe { slice::from_raw_parts(self.raw().shape.cast(), self.raw().ndim as usize) }\n    }\n\n    /// Returns an array that holds, for each dimension, the number of bytes to skip to get to the next element in the dimension.\n    ///\n    /// Stride values can be any integer. For regular arrays, strides are usually positive,\n    /// but a consumer MUST be able to handle the case `strides[n] <= 0`.\n    #[inline]\n    pub fn strides(&self) -> &[isize] {\n        unsafe { slice::from_raw_parts(self.raw().strides, self.raw().ndim as usize) }\n    }\n\n    /// An array of length ndim.\n    /// If `suboffsets[n] >= 0`, the values stored along the nth dimension are pointers and the suboffset value dictates how many bytes to add to each pointer after de-referencing.\n    /// A suboffset value that is negative indicates that no de-referencing should occur (striding in a contiguous memory block).\n    ///\n    /// If all suboffsets are negative (i.e. no de-referencing is needed), then this field must be NULL (the default value).\n    #[inline]\n    pub fn suboffsets(&self) -> Option<&[isize]> {\n        unsafe {\n            if self.raw().suboffsets.is_null() {\n                None\n            } else {\n                Some(slice::from_raw_parts(\n                    self.raw().suboffsets,\n                    self.raw().ndim as usize,\n                ))\n            }\n        }\n    }\n\n    /// A string in struct module style syntax describing the contents of a single item.\n    #[inline]\n    pub fn format(&self) -> &CStr {\n        if self.raw().format.is_null() {\n            ffi::c_str!(\"B\")\n        } else {\n            unsafe { CStr::from_ptr(self.raw().format) }\n        }\n    }\n\n    /// Gets whether the buffer is contiguous in C-style order (last index varies fastest when visiting items in order of memory address).\n    #[inline]\n    pub fn is_c_contiguous(&self) -> bool {\n        unsafe { ffi::PyBuffer_IsContiguous(self.raw(), b'C' as std::ffi::c_char) != 0 }\n    }\n\n    /// Gets whether the buffer is contiguous in Fortran-style order (first index varies fastest when visiting items in order of memory address).\n    #[inline]\n    pub fn is_fortran_contiguous(&self) -> bool {\n        unsafe { ffi::PyBuffer_IsContiguous(self.raw(), b'F' as std::ffi::c_char) != 0 }\n    }\n\n    fn raw(&self) -> &ffi::Py_buffer {\n        &self.0 .0\n    }\n}\n\nimpl RawBuffer {\n    /// Release the contents of this pinned buffer.\n    ///\n    /// # Safety\n    ///\n    /// - The buffer must not be used after calling this function.\n    /// - This function can only be called once.\n    /// - Must be attached to the interpreter.\n    ///\n    unsafe fn release(self: &mut Pin<Box<Self>>) {\n        unsafe {\n            ffi::PyBuffer_Release(&mut Pin::get_unchecked_mut(self.as_mut()).0);\n        }\n    }\n}\n\nimpl Drop for PyUntypedBuffer {\n    fn drop(&mut self) {\n        if Python::try_attach(|_| unsafe { self.0.release() }).is_none()\n            && crate::internal::state::is_in_gc_traversal()\n        {\n            eprintln!(\"Warning: PyBuffer dropped while in GC traversal, this is a bug and will leak memory.\");\n        }\n        // If `try_attach` failed and `is_in_gc_traversal()` is false, then probably the interpreter has\n        // already finalized and we can just assume that the underlying memory has already been freed.\n        //\n        // So we don't handle that case here.\n    }\n}\n\n/// Like [std::cell::Cell], but only provides read-only access to the data.\n///\n/// `&ReadOnlyCell<T>` is basically a safe version of `*const T`:\n///  The data cannot be modified through the reference, but other references may\n///  be modifying the data.\n#[repr(transparent)]\npub struct ReadOnlyCell<T: Element>(cell::UnsafeCell<T>);\n\nimpl<T: Element> ReadOnlyCell<T> {\n    /// Returns a copy of the current value.\n    #[inline]\n    pub fn get(&self) -> T {\n        unsafe { *self.0.get() }\n    }\n\n    /// Returns a pointer to the current value.\n    #[inline]\n    pub fn as_ptr(&self) -> *const T {\n        self.0.get()\n    }\n}\n\nmacro_rules! impl_element(\n    ($t:ty, $f:ident) => {\n        unsafe impl Element for $t {\n            fn is_compatible_format(format: &CStr) -> bool {\n                let slice = format.to_bytes();\n                if slice.len() > 1 && !is_matching_endian(slice[0]) {\n                    return false;\n                }\n                ElementType::from_format(format) == ElementType::$f { bytes: mem::size_of::<$t>() }\n            }\n        }\n    }\n);\n\nimpl_element!(u8, UnsignedInteger);\nimpl_element!(u16, UnsignedInteger);\nimpl_element!(u32, UnsignedInteger);\nimpl_element!(u64, UnsignedInteger);\nimpl_element!(usize, UnsignedInteger);\nimpl_element!(i8, SignedInteger);\nimpl_element!(i16, SignedInteger);\nimpl_element!(i32, SignedInteger);\nimpl_element!(i64, SignedInteger);\nimpl_element!(isize, SignedInteger);\nimpl_element!(f32, Float);\nimpl_element!(f64, Float);\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    use crate::ffi;\n    use crate::types::any::PyAnyMethods;\n    use crate::types::PyBytes;\n    use crate::Python;\n\n    #[test]\n    fn test_debug() {\n        Python::attach(|py| {\n            let bytes = PyBytes::new(py, b\"abcde\");\n            let buffer: PyBuffer<u8> = PyBuffer::get(&bytes).unwrap();\n            let expected = format!(\n                concat!(\n                    \"PyBuffer {{ buf: {:?}, obj: {:?}, \",\n                    \"len: 5, itemsize: 1, readonly: 1, \",\n                    \"ndim: 1, format: \\\"B\\\", shape: [5], \",\n                    \"strides: [1], suboffsets: None, internal: {:?} }}\",\n                ),\n                buffer.raw().buf,\n                buffer.raw().obj,\n                buffer.raw().internal\n            );\n            let debug_repr = format!(\"{:?}\", buffer);\n            assert_eq!(debug_repr, expected);\n        });\n    }\n\n    #[test]\n    fn test_element_type_from_format() {\n        use super::ElementType::*;\n        use std::mem::size_of;\n\n        for (cstr, expected) in [\n            // @ prefix goes to native_element_type_from_type_char\n            (\n                c\"@b\",\n                SignedInteger {\n                    bytes: size_of::<c_schar>(),\n                },\n            ),\n            (\n                c\"@c\",\n                UnsignedInteger {\n                    bytes: size_of::<c_char>(),\n                },\n            ),\n            (\n                c\"@b\",\n                SignedInteger {\n                    bytes: size_of::<c_schar>(),\n                },\n            ),\n            (\n                c\"@B\",\n                UnsignedInteger {\n                    bytes: size_of::<c_uchar>(),\n                },\n            ),\n            (c\"@?\", Bool),\n            (\n                c\"@h\",\n                SignedInteger {\n                    bytes: size_of::<c_short>(),\n                },\n            ),\n            (\n                c\"@H\",\n                UnsignedInteger {\n                    bytes: size_of::<c_ushort>(),\n                },\n            ),\n            (\n                c\"@i\",\n                SignedInteger {\n                    bytes: size_of::<c_int>(),\n                },\n            ),\n            (\n                c\"@I\",\n                UnsignedInteger {\n                    bytes: size_of::<c_uint>(),\n                },\n            ),\n            (\n                c\"@l\",\n                SignedInteger {\n                    bytes: size_of::<c_long>(),\n                },\n            ),\n            (\n                c\"@L\",\n                UnsignedInteger {\n                    bytes: size_of::<c_ulong>(),\n                },\n            ),\n            (\n                c\"@q\",\n                SignedInteger {\n                    bytes: size_of::<c_longlong>(),\n                },\n            ),\n            (\n                c\"@Q\",\n                UnsignedInteger {\n                    bytes: size_of::<c_ulonglong>(),\n                },\n            ),\n            (\n                c\"@n\",\n                SignedInteger {\n                    bytes: size_of::<libc::ssize_t>(),\n                },\n            ),\n            (\n                c\"@N\",\n                UnsignedInteger {\n                    bytes: size_of::<libc::size_t>(),\n                },\n            ),\n            (c\"@e\", Float { bytes: 2 }),\n            (c\"@f\", Float { bytes: 4 }),\n            (c\"@d\", Float { bytes: 8 }),\n            (c\"@z\", Unknown),\n            // = prefix goes to standard_element_type_from_type_char\n            (c\"=b\", SignedInteger { bytes: 1 }),\n            (c\"=c\", UnsignedInteger { bytes: 1 }),\n            (c\"=B\", UnsignedInteger { bytes: 1 }),\n            (c\"=?\", Bool),\n            (c\"=h\", SignedInteger { bytes: 2 }),\n            (c\"=H\", UnsignedInteger { bytes: 2 }),\n            (c\"=l\", SignedInteger { bytes: 4 }),\n            (c\"=l\", SignedInteger { bytes: 4 }),\n            (c\"=I\", UnsignedInteger { bytes: 4 }),\n            (c\"=L\", UnsignedInteger { bytes: 4 }),\n            (c\"=q\", SignedInteger { bytes: 8 }),\n            (c\"=Q\", UnsignedInteger { bytes: 8 }),\n            (c\"=e\", Float { bytes: 2 }),\n            (c\"=f\", Float { bytes: 4 }),\n            (c\"=d\", Float { bytes: 8 }),\n            (c\"=z\", Unknown),\n            (c\"=0\", Unknown),\n            // unknown prefix -> Unknown\n            (c\":b\", Unknown),\n        ] {\n            assert_eq!(\n                ElementType::from_format(cstr),\n                expected,\n                \"element from format &Cstr: {cstr:?}\",\n            );\n        }\n    }\n\n    #[test]\n    fn test_compatible_size() {\n        // for the cast in PyBuffer::shape()\n        assert_eq!(\n            std::mem::size_of::<ffi::Py_ssize_t>(),\n            std::mem::size_of::<usize>()\n        );\n    }\n\n    #[test]\n    fn test_bytes_buffer() {\n        Python::attach(|py| {\n            let bytes = PyBytes::new(py, b\"abcde\");\n            let buffer = PyBuffer::get(&bytes).unwrap();\n            assert_eq!(buffer.dimensions(), 1);\n            assert_eq!(buffer.item_count(), 5);\n            assert_eq!(buffer.format().to_str().unwrap(), \"B\");\n            assert_eq!(buffer.shape(), [5]);\n            // single-dimensional buffer is always contiguous\n            assert!(buffer.is_c_contiguous());\n            assert!(buffer.is_fortran_contiguous());\n\n            let slice = buffer.as_slice(py).unwrap();\n            assert_eq!(slice.len(), 5);\n            assert_eq!(slice[0].get(), b'a');\n            assert_eq!(slice[2].get(), b'c');\n\n            assert_eq!(unsafe { *(buffer.get_ptr(&[1]).cast::<u8>()) }, b'b');\n\n            assert!(buffer.as_mut_slice(py).is_none());\n\n            assert!(buffer.copy_to_slice(py, &mut [0u8]).is_err());\n            let mut arr = [0; 5];\n            buffer.copy_to_slice(py, &mut arr).unwrap();\n            assert_eq!(arr, b\"abcde\" as &[u8]);\n\n            assert!(buffer.copy_from_slice(py, &[0u8; 5]).is_err());\n            assert_eq!(buffer.to_vec(py).unwrap(), b\"abcde\");\n        });\n    }\n\n    #[test]\n    fn test_array_buffer() {\n        Python::attach(|py| {\n            let array = py\n                .import(\"array\")\n                .unwrap()\n                .call_method(\"array\", (\"f\", (1.0, 1.5, 2.0, 2.5)), None)\n                .unwrap();\n            let buffer = PyBuffer::get(&array).unwrap();\n            assert_eq!(buffer.dimensions(), 1);\n            assert_eq!(buffer.item_count(), 4);\n            assert_eq!(buffer.format().to_str().unwrap(), \"f\");\n            assert_eq!(buffer.shape(), [4]);\n\n            // array creates a 1D contiguous buffer, so it's both C and F contiguous.  This would\n            // be more interesting if we can come up with a 2D buffer but I think it would need a\n            // third-party lib or a custom class.\n\n            // C-contiguous fns\n            let slice = buffer.as_slice(py).unwrap();\n            assert_eq!(slice.len(), 4);\n            assert_eq!(slice[0].get(), 1.0);\n            assert_eq!(slice[3].get(), 2.5);\n\n            let mut_slice = buffer.as_mut_slice(py).unwrap();\n            assert_eq!(mut_slice.len(), 4);\n            assert_eq!(mut_slice[0].get(), 1.0);\n            mut_slice[3].set(2.75);\n            assert_eq!(slice[3].get(), 2.75);\n\n            buffer\n                .copy_from_slice(py, &[10.0f32, 11.0, 12.0, 13.0])\n                .unwrap();\n            assert_eq!(slice[2].get(), 12.0);\n\n            assert_eq!(buffer.to_vec(py).unwrap(), [10.0, 11.0, 12.0, 13.0]);\n\n            // F-contiguous fns\n            let buffer = PyBuffer::get(&array).unwrap();\n            let slice = buffer.as_fortran_slice(py).unwrap();\n            assert_eq!(slice.len(), 4);\n            assert_eq!(slice[1].get(), 11.0);\n\n            let mut_slice = buffer.as_fortran_mut_slice(py).unwrap();\n            assert_eq!(mut_slice.len(), 4);\n            assert_eq!(mut_slice[2].get(), 12.0);\n            mut_slice[3].set(2.75);\n            assert_eq!(slice[3].get(), 2.75);\n\n            buffer\n                .copy_from_fortran_slice(py, &[10.0f32, 11.0, 12.0, 13.0])\n                .unwrap();\n            assert_eq!(slice[2].get(), 12.0);\n\n            assert_eq!(buffer.to_fortran_vec(py).unwrap(), [10.0, 11.0, 12.0, 13.0]);\n        });\n    }\n\n    #[test]\n    fn test_untyped_buffer() {\n        Python::attach(|py| {\n            let bytes = PyBytes::new(py, b\"abcde\");\n            let untyped = PyUntypedBuffer::get(&bytes).unwrap();\n            assert_eq!(untyped.dimensions(), 1);\n            assert_eq!(untyped.item_count(), 5);\n            assert_eq!(untyped.format().to_str().unwrap(), \"B\");\n            assert_eq!(untyped.shape(), [5]);\n\n            let typed: &PyBuffer<u8> = untyped.as_typed().unwrap();\n            assert_eq!(typed.dimensions(), 1);\n            assert_eq!(typed.item_count(), 5);\n            assert_eq!(typed.format().to_str().unwrap(), \"B\");\n            assert_eq!(typed.shape(), [5]);\n        });\n    }\n}\n"
  },
  {
    "path": "src/byteswriter.rs",
    "content": "#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::PyTypeInfo;\n#[cfg(not(Py_LIMITED_API))]\nuse crate::{\n    err::error_on_minusone,\n    ffi::{\n        self,\n        compat::{\n            PyBytesWriter_Create, PyBytesWriter_Discard, PyBytesWriter_Finish,\n            PyBytesWriter_GetData, PyBytesWriter_GetSize, PyBytesWriter_Resize,\n        },\n    },\n    ffi_ptr_ext::FfiPtrExt,\n    py_result_ext::PyResultExt,\n};\nuse crate::{types::PyBytes, Bound, IntoPyObject, PyErr, PyResult, Python};\nuse std::io::IoSlice;\n#[cfg(not(Py_LIMITED_API))]\nuse std::{\n    mem::ManuallyDrop,\n    ptr::{self, NonNull},\n};\n\npub struct PyBytesWriter<'py> {\n    python: Python<'py>,\n    #[cfg(not(Py_LIMITED_API))]\n    writer: NonNull<ffi::compat::PyBytesWriter>,\n    #[cfg(Py_LIMITED_API)]\n    buffer: Vec<u8>,\n}\n\nimpl<'py> PyBytesWriter<'py> {\n    /// Create a new `PyBytesWriter` with a default initial capacity.\n    #[inline]\n    pub fn new(py: Python<'py>) -> PyResult<Self> {\n        Self::with_capacity(py, 0)\n    }\n\n    /// Create a new `PyBytesWriter` with the specified initial capacity.\n    #[inline]\n    #[cfg_attr(Py_LIMITED_API, allow(clippy::unnecessary_wraps))]\n    pub fn with_capacity(py: Python<'py>, capacity: usize) -> PyResult<Self> {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            NonNull::new(unsafe { PyBytesWriter_Create(capacity as _) }).map_or_else(\n                || Err(PyErr::fetch(py)),\n                |writer| {\n                    let mut writer = PyBytesWriter { python: py, writer };\n                    if capacity > 0 {\n                        // SAFETY: By setting the length to 0, we ensure no bytes are considered uninitialized.\n                        unsafe { writer.set_len(0)? };\n                    }\n                    Ok(writer)\n                },\n            )\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        {\n            Ok(PyBytesWriter {\n                python: py,\n                buffer: Vec::with_capacity(capacity),\n            })\n        }\n    }\n\n    /// Get the current length of the internal buffer.\n    #[inline]\n    pub fn len(&self) -> usize {\n        #[cfg(not(Py_LIMITED_API))]\n        unsafe {\n            PyBytesWriter_GetSize(self.writer.as_ptr()) as _\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        {\n            self.buffer.len()\n        }\n    }\n\n    #[inline]\n    #[cfg(not(Py_LIMITED_API))]\n    fn as_mut_ptr(&mut self) -> *mut u8 {\n        unsafe { PyBytesWriter_GetData(self.writer.as_ptr()) as _ }\n    }\n\n    /// Set the length of the internal buffer to `new_len`. The new bytes are uninitialized.\n    ///\n    /// # Safety\n    /// The caller must ensure the new bytes are initialized.\n    #[inline]\n    #[cfg(not(Py_LIMITED_API))]\n    unsafe fn set_len(&mut self, new_len: usize) -> PyResult<()> {\n        unsafe {\n            error_on_minusone(\n                self.python,\n                PyBytesWriter_Resize(self.writer.as_ptr(), new_len as _),\n            )\n        }\n    }\n}\n\nimpl<'py> TryFrom<PyBytesWriter<'py>> for Bound<'py, PyBytes> {\n    type Error = PyErr;\n\n    #[inline]\n    fn try_from(value: PyBytesWriter<'py>) -> Result<Self, Self::Error> {\n        let py = value.python;\n\n        #[cfg(not(Py_LIMITED_API))]\n        unsafe {\n            PyBytesWriter_Finish(ManuallyDrop::new(value).writer.as_ptr())\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        {\n            Ok(PyBytes::new(py, &value.buffer))\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for PyBytesWriter<'py> {\n    type Target = PyBytes;\n    type Output = Bound<'py, PyBytes>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyBytes::TYPE_HINT;\n\n    #[inline]\n    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.try_into()\n    }\n}\n\n#[cfg(not(Py_LIMITED_API))]\nimpl<'py> Drop for PyBytesWriter<'py> {\n    #[inline]\n    fn drop(&mut self) {\n        unsafe { PyBytesWriter_Discard(self.writer.as_ptr()) }\n    }\n}\n\n#[cfg(not(Py_LIMITED_API))]\nimpl std::io::Write for PyBytesWriter<'_> {\n    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {\n        self.write_all(buf)?;\n        Ok(buf.len())\n    }\n\n    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> std::io::Result<usize> {\n        let len = bufs.iter().map(|b| b.len()).sum();\n        // SAFETY: We ensure enough capacity below.\n        let mut pos = unsafe { self.as_mut_ptr().add(self.len()) };\n\n        // SAFETY: We write the new uninitialized bytes below.\n        unsafe { self.set_len(self.len() + len)? }\n\n        for buf in bufs {\n            // SAFETY: We have ensured enough capacity above.\n            unsafe { ptr::copy_nonoverlapping(buf.as_ptr(), pos, buf.len()) };\n\n            // SAFETY: We just wrote buf.len() bytes\n            pos = unsafe { pos.add(buf.len()) };\n        }\n        Ok(len)\n    }\n\n    fn flush(&mut self) -> std::io::Result<()> {\n        Ok(())\n    }\n\n    fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {\n        let len = buf.len();\n        let pos = self.len();\n\n        // SAFETY: We write the new uninitialized bytes below.\n        unsafe { self.set_len(pos + len)? }\n\n        // SAFETY: We have ensured enough capacity above.\n        unsafe { ptr::copy_nonoverlapping(buf.as_ptr(), self.as_mut_ptr().add(pos), len) };\n\n        Ok(())\n    }\n}\n\n#[cfg(Py_LIMITED_API)]\nimpl std::io::Write for PyBytesWriter<'_> {\n    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {\n        self.buffer.write(buf)\n    }\n\n    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> std::io::Result<usize> {\n        self.buffer.write_vectored(bufs)\n    }\n\n    fn flush(&mut self) -> std::io::Result<()> {\n        self.buffer.flush()\n    }\n\n    fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {\n        self.buffer.write_all(buf)\n    }\n\n    fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::io::Result<()> {\n        self.buffer.write_fmt(args)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::PyBytesMethods;\n    use std::io::Write;\n\n    #[test]\n    fn test_io_write() {\n        Python::attach(|py| {\n            let buf = b\"hallo world\";\n            let mut writer = PyBytesWriter::new(py).unwrap();\n            assert_eq!(writer.write(buf).unwrap(), 11);\n            let bytes: Bound<'_, PyBytes> = writer.try_into().unwrap();\n            assert_eq!(bytes.as_bytes(), buf);\n        })\n    }\n\n    #[test]\n    fn test_pre_allocated() {\n        Python::attach(|py| {\n            let buf = b\"hallo world\";\n            let mut writer = PyBytesWriter::with_capacity(py, buf.len()).unwrap();\n            assert_eq!(writer.len(), 0, \"Writer position should be zero\");\n            assert_eq!(writer.write(buf).unwrap(), 11);\n            let bytes: Bound<'_, PyBytes> = writer.try_into().unwrap();\n            assert_eq!(bytes.as_bytes(), buf);\n        })\n    }\n\n    #[test]\n    fn test_io_write_vectored() {\n        Python::attach(|py| {\n            let bufs = [IoSlice::new(b\"hallo \"), IoSlice::new(b\"world\")];\n            let mut writer = PyBytesWriter::new(py).unwrap();\n            assert_eq!(writer.write_vectored(&bufs).unwrap(), 11);\n            let bytes: Bound<'_, PyBytes> = writer.try_into().unwrap();\n            assert_eq!(bytes.as_bytes(), b\"hallo world\");\n        })\n    }\n\n    #[test]\n    fn test_large_data() {\n        Python::attach(|py| {\n            let mut writer = PyBytesWriter::new(py).unwrap();\n            let large_data = vec![0; 1024]; // 1 KB\n            writer.write_all(&large_data).unwrap();\n            let bytes: Bound<'_, PyBytes> = writer.try_into().unwrap();\n            assert_eq!(bytes.as_bytes(), large_data.as_slice());\n        })\n    }\n}\n"
  },
  {
    "path": "src/call.rs",
    "content": "//! Defines how Python calls are dispatched, see [`PyCallArgs`].for more information.\r\n\r\nuse crate::ffi_ptr_ext::FfiPtrExt as _;\r\nuse crate::types::{PyAnyMethods as _, PyDict, PyString, PyTuple};\r\nuse crate::{ffi, Borrowed, Bound, IntoPyObjectExt as _, Py, PyAny, PyResult};\r\n\r\npub(crate) mod private {\r\n    use super::*;\r\n\r\n    pub trait Sealed {}\r\n\r\n    impl Sealed for () {}\r\n    impl Sealed for Bound<'_, PyTuple> {}\r\n    impl Sealed for &'_ Bound<'_, PyTuple> {}\r\n    impl Sealed for Py<PyTuple> {}\r\n    impl Sealed for &'_ Py<PyTuple> {}\r\n    impl Sealed for Borrowed<'_, '_, PyTuple> {}\r\n    pub struct Token;\r\n}\r\n\r\n/// This trait marks types that can be used as arguments to Python function\r\n/// calls.\r\n///\r\n/// This trait is currently implemented for Rust tuple (up to a size of 12),\r\n/// [`Bound<'py, PyTuple>`] and [`Py<PyTuple>`]. Custom types that are\r\n/// convertible to `PyTuple` via `IntoPyObject` need to do so before passing it\r\n/// to `call`.\r\n///\r\n/// This trait is not intended to used by downstream crates directly. As such it\r\n/// has no publicly available methods and cannot be implemented outside of\r\n/// `pyo3`. The corresponding public API is available through [`call`]\r\n/// ([`call0`], [`call1`] and friends) on [`PyAnyMethods`].\r\n///\r\n/// # What is `PyCallArgs` used for?\r\n/// `PyCallArgs` is used internally in `pyo3` to dispatch the Python calls in\r\n/// the most optimal way for the current build configuration. Certain types,\r\n/// such as Rust tuples, do allow the usage of a faster calling convention of\r\n/// the Python interpreter (if available). More types that may take advantage\r\n/// from this may be added in the future.\r\n///\r\n/// [`call0`]: crate::types::PyAnyMethods::call0\r\n/// [`call1`]: crate::types::PyAnyMethods::call1\r\n/// [`call`]: crate::types::PyAnyMethods::call\r\n/// [`PyAnyMethods`]: crate::types::PyAnyMethods\r\n#[diagnostic::on_unimplemented(\r\n    message = \"`{Self}` cannot used as a Python `call` argument\",\r\n    note = \"`PyCallArgs` is implemented for Rust tuples, `Bound<'py, PyTuple>` and `Py<PyTuple>`\",\r\n    note = \"if your type is convertible to `PyTuple` via `IntoPyObject`, call `<arg>.into_pyobject(py)` manually\",\r\n    note = \"if you meant to pass the type as a single argument, wrap it in a 1-tuple, `(<arg>,)`\"\r\n)]\r\npub trait PyCallArgs<'py>: Sized + private::Sealed {\r\n    #[doc(hidden)]\r\n    fn call(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        kwargs: Borrowed<'_, 'py, PyDict>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>>;\r\n\r\n    #[doc(hidden)]\r\n    fn call_positional(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>>;\r\n\r\n    #[doc(hidden)]\r\n    fn call_method_positional(\r\n        self,\r\n        object: Borrowed<'_, 'py, PyAny>,\r\n        method_name: Borrowed<'_, 'py, PyString>,\r\n        _: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        object\r\n            .getattr(method_name)\r\n            .and_then(|method| method.call1(self))\r\n    }\r\n}\r\n\r\nimpl<'py> PyCallArgs<'py> for () {\r\n    fn call(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        kwargs: Borrowed<'_, 'py, PyDict>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        let args = self.into_pyobject_or_pyerr(function.py())?;\r\n        args.call(function, kwargs, token)\r\n    }\r\n\r\n    fn call_positional(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        let args = self.into_pyobject_or_pyerr(function.py())?;\r\n        args.call_positional(function, token)\r\n    }\r\n}\r\n\r\nimpl<'py> PyCallArgs<'py> for Bound<'py, PyTuple> {\r\n    #[inline]\r\n    fn call(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        kwargs: Borrowed<'_, 'py, PyDict>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        self.as_borrowed().call(function, kwargs, token)\r\n    }\r\n\r\n    #[inline]\r\n    fn call_positional(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        self.as_borrowed().call_positional(function, token)\r\n    }\r\n}\r\n\r\nimpl<'py> PyCallArgs<'py> for &'_ Bound<'py, PyTuple> {\r\n    #[inline]\r\n    fn call(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        kwargs: Borrowed<'_, 'py, PyDict>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        self.as_borrowed().call(function, kwargs, token)\r\n    }\r\n\r\n    #[inline]\r\n    fn call_positional(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        self.as_borrowed().call_positional(function, token)\r\n    }\r\n}\r\n\r\nimpl<'py> PyCallArgs<'py> for Py<PyTuple> {\r\n    #[inline]\r\n    fn call(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        kwargs: Borrowed<'_, 'py, PyDict>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        self.bind_borrowed(function.py())\r\n            .call(function, kwargs, token)\r\n    }\r\n\r\n    #[inline]\r\n    fn call_positional(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        self.bind_borrowed(function.py())\r\n            .call_positional(function, token)\r\n    }\r\n}\r\n\r\nimpl<'py> PyCallArgs<'py> for &'_ Py<PyTuple> {\r\n    #[inline]\r\n    fn call(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        kwargs: Borrowed<'_, 'py, PyDict>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        self.bind_borrowed(function.py())\r\n            .call(function, kwargs, token)\r\n    }\r\n\r\n    #[inline]\r\n    fn call_positional(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        token: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        self.bind_borrowed(function.py())\r\n            .call_positional(function, token)\r\n    }\r\n}\r\n\r\nimpl<'py> PyCallArgs<'py> for Borrowed<'_, 'py, PyTuple> {\r\n    #[inline]\r\n    fn call(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        kwargs: Borrowed<'_, 'py, PyDict>,\r\n        _: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        unsafe {\r\n            ffi::PyObject_Call(function.as_ptr(), self.as_ptr(), kwargs.as_ptr())\r\n                .assume_owned_or_err(function.py())\r\n        }\r\n    }\r\n\r\n    #[inline]\r\n    fn call_positional(\r\n        self,\r\n        function: Borrowed<'_, 'py, PyAny>,\r\n        _: private::Token,\r\n    ) -> PyResult<Bound<'py, PyAny>> {\r\n        unsafe {\r\n            ffi::PyObject_Call(function.as_ptr(), self.as_ptr(), std::ptr::null_mut())\r\n                .assume_owned_or_err(function.py())\r\n        }\r\n    }\r\n}\r\n\r\n#[cfg(test)]\r\n#[cfg(feature = \"macros\")]\r\nmod tests {\r\n    use crate::{\r\n        pyfunction,\r\n        types::{PyDict, PyTuple},\r\n        Py,\r\n    };\r\n\r\n    #[pyfunction(signature = (*args, **kwargs), crate = \"crate\")]\r\n    fn args_kwargs(\r\n        args: Py<PyTuple>,\r\n        kwargs: Option<Py<PyDict>>,\r\n    ) -> (Py<PyTuple>, Option<Py<PyDict>>) {\r\n        (args, kwargs)\r\n    }\r\n\r\n    #[test]\r\n    fn test_call() {\r\n        use crate::{\r\n            types::{IntoPyDict, PyAnyMethods, PyDict, PyTuple},\r\n            wrap_pyfunction, Py, Python,\r\n        };\r\n\r\n        Python::attach(|py| {\r\n            let f = wrap_pyfunction!(args_kwargs, py).unwrap();\r\n\r\n            let args = PyTuple::new(py, [1, 2, 3]).unwrap();\r\n            let kwargs = &[(\"foo\", 1), (\"bar\", 2)].into_py_dict(py).unwrap();\r\n\r\n            macro_rules! check_call {\r\n                ($args:expr, $kwargs:expr) => {\r\n                    let (a, k): (Py<PyTuple>, Py<PyDict>) = f\r\n                        .call(args.clone(), Some(kwargs))\r\n                        .unwrap()\r\n                        .extract()\r\n                        .unwrap();\r\n                    assert!(a.is(&args));\r\n                    assert!(k.is(kwargs));\r\n                };\r\n            }\r\n\r\n            // Bound<'py, PyTuple>\r\n            check_call!(args.clone(), kwargs);\r\n\r\n            // &Bound<'py, PyTuple>\r\n            check_call!(&args, kwargs);\r\n\r\n            // Py<PyTuple>\r\n            check_call!(args.clone().unbind(), kwargs);\r\n\r\n            // &Py<PyTuple>\r\n            check_call!(&args.as_unbound(), kwargs);\r\n\r\n            // Borrowed<'_, '_, PyTuple>\r\n            check_call!(args.as_borrowed(), kwargs);\r\n        })\r\n    }\r\n\r\n    #[test]\r\n    fn test_call_positional() {\r\n        use crate::{\r\n            types::{PyAnyMethods, PyNone, PyTuple},\r\n            wrap_pyfunction, Py, Python,\r\n        };\r\n\r\n        Python::attach(|py| {\r\n            let f = wrap_pyfunction!(args_kwargs, py).unwrap();\r\n\r\n            let args = PyTuple::new(py, [1, 2, 3]).unwrap();\r\n\r\n            macro_rules! check_call {\r\n                ($args:expr, $kwargs:expr) => {\r\n                    let (a, k): (Py<PyTuple>, Py<PyNone>) =\r\n                        f.call1(args.clone()).unwrap().extract().unwrap();\r\n                    assert!(a.is(&args));\r\n                    assert!(k.is_none(py));\r\n                };\r\n            }\r\n\r\n            // Bound<'py, PyTuple>\r\n            check_call!(args.clone(), kwargs);\r\n\r\n            // &Bound<'py, PyTuple>\r\n            check_call!(&args, kwargs);\r\n\r\n            // Py<PyTuple>\r\n            check_call!(args.clone().unbind(), kwargs);\r\n\r\n            // &Py<PyTuple>\r\n            check_call!(args.as_unbound(), kwargs);\r\n\r\n            // Borrowed<'_, '_, PyTuple>\r\n            check_call!(args.as_borrowed(), kwargs);\r\n        })\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/conversion.rs",
    "content": "//! Defines conversions between Rust and Python types.\nuse crate::err::PyResult;\nuse crate::impl_::pyclass::ExtractPyClassWithClone;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_identifier, type_hint_subscript, PyStaticExpr};\nuse crate::pyclass::boolean_struct::False;\nuse crate::pyclass::{PyClassGuardError, PyClassGuardMutError};\nuse crate::types::PyList;\nuse crate::types::PyTuple;\nuse crate::{\n    Borrowed, Bound, BoundObject, Py, PyAny, PyClass, PyClassGuard, PyErr, PyRef, PyRefMut,\n    PyTypeCheck, Python,\n};\nuse std::convert::Infallible;\nuse std::marker::PhantomData;\n\n/// Defines a conversion from a Rust type to a Python object, which may fail.\n///\n/// This trait has `#[derive(IntoPyObject)]` to automatically implement it for simple types and\n/// `#[derive(IntoPyObjectRef)]` to implement the same for references.\n///\n/// It functions similarly to std's [`TryInto`] trait, but requires a [`Python<'py>`] token\n/// as an argument.\n///\n/// The [`into_pyobject`][IntoPyObject::into_pyobject] method is designed for maximum flexibility and efficiency; it\n///  - allows for a concrete Python type to be returned (the [`Target`][IntoPyObject::Target] associated type)\n///  - allows for the smart pointer containing the Python object to be either `Bound<'py, Self::Target>` or `Borrowed<'a, 'py, Self::Target>`\n///    to avoid unnecessary reference counting overhead\n///  - allows for a custom error type to be returned in the event of a conversion error to avoid\n///    unnecessarily creating a Python exception\n///\n/// # See also\n///\n/// - The [`IntoPyObjectExt`] trait, which provides convenience methods for common usages of\n///   `IntoPyObject` which erase type information and convert errors to `PyErr`.\n#[diagnostic::on_unimplemented(\n    message = \"`{Self}` cannot be converted to a Python object\",\n    note = \"`IntoPyObject` is automatically implemented by the `#[pyclass]` macro\",\n    note = \"if you do not wish to have a corresponding Python type, implement it manually\",\n    note = \"if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`\"\n)]\npub trait IntoPyObject<'py>: Sized {\n    /// The Python output type\n    type Target;\n    /// The smart pointer type to use.\n    ///\n    /// This will usually be [`Bound<'py, Target>`], but in special cases [`Borrowed<'a, 'py, Target>`] can be\n    /// used to minimize reference counting overhead.\n    type Output: BoundObject<'py, Self::Target>;\n    /// The type returned in the event of a conversion error.\n    type Error: Into<PyErr>;\n\n    /// Extracts the type hint information for this type when it appears as a return value.\n    ///\n    /// For example, `Vec<u32>` would return `List[int]`.\n    /// The default implementation returns `Any`, which is correct for any type.\n    ///\n    /// For most types, the return value for this method will be identical to that of [`FromPyObject::INPUT_TYPE`].\n    /// It may be different for some types, such as `Dict`, to allow duck-typing: functions return `Dict` but take `Mapping` as argument.\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"_typeshed\", \"Incomplete\");\n\n    /// Performs the conversion.\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error>;\n\n    /// Converts sequence of Self into a Python object. Used to specialize `Vec<u8>`, `[u8; N]`\n    /// and `SmallVec<[u8; N]>` as a sequence of bytes into a `bytes` object.\n    #[doc(hidden)]\n    fn owned_sequence_into_pyobject<I>(\n        iter: I,\n        py: Python<'py>,\n        _: private::Token,\n    ) -> Result<Bound<'py, PyAny>, PyErr>\n    where\n        I: IntoIterator<Item = Self> + AsRef<[Self]>,\n        I::IntoIter: ExactSizeIterator<Item = Self>,\n    {\n        Ok(PyList::new(py, iter)?.into_any())\n    }\n\n    /// Converts sequence of Self into a Python object. Used to specialize `&[u8]` and `Cow<[u8]>`\n    /// as a sequence of bytes into a `bytes` object.\n    #[doc(hidden)]\n    fn borrowed_sequence_into_pyobject<I>(\n        iter: I,\n        py: Python<'py>,\n        _: private::Token,\n    ) -> Result<Bound<'py, PyAny>, PyErr>\n    where\n        Self: private::Reference,\n        I: IntoIterator<Item = Self> + AsRef<[<Self as private::Reference>::BaseType]>,\n        I::IntoIter: ExactSizeIterator<Item = Self>,\n    {\n        Ok(PyList::new(py, iter)?.into_any())\n    }\n\n    /// The output type of [`IntoPyObject::owned_sequence_into_pyobject`] and [`IntoPyObject::borrowed_sequence_into_pyobject`]\n    #[cfg(feature = \"experimental-inspect\")]\n    #[doc(hidden)]\n    const SEQUENCE_OUTPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyList::TYPE_HINT, Self::OUTPUT_TYPE);\n}\n\npub(crate) mod private {\n    pub struct Token;\n\n    pub trait Reference {\n        type BaseType;\n    }\n\n    impl<T> Reference for &'_ T {\n        type BaseType = T;\n    }\n}\n\nimpl<'py, T: PyTypeCheck> IntoPyObject<'py> for Bound<'py, T> {\n    type Target = T;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self)\n    }\n}\n\nimpl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for &'a Bound<'py, T> {\n    type Target = T;\n    type Output = Borrowed<'a, 'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.as_borrowed())\n    }\n}\n\nimpl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for Borrowed<'a, 'py, T> {\n    type Target = T;\n    type Output = Borrowed<'a, 'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self)\n    }\n}\n\nimpl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for &Borrowed<'a, 'py, T> {\n    type Target = T;\n    type Output = Borrowed<'a, 'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(*self)\n    }\n}\n\nimpl<'py, T: PyTypeCheck> IntoPyObject<'py> for Py<T> {\n    type Target = T;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.into_bound(py))\n    }\n}\n\nimpl<'a, 'py, T: PyTypeCheck> IntoPyObject<'py> for &'a Py<T> {\n    type Target = T;\n    type Output = Borrowed<'a, 'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.bind_borrowed(py))\n    }\n}\n\nimpl<'a, 'py, T> IntoPyObject<'py> for &&'a T\nwhere\n    &'a T: IntoPyObject<'py>,\n{\n    type Target = <&'a T as IntoPyObject<'py>>::Target;\n    type Output = <&'a T as IntoPyObject<'py>>::Output;\n    type Error = <&'a T as IntoPyObject<'py>>::Error;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&'a T as IntoPyObject<'py>>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nmod into_pyobject_ext {\n    pub trait Sealed {}\n    impl<'py, T> Sealed for T where T: super::IntoPyObject<'py> {}\n}\n\n/// Convenience methods for common usages of [`IntoPyObject`]. Every type that implements\n/// [`IntoPyObject`] also implements this trait.\n///\n/// These methods:\n///   - Drop type information from the output, returning a `PyAny` object.\n///   - Always convert the `Error` type to `PyErr`, which may incur a performance penalty but it\n///     more convenient in contexts where the `?` operator would produce a `PyErr` anyway.\npub trait IntoPyObjectExt<'py>: IntoPyObject<'py> + into_pyobject_ext::Sealed {\n    /// Converts `self` into an owned Python object, dropping type information.\n    #[inline]\n    fn into_bound_py_any(self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {\n        match self.into_pyobject(py) {\n            Ok(obj) => Ok(obj.into_any().into_bound()),\n            Err(err) => Err(err.into()),\n        }\n    }\n\n    /// Converts `self` into an owned Python object, dropping type information and unbinding it\n    /// from the `'py` lifetime.\n    #[inline]\n    fn into_py_any(self, py: Python<'py>) -> PyResult<Py<PyAny>> {\n        match self.into_pyobject(py) {\n            Ok(obj) => Ok(obj.into_any().unbind()),\n            Err(err) => Err(err.into()),\n        }\n    }\n\n    /// Converts `self` into a Python object.\n    ///\n    /// This is equivalent to calling [`into_pyobject`][IntoPyObject::into_pyobject] followed\n    /// with `.map_err(Into::into)` to convert the error type to [`PyErr`]. This is helpful\n    /// for generic code which wants to make use of the `?` operator.\n    #[inline]\n    fn into_pyobject_or_pyerr(self, py: Python<'py>) -> PyResult<Self::Output> {\n        match self.into_pyobject(py) {\n            Ok(obj) => Ok(obj),\n            Err(err) => Err(err.into()),\n        }\n    }\n}\n\nimpl<'py, T> IntoPyObjectExt<'py> for T where T: IntoPyObject<'py> {}\n\n/// Extract a type from a Python object.\n///\n///\n/// Normal usage is through the `extract` methods on [`Bound`], [`Borrowed`] and [`Py`], which\n/// forward to this trait.\n///\n/// # Examples\n///\n/// ```rust\n/// use pyo3::prelude::*;\n/// use pyo3::types::PyString;\n///\n/// # fn main() -> PyResult<()> {\n/// Python::attach(|py| {\n///     // Calling `.extract()` on a `Bound` smart pointer\n///     let obj: Bound<'_, PyString> = PyString::new(py, \"blah\");\n///     let s: String = obj.extract()?;\n/// #   assert_eq!(s, \"blah\");\n///\n///     // Calling `.extract(py)` on a `Py` smart pointer\n///     let obj: Py<PyString> = obj.unbind();\n///     let s: String = obj.extract(py)?;\n/// #   assert_eq!(s, \"blah\");\n/// #   Ok(())\n/// })\n/// # }\n/// ```\n///\n/// Note: Depending on the Python version and implementation, some [`FromPyObject`] implementations\n/// may produce a result that borrows into the Python type. This is described by the input lifetime\n/// `'a` of `obj`.\n///\n/// Types that must not borrow from the input can use [`FromPyObjectOwned`] as a restriction. This\n/// is most often the case for collection types. See its documentation for more details.\n///\n/// # How to implement [`FromPyObject`]?\n/// ## `#[derive(FromPyObject)]`\n/// The simplest way to implement [`FromPyObject`] for a custom type is to make use of our derive\n/// macro.\n/// ```rust,no_run\n/// # #![allow(dead_code)]\n/// use pyo3::prelude::*;\n///\n/// #[derive(FromPyObject)]\n/// struct MyObject {\n///     msg: String,\n///     list: Vec<u32>\n/// }\n/// # fn main() {}\n/// ```\n/// By default this will try to extract each field from the Python object by attribute access, but\n/// this can be customized. For more information about the derive macro, its configuration as well\n/// as its working principle for other types, take a look at the [guide].\n///\n/// In case the derive macro is not sufficient or can not be used for some other reason,\n/// [`FromPyObject`] can be implemented manually. In the following types without lifetime parameters\n/// are handled first, because they are a little bit simpler. Types with lifetime parameters are\n/// explained below.\n///\n/// ## Manual implementation for types without lifetime\n/// Types that do not contain lifetime parameters are unable to borrow from the Python object, so\n/// the lifetimes of [`FromPyObject`] can be elided:\n/// ```rust,no_run\n/// # #![allow(dead_code)]\n/// use pyo3::prelude::*;\n///\n/// struct MyObject {\n///     msg: String,\n///     list: Vec<u32>\n/// }\n///\n/// impl FromPyObject<'_, '_> for MyObject {\n///     type Error = PyErr;\n///\n///     fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n///         Ok(MyObject {\n///             msg: obj.getattr(\"msg\")?.extract()?,\n///             list: obj.getattr(\"list\")?.extract()?,\n///         })\n///     }\n/// }\n///\n/// # fn main() {}\n/// ```\n/// This is basically what the derive macro above expands to.\n///\n/// ## Manual implementation for types with lifetime parameters\n/// For types that contain lifetimes, these lifetimes need to be bound to the corresponding\n/// [`FromPyObject`] lifetime. This is roughly how the extraction of a typed [`Bound`] is\n/// implemented within PyO3.\n///\n/// ```rust,no_run\n/// # #![allow(dead_code)]\n/// use pyo3::prelude::*;\n/// use pyo3::types::PyString;\n///\n/// struct MyObject<'py>(Bound<'py, PyString>);\n///\n/// impl<'py> FromPyObject<'_, 'py> for MyObject<'py> {\n///     type Error = PyErr;\n///\n///     fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n///         Ok(MyObject(obj.cast()?.to_owned()))\n///     }\n/// }\n///\n/// # fn main() {}\n/// ```\n///\n/// # Details\n/// [`Cow<'a, str>`] is an example of an output type that may or may not borrow from the input\n/// lifetime `'a`. Which variant will be produced depends on the runtime type of the Python object.\n/// For a Python byte string, the existing string data can be borrowed for `'a` into a\n/// [`Cow::Borrowed`]. For a Python Unicode string, the data may have to be reencoded to UTF-8, and\n/// copied into a [`Cow::Owned`]. It does _not_ depend on the Python lifetime `'py`.\n///\n/// The output type may also depend on the Python lifetime `'py`. This allows the output type to\n/// keep interacting with the Python interpreter. See also [`Bound<'py, T>`].\n///\n/// [`Cow<'a, str>`]: std::borrow::Cow\n/// [`Cow::Borrowed`]: std::borrow::Cow::Borrowed\n/// [`Cow::Owned`]: std::borrow::Cow::Owned\n/// [guide]: https://pyo3.rs/latest/conversions/traits.html#deriving-frompyobject\npub trait FromPyObject<'a, 'py>: Sized {\n    /// The type returned in the event of a conversion error.\n    ///\n    /// For most use cases defaulting to [PyErr] here is perfectly acceptable. Using a custom error\n    /// type can be used to avoid having to create a Python exception object in the case where that\n    /// exception never reaches Python. This may lead to slightly better performance under certain\n    /// conditions.\n    ///\n    /// # Note\n    /// Unfortunately `Try` and thus `?` is based on [`From`], not [`Into`], so implementations may\n    /// need to use `.map_err(Into::into)` sometimes to convert a generic `Error` into a [`PyErr`].\n    type Error: Into<PyErr>;\n\n    /// Provides the type hint information for this type when it appears as an argument.\n    ///\n    /// For example, `Vec<u32>` would be `collections.abc.Sequence[int]`.\n    /// The default value is `typing.Any`, which is correct for any type.\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"_typeshed\", \"Incomplete\");\n\n    /// Extracts `Self` from the bound smart pointer `obj`.\n    ///\n    /// Users are advised against calling this method directly: instead, use this via\n    /// [`Bound<'_, PyAny>::extract`](crate::types::any::PyAnyMethods::extract) or [`Py::extract`].\n    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error>;\n\n    /// Specialization hook for extracting sequences for types like `Vec<u8>` and `[u8; N]`,\n    /// where the bytes can be directly copied from some python objects without going through\n    /// iteration.\n    #[doc(hidden)]\n    #[inline(always)]\n    fn sequence_extractor(\n        _obj: Borrowed<'_, 'py, PyAny>,\n        _: private::Token,\n    ) -> Option<impl FromPyObjectSequence<Target = Self>> {\n        struct NeverASequence<T>(PhantomData<T>);\n\n        impl<T> FromPyObjectSequence for NeverASequence<T> {\n            type Target = T;\n\n            fn to_vec(&self) -> Vec<Self::Target> {\n                unreachable!()\n            }\n\n            fn to_array<const N: usize>(&self) -> PyResult<[Self::Target; N]> {\n                unreachable!()\n            }\n        }\n\n        Option::<NeverASequence<Self>>::None\n    }\n\n    /// Helper used to make a specialized path in extracting `DateTime<Tz>` where `Tz` is\n    /// `chrono::Local`, which will accept \"naive\" datetime objects as being in the local timezone.\n    #[cfg(feature = \"chrono-local\")]\n    #[inline]\n    fn as_local_tz(_: private::Token) -> Option<Self> {\n        None\n    }\n}\n\nmod from_py_object_sequence {\n    use crate::PyResult;\n\n    /// Private trait for implementing specialized sequence extraction for `Vec<u8>` and `[u8; N]`\n    #[doc(hidden)]\n    pub trait FromPyObjectSequence {\n        type Target;\n\n        fn to_vec(&self) -> Vec<Self::Target>;\n\n        fn to_array<const N: usize>(&self) -> PyResult<[Self::Target; N]>;\n    }\n}\n\n// Only reachable / implementable inside PyO3 itself.\npub(crate) use from_py_object_sequence::FromPyObjectSequence;\n\n/// A data structure that can be extracted without borrowing any data from the input.\n///\n/// This is primarily useful for trait bounds. For example a [`FromPyObject`] implementation of a\n/// wrapper type may be able to borrow data from the input, but a [`FromPyObject`] implementation of\n/// a collection type may only extract owned data.\n///\n/// For example [`PyList`] will not hand out references tied to its own lifetime, but \"owned\"\n/// references independent of it. (Similar to [`Vec<Arc<T>>`] where you clone the [`Arc<T>`] out).\n/// This makes it impossible to collect borrowed types in a collection, since they would not borrow\n/// from the original [`PyList`], but the much shorter lived element reference. See the example\n/// below.\n///\n/// ```,no_run\n/// # use pyo3::prelude::*;\n/// # #[allow(dead_code)]\n/// pub struct MyWrapper<T>(T);\n///\n/// impl<'a, 'py, T> FromPyObject<'a, 'py> for MyWrapper<T>\n/// where\n///     T: FromPyObject<'a, 'py>\n/// {\n///     type Error = T::Error;\n///\n///     fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n///         obj.extract().map(MyWrapper)\n///     }\n/// }\n///\n/// # #[allow(dead_code)]\n/// pub struct MyVec<T>(Vec<T>);\n///\n/// impl<'py, T> FromPyObject<'_, 'py> for MyVec<T>\n/// where\n///     T: FromPyObjectOwned<'py> // 👈 can only extract owned values, because each `item` below\n///                               //    is a temporary short lived owned reference\n/// {\n///     type Error = PyErr;\n///\n///     fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n///         let mut v = MyVec(Vec::new());\n///         for item in obj.try_iter()? {\n///             v.0.push(item?.extract::<T>().map_err(Into::into)?);\n///         }\n///         Ok(v)\n///     }\n/// }\n/// ```\n///\n/// [`PyList`]: crate::types::PyList\n/// [`Arc<T>`]: std::sync::Arc\npub trait FromPyObjectOwned<'py>: for<'a> FromPyObject<'a, 'py> {}\nimpl<'py, T> FromPyObjectOwned<'py> for T where T: for<'a> FromPyObject<'a, 'py> {}\n\nimpl<'a, 'py, T> FromPyObject<'a, 'py> for T\nwhere\n    T: PyClass + Clone + ExtractPyClassWithClone,\n{\n    type Error = PyClassGuardError<'a, 'py>;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = <T as crate::PyTypeInfo>::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        Ok(obj.extract::<PyClassGuard<'_, T>>()?.clone())\n    }\n}\n\nimpl<'a, 'py, T> FromPyObject<'a, 'py> for PyRef<'py, T>\nwhere\n    T: PyClass,\n{\n    type Error = PyClassGuardError<'a, 'py>;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = <T as crate::PyTypeInfo>::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        obj.cast::<T>()\n            .map_err(|e| PyClassGuardError(Some(e)))?\n            .try_borrow()\n            .map_err(|_| PyClassGuardError(None))\n    }\n}\n\nimpl<'a, 'py, T> FromPyObject<'a, 'py> for PyRefMut<'py, T>\nwhere\n    T: PyClass<Frozen = False>,\n{\n    type Error = PyClassGuardMutError<'a, 'py>;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = <T as crate::PyTypeInfo>::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        obj.cast::<T>()\n            .map_err(|e| PyClassGuardMutError(Some(e)))?\n            .try_borrow_mut()\n            .map_err(|_| PyClassGuardMutError(None))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for () {\n    type Target = PyTuple;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyTuple::TYPE_HINT, PyStaticExpr::Tuple { elts: &[] });\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PyTuple::empty(py))\n    }\n}\n\n/// ```rust,compile_fail\n/// use pyo3::prelude::*;\n///\n/// #[pyclass]\n/// struct TestClass {\n///     num: u32,\n/// }\n///\n/// let t = TestClass { num: 10 };\n///\n/// Python::attach(|py| {\n///     let pyvalue = Py::new(py, t).unwrap().to_object(py);\n///     let t: TestClass = pyvalue.extract(py).unwrap();\n/// })\n/// ```\nmod test_no_clone {}\n\n#[cfg(test)]\nmod tests {\n    #[test]\n    #[cfg(feature = \"macros\")]\n    fn test_pyclass_skip_from_py_object() {\n        use crate::{types::PyAnyMethods, FromPyObject, IntoPyObject, PyErr, Python};\n\n        #[crate::pyclass(crate = \"crate\", skip_from_py_object)]\n        #[derive(Clone)]\n        struct Foo(i32);\n\n        impl<'py> FromPyObject<'_, 'py> for Foo {\n            type Error = PyErr;\n\n            fn extract(obj: crate::Borrowed<'_, 'py, crate::PyAny>) -> Result<Self, Self::Error> {\n                if let Ok(obj) = obj.cast::<Self>() {\n                    Ok(obj.borrow().clone())\n                } else {\n                    obj.extract::<i32>().map(Self)\n                }\n            }\n        }\n        Python::attach(|py| {\n            let foo1 = 42i32.into_pyobject(py)?;\n            assert_eq!(foo1.extract::<Foo>()?.0, 42);\n\n            let foo2 = Foo(0).into_pyobject(py)?;\n            assert_eq!(foo2.extract::<Foo>()?.0, 0);\n\n            Ok::<_, PyErr>(())\n        })\n        .unwrap();\n    }\n\n    #[test]\n    #[cfg(feature = \"macros\")]\n    fn test_pyclass_from_py_object() {\n        use crate::{types::PyAnyMethods, IntoPyObject, PyErr, Python};\n\n        #[crate::pyclass(crate = \"crate\", from_py_object)]\n        #[derive(Clone)]\n        struct Foo(i32);\n\n        Python::attach(|py| {\n            let foo1 = 42i32.into_pyobject(py)?;\n            assert!(foo1.extract::<Foo>().is_err());\n\n            let foo2 = Foo(0).into_pyobject(py)?;\n            assert_eq!(foo2.extract::<Foo>()?.0, 0);\n\n            Ok::<_, PyErr>(())\n        })\n        .unwrap();\n    }\n}\n"
  },
  {
    "path": "src/conversions/anyhow.rs",
    "content": "#![cfg(feature = \"anyhow\")]\n\n//! A conversion from [anyhow]’s [`Error`][anyhow-error] type to [`PyErr`].\n//!\n//! Use of an error handling library like [anyhow] is common in application code and when you just\n//! want error handling to be easy. If you are writing a library or you need more control over your\n//! errors you might want to design your own error type instead.\n//!\n//! When the inner error is a [`PyErr`] without source, it will be extracted out.\n//! Otherwise a Python [`RuntimeError`] will be created.\n//! You might find that you need to map the error from your Rust code into another Python exception.\n//! See [`PyErr::new`] for more information about that.\n//!\n//! For information about error handling in general, see the [Error handling] chapter of the Rust\n//! book.\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! ## change * to the version you want to use, ideally the latest.\n//! anyhow = \"*\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"anyhow\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of anyhow and PyO3.\n//! The required anyhow version may vary based on the version of PyO3.\n//!\n//! # Example: Propagating a `PyErr` into [`anyhow::Error`]\n//!\n//! ```rust\n//! use pyo3::prelude::*;\n//! use std::path::PathBuf;\n//!\n//! // A wrapper around a Rust function.\n//! // The pyfunction macro performs the conversion to a PyErr\n//! #[pyfunction]\n//! fn py_open(filename: PathBuf) -> anyhow::Result<Vec<u8>> {\n//!     let data = std::fs::read(filename)?;\n//!     Ok(data)\n//! }\n//!\n//! fn main() {\n//!     let error = Python::attach(|py| -> PyResult<Vec<u8>> {\n//!         let fun = wrap_pyfunction!(py_open, py)?;\n//!         let text = fun.call1((\"foo.txt\",))?.extract::<Vec<u8>>()?;\n//!         Ok(text)\n//!     }).unwrap_err();\n//!\n//!     println!(\"{}\", error);\n//! }\n//! ```\n//!\n//! # Example: Using `anyhow` in general\n//!\n//! Note that you don't need this feature to convert a [`PyErr`] into an [`anyhow::Error`], because\n//! it can already convert anything that implements [`Error`](std::error::Error):\n//!\n//! ```rust\n//! use pyo3::prelude::*;\n//! use pyo3::types::PyBytes;\n//!\n//! // An example function that must handle multiple error types.\n//! //\n//! // To do this you usually need to design your own error type or use\n//! // `Box<dyn Error>`. `anyhow` is a convenient alternative for this.\n//! pub fn decompress(bytes: &[u8]) -> anyhow::Result<String> {\n//!     // An arbitrary example of a Python api you\n//!     // could call inside an application...\n//!     // This might return a `PyErr`.\n//!     let res = Python::attach(|py| {\n//!         let zlib = PyModule::import(py, \"zlib\")?;\n//!         let decompress = zlib.getattr(\"decompress\")?;\n//!         let bytes = PyBytes::new(py, bytes);\n//!         let value = decompress.call1((bytes,))?;\n//!         value.extract::<Vec<u8>>()\n//!     })?;\n//!\n//!     // This might be a `FromUtf8Error`.\n//!     let text = String::from_utf8(res)?;\n//!\n//!     Ok(text)\n//! }\n//!\n//! fn main() -> anyhow::Result<()> {\n//!     let bytes: &[u8] = b\"x\\x9c\\x8b\\xcc/U(\\xce\\xc8/\\xcdIQ((\\xcaOJL\\xca\\xa9T\\\n//!                         (-NU(\\xc9HU\\xc8\\xc9LJ\\xcbI,IUH.\\x02\\x91\\x99y\\xc5%\\\n//!                         \\xa9\\x89)z\\x00\\xf2\\x15\\x12\\xfe\";\n//!     let text = decompress(bytes)?;\n//!\n//!     println!(\"The text is \\\"{}\\\"\", text);\n//! # assert_eq!(text, \"You should probably use the libflate crate instead.\");\n//!     Ok(())\n//! }\n//! ```\n//!\n//! [anyhow]: https://docs.rs/anyhow/ \"A trait object based error system for easy idiomatic error handling in Rust applications.\"\n//! [anyhow-error]: https://docs.rs/anyhow/latest/anyhow/struct.Error.html \"Anyhows `Error` type, a wrapper around a dynamic error type\"\n//! [`RuntimeError`]: https://docs.python.org/3/library/exceptions.html#RuntimeError \"Built-in Exceptions — Python documentation\"\n//! [Error handling]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html \"Recoverable Errors with Result - The Rust Programming Language\"\n\nuse crate::exceptions::PyRuntimeError;\nuse crate::PyErr;\n\nimpl From<anyhow::Error> for PyErr {\n    fn from(mut error: anyhow::Error) -> Self {\n        // Errors containing a PyErr without chain or context are returned as the underlying error\n        if error.source().is_none() {\n            error = match error.downcast::<Self>() {\n                Ok(py_err) => return py_err,\n                Err(error) => error,\n            };\n        }\n        PyRuntimeError::new_err(format!(\"{error:?}\"))\n    }\n}\n\n#[cfg(test)]\nmod test_anyhow {\n    use crate::exceptions::{PyRuntimeError, PyValueError};\n    use crate::prelude::*;\n    use crate::types::IntoPyDict;\n\n    use anyhow::{anyhow, bail, Context, Result};\n\n    fn f() -> Result<()> {\n        use std::io;\n        bail!(io::Error::new(io::ErrorKind::PermissionDenied, \"oh no!\"));\n    }\n\n    fn g() -> Result<()> {\n        f().context(\"f failed\")\n    }\n\n    fn h() -> Result<()> {\n        g().context(\"g failed\")\n    }\n\n    #[test]\n    fn test_pyo3_exception_contents() {\n        let err = h().unwrap_err();\n        let expected_contents = format!(\"{err:?}\");\n        let pyerr = PyErr::from(err);\n\n        Python::attach(|py| {\n            let locals = [(\"err\", pyerr)].into_py_dict(py).unwrap();\n            let pyerr = py.run(c\"raise err\", None, Some(&locals)).unwrap_err();\n            assert_eq!(pyerr.value(py).to_string(), expected_contents);\n        })\n    }\n\n    fn k() -> Result<()> {\n        Err(anyhow!(\"Some sort of error\"))\n    }\n\n    #[test]\n    fn test_pyo3_exception_contents2() {\n        let err = k().unwrap_err();\n        let expected_contents = format!(\"{err:?}\");\n        let pyerr = PyErr::from(err);\n\n        Python::attach(|py| {\n            let locals = [(\"err\", pyerr)].into_py_dict(py).unwrap();\n            let pyerr = py.run(c\"raise err\", None, Some(&locals)).unwrap_err();\n            assert_eq!(pyerr.value(py).to_string(), expected_contents);\n        })\n    }\n\n    #[test]\n    fn test_pyo3_unwrap_simple_err() {\n        let origin_exc = PyValueError::new_err(\"Value Error\");\n        let err: anyhow::Error = origin_exc.into();\n        let converted: PyErr = err.into();\n        assert!(Python::attach(\n            |py| converted.is_instance_of::<PyValueError>(py)\n        ))\n    }\n    #[test]\n    fn test_pyo3_unwrap_complex_err() {\n        let origin_exc = PyValueError::new_err(\"Value Error\");\n        let mut err: anyhow::Error = origin_exc.into();\n        err = err.context(\"Context\");\n        let converted: PyErr = err.into();\n        assert!(Python::attach(\n            |py| converted.is_instance_of::<PyRuntimeError>(py)\n        ))\n    }\n}\n"
  },
  {
    "path": "src/conversions/bigdecimal.rs",
    "content": "#![cfg(feature = \"bigdecimal\")]\n//! Conversions to and from [bigdecimal](https://docs.rs/bigdecimal)'s [`BigDecimal`] type.\n//!\n//! This is useful for converting Python's decimal.Decimal into and from a native Rust type.\n//!\n//! # Setup\n//!\n//! To use this feature, add to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"bigdecimal\\\"] }\")]\n//! bigdecimal = \"0.4\"\n//! ```\n//!\n//! Note that you must use a compatible version of bigdecimal and PyO3.\n//! The required bigdecimal version may vary based on the version of PyO3.\n//!\n//! # Example\n//!\n//! Rust code to create a function that adds one to a BigDecimal\n//!\n//! ```rust\n//! use bigdecimal::BigDecimal;\n//! use pyo3::prelude::*;\n//!\n//! #[pyfunction]\n//! fn add_one(d: BigDecimal) -> BigDecimal {\n//!     d + 1\n//! }\n//!\n//! #[pymodule]\n//! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n//!     m.add_function(wrap_pyfunction!(add_one, m)?)?;\n//!     Ok(())\n//! }\n//! ```\n//!\n//! Python code that validates the functionality\n//!\n//!\n//! ```python\n//! from my_module import add_one\n//! from decimal import Decimal\n//!\n//! d = Decimal(\"2\")\n//! value = add_one(d)\n//!\n//! assert d + 1 == value\n//! ```\n\nuse std::str::FromStr;\n\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_hint_identifier;\nuse crate::types::PyTuple;\nuse crate::{\n    exceptions::PyValueError,\n    sync::PyOnceLock,\n    types::{PyAnyMethods, PyStringMethods, PyType},\n    Borrowed, Bound, FromPyObject, IntoPyObject, Py, PyAny, PyErr, PyResult, Python,\n};\nuse bigdecimal::BigDecimal;\nuse num_bigint::Sign;\n\nfn get_decimal_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> {\n    static DECIMAL_CLS: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n    DECIMAL_CLS.import(py, \"decimal\", \"Decimal\")\n}\n\nfn get_invalid_operation_error_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> {\n    static INVALID_OPERATION_CLS: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n    INVALID_OPERATION_CLS.import(py, \"decimal\", \"InvalidOperation\")\n}\n\nimpl FromPyObject<'_, '_> for BigDecimal {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"decimal\", \"Decimal\");\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {\n        let py_str = &obj.str()?;\n        let rs_str = &py_str.to_cow()?;\n        BigDecimal::from_str(rs_str).map_err(|e| PyValueError::new_err(e.to_string()))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for BigDecimal {\n    type Target = PyAny;\n\n    type Output = Bound<'py, Self::Target>;\n\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"decimal\", \"Decimal\");\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let cls = get_decimal_cls(py)?;\n        let (bigint, scale) = self.into_bigint_and_scale();\n        if scale == 0 {\n            return cls.call1((bigint,));\n        }\n        let exponent = scale.checked_neg().ok_or_else(|| {\n            get_invalid_operation_error_cls(py)\n                .map_or_else(|err| err, |cls| PyErr::from_type(cls.clone(), ()))\n        })?;\n        let (sign, digits) = bigint.to_radix_be(10);\n        let signed = matches!(sign, Sign::Minus).into_pyobject(py)?;\n        let digits = PyTuple::new(py, digits)?;\n\n        cls.call1(((signed, digits, exponent),))\n    }\n}\n\n#[cfg(test)]\nmod test_bigdecimal {\n    use super::*;\n    use crate::types::dict::PyDictMethods;\n    use crate::types::PyDict;\n    use std::ffi::CString;\n\n    use bigdecimal::{One, Zero};\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use proptest::prelude::*;\n\n    macro_rules! convert_constants {\n        ($name:ident, $rs:expr, $py:literal) => {\n            #[test]\n            fn $name() {\n                Python::attach(|py| {\n                    let rs_orig = $rs;\n                    let rs_dec = rs_orig.clone().into_pyobject(py).unwrap();\n                    let locals = PyDict::new(py);\n                    locals.set_item(\"rs_dec\", &rs_dec).unwrap();\n                    // Checks if BigDecimal -> Python Decimal conversion is correct\n                    py.run(\n                        &CString::new(format!(\n                            \"import decimal\\npy_dec = decimal.Decimal(\\\"{}\\\")\\nassert py_dec == rs_dec\",\n                            $py\n                        ))\n                        .unwrap(),\n                        None,\n                        Some(&locals),\n                    )\n                    .unwrap();\n                    // Checks if Python Decimal -> BigDecimal conversion is correct\n                    let py_dec = locals.get_item(\"py_dec\").unwrap().unwrap();\n                    let py_result: BigDecimal = py_dec.extract().unwrap();\n                    assert_eq!(rs_orig, py_result);\n                })\n            }\n        };\n    }\n\n    convert_constants!(convert_zero, BigDecimal::zero(), \"0\");\n    convert_constants!(convert_one, BigDecimal::one(), \"1\");\n    convert_constants!(convert_neg_one, -BigDecimal::one(), \"-1\");\n    convert_constants!(convert_two, BigDecimal::from(2), \"2\");\n    convert_constants!(convert_ten, BigDecimal::from_str(\"10\").unwrap(), \"10\");\n    convert_constants!(\n        convert_one_hundred_point_one,\n        BigDecimal::from_str(\"100.1\").unwrap(),\n        \"100.1\"\n    );\n    convert_constants!(\n        convert_one_thousand,\n        BigDecimal::from_str(\"1000\").unwrap(),\n        \"1000\"\n    );\n    convert_constants!(\n        convert_scientific,\n        BigDecimal::from_str(\"1e10\").unwrap(),\n        \"1e10\"\n    );\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    proptest! {\n        #[test]\n        fn test_roundtrip(\n            number in 0..28u32\n        ) {\n            let num = BigDecimal::from(number);\n            Python::attach(|py| {\n                let rs_dec = num.clone().into_pyobject(py).unwrap();\n                let locals = PyDict::new(py);\n                locals.set_item(\"rs_dec\", &rs_dec).unwrap();\n                py.run(\n                    &CString::new(format!(\n                       \"import decimal\\npy_dec = decimal.Decimal(\\\"{num}\\\")\\nassert py_dec == rs_dec\")).unwrap(),\n                None, Some(&locals)).unwrap();\n                let roundtripped: BigDecimal = rs_dec.extract().unwrap();\n                assert_eq!(num, roundtripped);\n            })\n        }\n\n        #[test]\n        fn test_integers(num in any::<i64>()) {\n            Python::attach(|py| {\n                let py_num = num.into_pyobject(py).unwrap();\n                let roundtripped: BigDecimal = py_num.extract().unwrap();\n                let rs_dec = BigDecimal::from(num);\n                assert_eq!(rs_dec, roundtripped);\n            })\n        }\n    }\n\n    #[test]\n    fn test_nan() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            py.run(\n                c\"import decimal\\npy_dec = decimal.Decimal(\\\"NaN\\\")\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let py_dec = locals.get_item(\"py_dec\").unwrap().unwrap();\n            let roundtripped: Result<BigDecimal, PyErr> = py_dec.extract();\n            assert!(roundtripped.is_err());\n        })\n    }\n\n    #[test]\n    fn test_infinity() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            py.run(\n                c\"import decimal\\npy_dec = decimal.Decimal(\\\"Infinity\\\")\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let py_dec = locals.get_item(\"py_dec\").unwrap().unwrap();\n            let roundtripped: Result<BigDecimal, PyErr> = py_dec.extract();\n            assert!(roundtripped.is_err());\n        })\n    }\n\n    #[test]\n    fn test_no_precision_loss() {\n        Python::attach(|py| {\n            let src = \"1e4\";\n            let expected = get_decimal_cls(py)\n                .unwrap()\n                .call1((src,))\n                .unwrap()\n                .call_method0(\"as_tuple\")\n                .unwrap();\n            let actual = src\n                .parse::<BigDecimal>()\n                .unwrap()\n                .into_pyobject(py)\n                .unwrap()\n                .call_method0(\"as_tuple\")\n                .unwrap();\n\n            assert!(actual.eq(expected).unwrap());\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/bytes.rs",
    "content": "#![cfg(feature = \"bytes\")]\n\n//! Conversions to and from [bytes](https://docs.rs/bytes/latest/bytes/)'s [`Bytes`].\n//!\n//! This is useful for efficiently converting Python's `bytes` types efficiently.\n//! While `bytes` will be directly borrowed, converting from `bytearray` will result in a copy.\n//!\n//! When converting `Bytes` back into Python, this will do a copy, just like `&[u8]` and `Vec<u8>`.\n//!\n//! # When to use `Bytes`\n//!\n//! Unless you specifically need [`Bytes`] for ref-counted ownership and sharing,\n//! you may find that using `&[u8]`, `Vec<u8>`, [`Bound<PyBytes>`], or [`PyBackedBytes`]\n//! is simpler for most use cases.\n//!\n//! # Setup\n//!\n//! To use this feature, add in your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! bytes = \"1.10\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"bytes\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of bytes and PyO3.\n//!\n//! # Example\n//!\n//! Rust code to create functions which return `Bytes` or take `Bytes` as arguments:\n//!\n//! ```rust,no_run\n//! use pyo3::prelude::*;\n//! use bytes::Bytes;\n//!\n//! #[pyfunction]\n//! fn get_message_bytes() -> Bytes {\n//!     Bytes::from_static(b\"Hello Python!\")\n//! }\n//!\n//! #[pyfunction]\n//! fn num_bytes(bytes: Bytes) -> usize {\n//!     bytes.len()\n//! }\n//!\n//! #[pymodule]\n//! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n//!     m.add_function(wrap_pyfunction!(get_message_bytes, m)?)?;\n//!     m.add_function(wrap_pyfunction!(num_bytes, m)?)?;\n//!     Ok(())\n//! }\n//! ```\n//!\n//! Python code that calls these functions:\n//!\n//! ```python\n//! from my_module import get_message_bytes, num_bytes\n//!\n//! message = get_message_bytes()\n//! assert message == b\"Hello Python!\"\n//!\n//! size = num_bytes(message)\n//! assert size == 13\n//! ```\nuse bytes::Bytes;\n\nuse crate::conversion::IntoPyObject;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::instance::Bound;\nuse crate::pybacked::PyBackedBytes;\nuse crate::types::PyBytes;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::PyTypeInfo;\nuse crate::{Borrowed, CastError, FromPyObject, PyAny, PyErr, Python};\n\nimpl<'a, 'py> FromPyObject<'a, 'py> for Bytes {\n    type Error = CastError<'a, 'py>;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyBackedBytes::INPUT_TYPE;\n\n    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        Ok(Bytes::from_owner(obj.extract::<PyBackedBytes>()?))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Bytes {\n    type Target = PyBytes;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyBytes::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PyBytes::new(py, &self))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Bytes {\n    type Target = PyBytes;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyBytes::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PyBytes::new(py, self))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::{PyAnyMethods, PyByteArray, PyByteArrayMethods, PyBytes};\n    use crate::Python;\n\n    #[test]\n    fn test_bytes() {\n        Python::attach(|py| {\n            let py_bytes = PyBytes::new(py, b\"foobar\");\n            let bytes: Bytes = py_bytes.extract().unwrap();\n            assert_eq!(&*bytes, b\"foobar\");\n\n            let bytes = Bytes::from_static(b\"foobar\").into_pyobject(py).unwrap();\n            assert!(bytes.is_instance_of::<PyBytes>());\n        });\n    }\n\n    #[test]\n    fn test_bytearray() {\n        Python::attach(|py| {\n            let py_bytearray = PyByteArray::new(py, b\"foobar\");\n            let bytes: Bytes = py_bytearray.extract().unwrap();\n            assert_eq!(&*bytes, b\"foobar\");\n\n            // Editing the bytearray should not change extracted Bytes\n            unsafe { py_bytearray.as_bytes_mut()[0] = b'x' };\n            assert_eq!(&bytes, \"foobar\");\n            assert_eq!(&py_bytearray.extract::<Vec<u8>>().unwrap(), b\"xoobar\");\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/chrono.rs",
    "content": "#![cfg(feature = \"chrono\")]\n\n//! Conversions to and from [chrono](https://docs.rs/chrono/)’s `Duration`,\n//! `NaiveDate`, `NaiveTime`, `DateTime<Tz>`, `FixedOffset`, and `Utc`.\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! chrono = \"0.4\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"chrono\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of chrono and PyO3.\n//! The required chrono version may vary based on the version of PyO3.\n//!\n//! # Example: Convert a `datetime.datetime` to chrono's `DateTime<Utc>`\n//!\n//! ```rust\n//! use chrono::{DateTime, Duration, TimeZone, Utc};\n//! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods};\n//!\n//! fn main() -> PyResult<()> {\n//!     Python::initialize();\n//!     Python::attach(|py| {\n//!         // Build some chrono values\n//!         let chrono_datetime = Utc.with_ymd_and_hms(2022, 1, 1, 12, 0, 0).unwrap();\n//!         let chrono_duration = Duration::seconds(1);\n//!         // Convert them to Python\n//!         let py_datetime = chrono_datetime.into_pyobject(py)?;\n//!         let py_timedelta = chrono_duration.into_pyobject(py)?;\n//!         // Do an operation in Python\n//!         let py_sum = py_datetime.call_method1(\"__add__\", (py_timedelta,))?;\n//!         // Convert back to Rust\n//!         let chrono_sum: DateTime<Utc> = py_sum.extract()?;\n//!         println!(\"DateTime<Utc>: {}\", chrono_datetime);\n//!         Ok(())\n//!     })\n//! }\n//! ```\n\nuse crate::conversion::{FromPyObjectOwned, IntoPyObject};\nuse crate::exceptions::{PyTypeError, PyUserWarning, PyValueError};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::intern;\nuse crate::types::any::PyAnyMethods;\nuse crate::types::PyNone;\nuse crate::types::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo, PyTzInfoAccess};\n#[cfg(not(Py_LIMITED_API))]\nuse crate::types::{PyDateAccess, PyDeltaAccess, PyTimeAccess};\n#[cfg(feature = \"chrono-local\")]\nuse crate::{\n    exceptions::PyRuntimeError,\n    sync::PyOnceLock,\n    types::{PyString, PyStringMethods},\n    Py,\n};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::{type_hint_identifier, PyTypeInfo};\nuse crate::{Borrowed, Bound, FromPyObject, IntoPyObjectExt, PyAny, PyErr, PyResult, Python};\nuse chrono::offset::{FixedOffset, Utc};\n#[cfg(feature = \"chrono-local\")]\nuse chrono::Local;\nuse chrono::{\n    DateTime, Datelike, Duration, LocalResult, NaiveDate, NaiveDateTime, NaiveTime, Offset,\n    TimeZone, Timelike,\n};\n\nimpl<'py> IntoPyObject<'py> for Duration {\n    type Target = PyDelta;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDelta::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        // Total number of days\n        let days = self.num_days();\n        // Remainder of seconds\n        let secs_dur = self - Duration::days(days);\n        let secs = secs_dur.num_seconds();\n        // Fractional part of the microseconds\n        let micros = (secs_dur - Duration::seconds(secs_dur.num_seconds()))\n            .num_microseconds()\n            // This should never panic since we are just getting the fractional\n            // part of the total microseconds, which should never overflow.\n            .unwrap();\n        // We do not need to check the days i64 to i32 cast from rust because\n        // python will panic with OverflowError.\n        // We pass true as the `normalize` parameter since we'd need to do several checks here to\n        // avoid that, and it shouldn't have a big performance impact.\n        // The seconds and microseconds cast should never overflow since it's at most the number of seconds per day\n        PyDelta::new(\n            py,\n            days.try_into().unwrap_or(i32::MAX),\n            secs.try_into()?,\n            micros.try_into()?,\n            true,\n        )\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Duration {\n    type Target = PyDelta;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Duration::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl FromPyObject<'_, '_> for Duration {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDelta::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let delta = ob.cast::<PyDelta>()?;\n        // Python size are much lower than rust size so we do not need bound checks.\n        // 0 <= microseconds < 1000000\n        // 0 <= seconds < 3600*24\n        // -999999999 <= days <= 999999999\n        #[cfg(not(Py_LIMITED_API))]\n        let (days, seconds, microseconds) = {\n            (\n                delta.get_days().into(),\n                delta.get_seconds().into(),\n                delta.get_microseconds().into(),\n            )\n        };\n        #[cfg(Py_LIMITED_API)]\n        let (days, seconds, microseconds) = {\n            let py = delta.py();\n            (\n                delta.getattr(intern!(py, \"days\"))?.extract()?,\n                delta.getattr(intern!(py, \"seconds\"))?.extract()?,\n                delta.getattr(intern!(py, \"microseconds\"))?.extract()?,\n            )\n        };\n        Ok(\n            Duration::days(days)\n                + Duration::seconds(seconds)\n                + Duration::microseconds(microseconds),\n        )\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for NaiveDate {\n    type Target = PyDate;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDate::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let DateArgs { year, month, day } = (&self).into();\n        PyDate::new(py, year, month, day)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &NaiveDate {\n    type Target = PyDate;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = NaiveDate::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl FromPyObject<'_, '_> for NaiveDate {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDate::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let date = &*ob.cast::<PyDate>()?;\n        py_date_to_naive_date(date)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for NaiveTime {\n    type Target = PyTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyTime::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let TimeArgs {\n            hour,\n            min,\n            sec,\n            micro,\n            truncated_leap_second,\n        } = (&self).into();\n\n        let time = PyTime::new(py, hour, min, sec, micro, None)?;\n\n        if truncated_leap_second {\n            warn_truncated_leap_second(&time);\n        }\n\n        Ok(time)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &NaiveTime {\n    type Target = PyTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = NaiveTime::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl FromPyObject<'_, '_> for NaiveTime {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyTime::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let time = &*ob.cast::<PyTime>()?;\n        py_time_to_naive_time(time)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for NaiveDateTime {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let DateArgs { year, month, day } = (&self.date()).into();\n        let TimeArgs {\n            hour,\n            min,\n            sec,\n            micro,\n            truncated_leap_second,\n        } = (&self.time()).into();\n\n        let datetime = PyDateTime::new(py, year, month, day, hour, min, sec, micro, None)?;\n\n        if truncated_leap_second {\n            warn_truncated_leap_second(&datetime);\n        }\n\n        Ok(datetime)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &NaiveDateTime {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = NaiveDateTime::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl FromPyObject<'_, '_> for NaiveDateTime {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn extract(dt: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let dt = &*dt.cast::<PyDateTime>()?;\n\n        // If the user tries to convert a timezone aware datetime into a naive one,\n        // we return a hard error. We could silently remove tzinfo, or assume local timezone\n        // and do a conversion, but better leave this decision to the user of the library.\n        let has_tzinfo = dt.get_tzinfo().is_some();\n        if has_tzinfo {\n            return Err(PyTypeError::new_err(\"expected a datetime without tzinfo\"));\n        }\n\n        let dt = NaiveDateTime::new(py_date_to_naive_date(dt)?, py_time_to_naive_time(dt)?);\n        Ok(dt)\n    }\n}\n\nimpl<'py, Tz: TimeZone> IntoPyObject<'py> for DateTime<Tz>\nwhere\n    Tz: IntoPyObject<'py>,\n{\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&DateTime<Tz>>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (&self).into_pyobject(py)\n    }\n}\n\nimpl<'py, Tz: TimeZone> IntoPyObject<'py> for &DateTime<Tz>\nwhere\n    Tz: IntoPyObject<'py>,\n{\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let tz = self.timezone().into_bound_py_any(py)?.cast_into()?;\n\n        let DateArgs { year, month, day } = (&self.naive_local().date()).into();\n        let TimeArgs {\n            hour,\n            min,\n            sec,\n            micro,\n            truncated_leap_second,\n        } = (&self.naive_local().time()).into();\n\n        let fold = matches!(\n            self.timezone().offset_from_local_datetime(&self.naive_local()),\n            LocalResult::Ambiguous(_, latest) if self.offset().fix() == latest.fix()\n        );\n\n        let datetime = PyDateTime::new_with_fold(\n            py,\n            year,\n            month,\n            day,\n            hour,\n            min,\n            sec,\n            micro,\n            Some(&tz),\n            fold,\n        )?;\n\n        if truncated_leap_second {\n            warn_truncated_leap_second(&datetime);\n        }\n\n        Ok(datetime)\n    }\n}\n\nimpl<'py, Tz> FromPyObject<'_, 'py> for DateTime<Tz>\nwhere\n    Tz: TimeZone + FromPyObjectOwned<'py>,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn extract(dt: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        let dt = &*dt.cast::<PyDateTime>()?;\n        let tzinfo = dt.get_tzinfo();\n\n        let tz = if let Some(tzinfo) = tzinfo {\n            tzinfo.extract().map_err(Into::into)?\n        } else {\n            // Special case: allow naive `datetime` objects for `DateTime<Local>`, interpreting them as local time.\n            #[cfg(feature = \"chrono-local\")]\n            if let Some(tz) = Tz::as_local_tz(crate::conversion::private::Token) {\n                return py_datetime_to_datetime_with_timezone(dt, tz);\n            }\n\n            return Err(PyTypeError::new_err(\n                \"expected a datetime with non-None tzinfo\",\n            ));\n        };\n\n        py_datetime_to_datetime_with_timezone(dt, tz)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for FixedOffset {\n    type Target = PyTzInfo;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"datetime\", \"timezone\");\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let seconds_offset = self.local_minus_utc();\n        let td = PyDelta::new(py, 0, seconds_offset, 0, true)?;\n        PyTzInfo::fixed_offset(py, td)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &FixedOffset {\n    type Target = PyTzInfo;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = FixedOffset::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl FromPyObject<'_, '_> for FixedOffset {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyTzInfo::TYPE_HINT;\n\n    /// Convert python tzinfo to rust [`FixedOffset`].\n    ///\n    /// Note that the conversion will result in precision lost in microseconds as chrono offset\n    /// does not supports microseconds.\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let ob = ob.cast::<PyTzInfo>()?;\n\n        // Passing Python's None to the `utcoffset` function will only\n        // work for timezones defined as fixed offsets in Python.\n        // Any other timezone would require a datetime as the parameter, and return\n        // None if the datetime is not provided.\n        // Trying to convert None to a PyDelta in the next line will then fail.\n        let py_timedelta =\n            ob.call_method1(intern!(ob.py(), \"utcoffset\"), (PyNone::get(ob.py()),))?;\n        if py_timedelta.is_none() {\n            return Err(PyTypeError::new_err(format!(\n                \"{ob:?} is not a fixed offset timezone\"\n            )));\n        }\n        let total_seconds: Duration = py_timedelta.extract()?;\n        // This cast is safe since the timedelta is limited to -24 hours and 24 hours.\n        let total_seconds = total_seconds.num_seconds() as i32;\n        FixedOffset::east_opt(total_seconds)\n            .ok_or_else(|| PyValueError::new_err(\"fixed offset out of bounds\"))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Utc {\n    type Target = PyTzInfo;\n    type Output = Borrowed<'static, 'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"datetime\", \"timezone\");\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        PyTzInfo::utc(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Utc {\n    type Target = PyTzInfo;\n    type Output = Borrowed<'static, 'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Utc::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl FromPyObject<'_, '_> for Utc {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = Utc::OUTPUT_TYPE;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let py_utc = Utc.into_pyobject(ob.py())?;\n        if ob.eq(py_utc)? {\n            Ok(Utc)\n        } else {\n            Err(PyValueError::new_err(\"expected datetime.timezone.utc\"))\n        }\n    }\n}\n\n#[cfg(feature = \"chrono-local\")]\nimpl<'py> IntoPyObject<'py> for Local {\n    type Target = PyTzInfo;\n    type Output = Borrowed<'static, 'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(all(feature = \"experimental-inspect\", Py_3_9))]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"zoneinfo\", \"ZoneInfo\");\n\n    #[cfg(all(feature = \"experimental-inspect\", not(Py_3_9)))]\n    const OUTPUT_TYPE: PyStaticExpr = PyTzInfo::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        static LOCAL_TZ: PyOnceLock<Py<PyTzInfo>> = PyOnceLock::new();\n        let tz = LOCAL_TZ\n            .get_or_try_init(py, || {\n                let iana_name = iana_time_zone::get_timezone().map_err(|e| {\n                    PyRuntimeError::new_err(format!(\"Could not get local timezone: {e}\"))\n                })?;\n                PyTzInfo::timezone(py, iana_name).map(Bound::unbind)\n            })?\n            .bind_borrowed(py);\n        Ok(tz)\n    }\n}\n\n#[cfg(feature = \"chrono-local\")]\nimpl<'py> IntoPyObject<'py> for &Local {\n    type Target = PyTzInfo;\n    type Output = Borrowed<'static, 'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Local::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\n#[cfg(feature = \"chrono-local\")]\nimpl FromPyObject<'_, '_> for Local {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = Local::OUTPUT_TYPE;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> PyResult<Local> {\n        let local_tz = Local.into_pyobject(ob.py())?;\n        if ob.eq(local_tz)? {\n            Ok(Local)\n        } else {\n            let name = local_tz.getattr(\"key\")?.cast_into::<PyString>()?;\n            Err(PyValueError::new_err(format!(\n                \"expected local timezone {}\",\n                name.to_cow()?\n            )))\n        }\n    }\n\n    #[inline]\n    fn as_local_tz(_: crate::conversion::private::Token) -> Option<Self> {\n        Some(Local)\n    }\n}\n\nstruct DateArgs {\n    year: i32,\n    month: u8,\n    day: u8,\n}\n\nimpl From<&NaiveDate> for DateArgs {\n    fn from(value: &NaiveDate) -> Self {\n        Self {\n            year: value.year(),\n            month: value.month() as u8,\n            day: value.day() as u8,\n        }\n    }\n}\n\nstruct TimeArgs {\n    hour: u8,\n    min: u8,\n    sec: u8,\n    micro: u32,\n    truncated_leap_second: bool,\n}\n\nimpl From<&NaiveTime> for TimeArgs {\n    fn from(value: &NaiveTime) -> Self {\n        let ns = value.nanosecond();\n        let checked_sub = ns.checked_sub(1_000_000_000);\n        let truncated_leap_second = checked_sub.is_some();\n        let micro = checked_sub.unwrap_or(ns) / 1000;\n        Self {\n            hour: value.hour() as u8,\n            min: value.minute() as u8,\n            sec: value.second() as u8,\n            micro,\n            truncated_leap_second,\n        }\n    }\n}\n\nfn warn_truncated_leap_second(obj: &Bound<'_, PyAny>) {\n    let py = obj.py();\n    if let Err(e) = PyErr::warn(\n        py,\n        &py.get_type::<PyUserWarning>(),\n        c\"ignored leap-second, `datetime` does not support leap-seconds\",\n        0,\n    ) {\n        e.write_unraisable(py, Some(obj))\n    };\n}\n\n#[cfg(not(Py_LIMITED_API))]\nfn py_date_to_naive_date(\n    py_date: impl std::ops::Deref<Target = impl PyDateAccess>,\n) -> PyResult<NaiveDate> {\n    NaiveDate::from_ymd_opt(\n        py_date.get_year(),\n        py_date.get_month().into(),\n        py_date.get_day().into(),\n    )\n    .ok_or_else(|| PyValueError::new_err(\"invalid or out-of-range date\"))\n}\n\n#[cfg(Py_LIMITED_API)]\nfn py_date_to_naive_date(py_date: &Bound<'_, PyAny>) -> PyResult<NaiveDate> {\n    NaiveDate::from_ymd_opt(\n        py_date.getattr(intern!(py_date.py(), \"year\"))?.extract()?,\n        py_date.getattr(intern!(py_date.py(), \"month\"))?.extract()?,\n        py_date.getattr(intern!(py_date.py(), \"day\"))?.extract()?,\n    )\n    .ok_or_else(|| PyValueError::new_err(\"invalid or out-of-range date\"))\n}\n\n#[cfg(not(Py_LIMITED_API))]\nfn py_time_to_naive_time(\n    py_time: impl std::ops::Deref<Target = impl PyTimeAccess>,\n) -> PyResult<NaiveTime> {\n    NaiveTime::from_hms_micro_opt(\n        py_time.get_hour().into(),\n        py_time.get_minute().into(),\n        py_time.get_second().into(),\n        py_time.get_microsecond(),\n    )\n    .ok_or_else(|| PyValueError::new_err(\"invalid or out-of-range time\"))\n}\n\n#[cfg(Py_LIMITED_API)]\nfn py_time_to_naive_time(py_time: &Bound<'_, PyAny>) -> PyResult<NaiveTime> {\n    NaiveTime::from_hms_micro_opt(\n        py_time.getattr(intern!(py_time.py(), \"hour\"))?.extract()?,\n        py_time\n            .getattr(intern!(py_time.py(), \"minute\"))?\n            .extract()?,\n        py_time\n            .getattr(intern!(py_time.py(), \"second\"))?\n            .extract()?,\n        py_time\n            .getattr(intern!(py_time.py(), \"microsecond\"))?\n            .extract()?,\n    )\n    .ok_or_else(|| PyValueError::new_err(\"invalid or out-of-range time\"))\n}\n\nfn py_datetime_to_datetime_with_timezone<Tz: TimeZone>(\n    dt: &Bound<'_, PyDateTime>,\n    tz: Tz,\n) -> PyResult<DateTime<Tz>> {\n    let naive_dt = NaiveDateTime::new(py_date_to_naive_date(dt)?, py_time_to_naive_time(dt)?);\n    match naive_dt.and_local_timezone(tz) {\n        LocalResult::Single(value) => Ok(value),\n        LocalResult::Ambiguous(earliest, latest) => {\n            #[cfg(not(Py_LIMITED_API))]\n            let fold = dt.get_fold();\n\n            #[cfg(Py_LIMITED_API)]\n            let fold = dt.getattr(intern!(dt.py(), \"fold\"))?.extract::<usize>()? > 0;\n\n            if fold {\n                Ok(latest)\n            } else {\n                Ok(earliest)\n            }\n        }\n        LocalResult::None => Err(PyValueError::new_err(format!(\n            \"The datetime {dt:?} contains an incompatible timezone\"\n        ))),\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::{test_utils::assert_warnings, types::PyTuple, BoundObject};\n    use std::{cmp::Ordering, panic};\n\n    #[test]\n    // Only Python>=3.9 has the zoneinfo package\n    // We skip the test on windows too since we'd need to install\n    // tzdata there to make this work.\n    #[cfg(all(Py_3_9, not(target_os = \"windows\")))]\n    fn test_zoneinfo_is_not_fixed_offset() {\n        use crate::types::any::PyAnyMethods;\n        use crate::types::dict::PyDictMethods;\n\n        Python::attach(|py| {\n            let locals = crate::types::PyDict::new(py);\n            py.run(\n                c\"import zoneinfo; zi = zoneinfo.ZoneInfo('Europe/London')\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let result: PyResult<FixedOffset> = locals.get_item(\"zi\").unwrap().unwrap().extract();\n            assert!(result.is_err());\n            let res = result.err().unwrap();\n            // Also check the error message is what we expect\n            let msg = res.value(py).repr().unwrap().to_string();\n            assert_eq!(msg, \"TypeError(\\\"zoneinfo.ZoneInfo(key='Europe/London') is not a fixed offset timezone\\\")\");\n        });\n    }\n\n    #[test]\n    fn test_timezone_aware_to_naive_fails() {\n        // Test that if a user tries to convert a python's timezone aware datetime into a naive\n        // one, the conversion fails.\n        Python::attach(|py| {\n            let py_datetime =\n                new_py_datetime_ob(py, \"datetime\", (2022, 1, 1, 1, 0, 0, 0, python_utc(py)));\n            // Now test that converting a PyDateTime with tzinfo to a NaiveDateTime fails\n            let res: PyResult<NaiveDateTime> = py_datetime.extract();\n            assert_eq!(\n                res.unwrap_err().value(py).repr().unwrap().to_string(),\n                \"TypeError('expected a datetime without tzinfo')\"\n            );\n        });\n    }\n\n    #[test]\n    fn test_naive_to_timezone_aware_fails() {\n        // Test that if a user tries to convert a python's timezone aware datetime into a naive\n        // one, the conversion fails.\n        Python::attach(|py| {\n            let py_datetime = new_py_datetime_ob(py, \"datetime\", (2022, 1, 1, 1, 0, 0, 0));\n            // Now test that converting a PyDateTime with tzinfo to a NaiveDateTime fails\n            let res: PyResult<DateTime<Utc>> = py_datetime.extract();\n            assert_eq!(\n                res.unwrap_err().value(py).repr().unwrap().to_string(),\n                \"TypeError('expected a datetime with non-None tzinfo')\"\n            );\n\n            // Now test that converting a PyDateTime with tzinfo to a NaiveDateTime fails\n            let res: PyResult<DateTime<FixedOffset>> = py_datetime.extract();\n            assert_eq!(\n                res.unwrap_err().value(py).repr().unwrap().to_string(),\n                \"TypeError('expected a datetime with non-None tzinfo')\"\n            );\n        });\n    }\n\n    #[test]\n    fn test_invalid_types_fail() {\n        // Test that if a user tries to convert a python's timezone aware datetime into a naive\n        // one, the conversion fails.\n        Python::attach(|py| {\n            let none = py.None().into_bound(py);\n            assert_eq!(\n                none.extract::<Duration>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'timedelta'\"\n            );\n            assert_eq!(\n                none.extract::<FixedOffset>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'tzinfo'\"\n            );\n            assert_eq!(\n                none.extract::<Utc>().unwrap_err().to_string(),\n                \"ValueError: expected datetime.timezone.utc\"\n            );\n            assert_eq!(\n                none.extract::<NaiveTime>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'time'\"\n            );\n            assert_eq!(\n                none.extract::<NaiveDate>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'date'\"\n            );\n            assert_eq!(\n                none.extract::<NaiveDateTime>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'datetime'\"\n            );\n            assert_eq!(\n                none.extract::<DateTime<Utc>>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'datetime'\"\n            );\n            assert_eq!(\n                none.extract::<DateTime<FixedOffset>>()\n                    .unwrap_err()\n                    .to_string(),\n                \"TypeError: 'None' is not an instance of 'datetime'\"\n            );\n        });\n    }\n\n    #[test]\n    fn test_pyo3_timedelta_into_pyobject() {\n        // Utility function used to check different durations.\n        // The `name` parameter is used to identify the check in case of a failure.\n        let check = |name: &'static str, delta: Duration, py_days, py_seconds, py_ms| {\n            Python::attach(|py| {\n                let delta = delta.into_pyobject(py).unwrap();\n                let py_delta = new_py_datetime_ob(py, \"timedelta\", (py_days, py_seconds, py_ms));\n                assert!(\n                    delta.eq(&py_delta).unwrap(),\n                    \"{name}: {delta} != {py_delta}\"\n                );\n            });\n        };\n\n        let delta = Duration::days(-1) + Duration::seconds(1) + Duration::microseconds(-10);\n        check(\"delta normalization\", delta, -1, 1, -10);\n\n        // Check the minimum value allowed by PyDelta, which is different\n        // from the minimum value allowed in Duration. This should pass.\n        let delta = Duration::seconds(-86399999913600); // min\n        check(\"delta min value\", delta, -999999999, 0, 0);\n\n        // Same, for max value\n        let delta = Duration::seconds(86399999999999) + Duration::nanoseconds(999999000); // max\n        check(\"delta max value\", delta, 999999999, 86399, 999999);\n\n        // Also check that trying to convert an out of bound value errors.\n        Python::attach(|py| {\n            // min_value and max_value were deprecated in chrono 0.4.39\n            #[allow(deprecated)]\n            {\n                assert!(Duration::min_value().into_pyobject(py).is_err());\n                assert!(Duration::max_value().into_pyobject(py).is_err());\n            }\n        });\n    }\n\n    #[test]\n    fn test_pyo3_timedelta_frompyobject() {\n        // Utility function used to check different durations.\n        // The `name` parameter is used to identify the check in case of a failure.\n        let check = |name: &'static str, delta: Duration, py_days, py_seconds, py_ms| {\n            Python::attach(|py| {\n                let py_delta = new_py_datetime_ob(py, \"timedelta\", (py_days, py_seconds, py_ms));\n                let py_delta: Duration = py_delta.extract().unwrap();\n                assert_eq!(py_delta, delta, \"{name}: {py_delta} != {delta}\");\n            })\n        };\n\n        // Check the minimum value allowed by PyDelta, which is different\n        // from the minimum value allowed in Duration. This should pass.\n        check(\n            \"min py_delta value\",\n            Duration::seconds(-86399999913600),\n            -999999999,\n            0,\n            0,\n        );\n        // Same, for max value\n        check(\n            \"max py_delta value\",\n            Duration::seconds(86399999999999) + Duration::microseconds(999999),\n            999999999,\n            86399,\n            999999,\n        );\n\n        // This check is to assert that we can't construct every possible Duration from a PyDelta\n        // since they have different bounds.\n        Python::attach(|py| {\n            let low_days: i32 = -1000000000;\n            // This is possible\n            assert!(panic::catch_unwind(|| Duration::days(low_days as i64)).is_ok());\n            // This panics on PyDelta::new\n            assert!(panic::catch_unwind(|| {\n                let py_delta = new_py_datetime_ob(py, \"timedelta\", (low_days, 0, 0));\n                if let Ok(_duration) = py_delta.extract::<Duration>() {\n                    // So we should never get here\n                }\n            })\n            .is_err());\n\n            let high_days: i32 = 1000000000;\n            // This is possible\n            assert!(panic::catch_unwind(|| Duration::days(high_days as i64)).is_ok());\n            // This panics on PyDelta::new\n            assert!(panic::catch_unwind(|| {\n                let py_delta = new_py_datetime_ob(py, \"timedelta\", (high_days, 0, 0));\n                if let Ok(_duration) = py_delta.extract::<Duration>() {\n                    // So we should never get here\n                }\n            })\n            .is_err());\n        });\n    }\n\n    #[test]\n    fn test_pyo3_date_into_pyobject() {\n        let eq_ymd = |name: &'static str, year, month, day| {\n            Python::attach(|py| {\n                let date = NaiveDate::from_ymd_opt(year, month, day)\n                    .unwrap()\n                    .into_pyobject(py)\n                    .unwrap();\n                let py_date = new_py_datetime_ob(py, \"date\", (year, month, day));\n                assert_eq!(\n                    date.compare(&py_date).unwrap(),\n                    Ordering::Equal,\n                    \"{name}: {date} != {py_date}\"\n                );\n            })\n        };\n\n        eq_ymd(\"past date\", 2012, 2, 29);\n        eq_ymd(\"min date\", 1, 1, 1);\n        eq_ymd(\"future date\", 3000, 6, 5);\n        eq_ymd(\"max date\", 9999, 12, 31);\n    }\n\n    #[test]\n    fn test_pyo3_date_frompyobject() {\n        let eq_ymd = |name: &'static str, year, month, day| {\n            Python::attach(|py| {\n                let py_date = new_py_datetime_ob(py, \"date\", (year, month, day));\n                let py_date: NaiveDate = py_date.extract().unwrap();\n                let date = NaiveDate::from_ymd_opt(year, month, day).unwrap();\n                assert_eq!(py_date, date, \"{name}: {date} != {py_date}\");\n            })\n        };\n\n        eq_ymd(\"past date\", 2012, 2, 29);\n        eq_ymd(\"min date\", 1, 1, 1);\n        eq_ymd(\"future date\", 3000, 6, 5);\n        eq_ymd(\"max date\", 9999, 12, 31);\n    }\n\n    #[test]\n    fn test_pyo3_datetime_into_pyobject_utc() {\n        Python::attach(|py| {\n            let check_utc =\n                |name: &'static str, year, month, day, hour, minute, second, ms, py_ms| {\n                    let datetime = NaiveDate::from_ymd_opt(year, month, day)\n                        .unwrap()\n                        .and_hms_micro_opt(hour, minute, second, ms)\n                        .unwrap()\n                        .and_utc();\n                    let datetime = datetime.into_pyobject(py).unwrap();\n                    let py_datetime = new_py_datetime_ob(\n                        py,\n                        \"datetime\",\n                        (\n                            year,\n                            month,\n                            day,\n                            hour,\n                            minute,\n                            second,\n                            py_ms,\n                            python_utc(py),\n                        ),\n                    );\n                    assert_eq!(\n                        datetime.compare(&py_datetime).unwrap(),\n                        Ordering::Equal,\n                        \"{name}: {datetime} != {py_datetime}\"\n                    );\n                };\n\n            check_utc(\"regular\", 2014, 5, 6, 7, 8, 9, 999_999, 999_999);\n\n            assert_warnings!(\n                py,\n                check_utc(\"leap second\", 2014, 5, 6, 7, 8, 59, 1_999_999, 999_999),\n                [(\n                    PyUserWarning,\n                    \"ignored leap-second, `datetime` does not support leap-seconds\"\n                )]\n            );\n        })\n    }\n\n    #[test]\n    fn test_pyo3_datetime_into_pyobject_fixed_offset() {\n        Python::attach(|py| {\n            let check_fixed_offset =\n                |name: &'static str, year, month, day, hour, minute, second, ms, py_ms| {\n                    let offset = FixedOffset::east_opt(3600).unwrap();\n                    let datetime = NaiveDate::from_ymd_opt(year, month, day)\n                        .unwrap()\n                        .and_hms_micro_opt(hour, minute, second, ms)\n                        .unwrap()\n                        .and_local_timezone(offset)\n                        .unwrap();\n                    let datetime = datetime.into_pyobject(py).unwrap();\n                    let py_tz = offset.into_pyobject(py).unwrap();\n                    let py_datetime = new_py_datetime_ob(\n                        py,\n                        \"datetime\",\n                        (year, month, day, hour, minute, second, py_ms, py_tz),\n                    );\n                    assert_eq!(\n                        datetime.compare(&py_datetime).unwrap(),\n                        Ordering::Equal,\n                        \"{name}: {datetime} != {py_datetime}\"\n                    );\n                };\n\n            check_fixed_offset(\"regular\", 2014, 5, 6, 7, 8, 9, 999_999, 999_999);\n\n            assert_warnings!(\n                py,\n                check_fixed_offset(\"leap second\", 2014, 5, 6, 7, 8, 59, 1_999_999, 999_999),\n                [(\n                    PyUserWarning,\n                    \"ignored leap-second, `datetime` does not support leap-seconds\"\n                )]\n            );\n        })\n    }\n\n    #[test]\n    #[cfg(all(Py_3_9, feature = \"chrono-tz\", not(windows)))]\n    fn test_pyo3_datetime_into_pyobject_tz() {\n        Python::attach(|py| {\n            let datetime = NaiveDate::from_ymd_opt(2024, 12, 11)\n                .unwrap()\n                .and_hms_opt(23, 3, 13)\n                .unwrap()\n                .and_local_timezone(chrono_tz::Tz::Europe__London)\n                .unwrap();\n            let datetime = datetime.into_pyobject(py).unwrap();\n            let py_datetime = new_py_datetime_ob(\n                py,\n                \"datetime\",\n                (\n                    2024,\n                    12,\n                    11,\n                    23,\n                    3,\n                    13,\n                    0,\n                    python_zoneinfo(py, \"Europe/London\"),\n                ),\n            );\n            assert_eq!(datetime.compare(&py_datetime).unwrap(), Ordering::Equal);\n        })\n    }\n\n    #[test]\n    fn test_pyo3_datetime_frompyobject_utc() {\n        Python::attach(|py| {\n            let year = 2014;\n            let month = 5;\n            let day = 6;\n            let hour = 7;\n            let minute = 8;\n            let second = 9;\n            let micro = 999_999;\n            let tz_utc = PyTzInfo::utc(py).unwrap();\n            let py_datetime = new_py_datetime_ob(\n                py,\n                \"datetime\",\n                (year, month, day, hour, minute, second, micro, tz_utc),\n            );\n            let py_datetime: DateTime<Utc> = py_datetime.extract().unwrap();\n            let datetime = NaiveDate::from_ymd_opt(year, month, day)\n                .unwrap()\n                .and_hms_micro_opt(hour, minute, second, micro)\n                .unwrap()\n                .and_utc();\n            assert_eq!(py_datetime, datetime,);\n        })\n    }\n\n    #[test]\n    #[cfg(feature = \"chrono-local\")]\n    fn test_pyo3_naive_datetime_frompyobject_local() {\n        Python::attach(|py| {\n            let year = 2014;\n            let month = 5;\n            let day = 6;\n            let hour = 7;\n            let minute = 8;\n            let second = 9;\n            let micro = 999_999;\n            let py_datetime = new_py_datetime_ob(\n                py,\n                \"datetime\",\n                (year, month, day, hour, minute, second, micro),\n            );\n            let py_datetime: DateTime<Local> = py_datetime.extract().unwrap();\n            let expected_datetime = NaiveDate::from_ymd_opt(year, month, day)\n                .unwrap()\n                .and_hms_micro_opt(hour, minute, second, micro)\n                .unwrap()\n                .and_local_timezone(Local)\n                .unwrap();\n            assert_eq!(py_datetime, expected_datetime);\n        })\n    }\n\n    #[test]\n    fn test_pyo3_datetime_frompyobject_fixed_offset() {\n        Python::attach(|py| {\n            let year = 2014;\n            let month = 5;\n            let day = 6;\n            let hour = 7;\n            let minute = 8;\n            let second = 9;\n            let micro = 999_999;\n            let offset = FixedOffset::east_opt(3600).unwrap();\n            let py_tz = offset.into_pyobject(py).unwrap();\n            let py_datetime = new_py_datetime_ob(\n                py,\n                \"datetime\",\n                (year, month, day, hour, minute, second, micro, py_tz),\n            );\n            let datetime_from_py: DateTime<FixedOffset> = py_datetime.extract().unwrap();\n            let datetime = NaiveDate::from_ymd_opt(year, month, day)\n                .unwrap()\n                .and_hms_micro_opt(hour, minute, second, micro)\n                .unwrap();\n            let datetime = datetime.and_local_timezone(offset).unwrap();\n\n            assert_eq!(datetime_from_py, datetime);\n            assert!(\n                py_datetime.extract::<DateTime<Utc>>().is_err(),\n                \"Extracting Utc from nonzero FixedOffset timezone will fail\"\n            );\n\n            let utc = python_utc(py);\n            let py_datetime_utc = new_py_datetime_ob(\n                py,\n                \"datetime\",\n                (year, month, day, hour, minute, second, micro, utc),\n            );\n            assert!(\n                py_datetime_utc.extract::<DateTime<FixedOffset>>().is_ok(),\n                \"Extracting FixedOffset from Utc timezone will succeed\"\n            );\n        })\n    }\n\n    #[test]\n    fn test_pyo3_offset_fixed_into_pyobject() {\n        Python::attach(|py| {\n            // Chrono offset\n            let offset = FixedOffset::east_opt(3600)\n                .unwrap()\n                .into_pyobject(py)\n                .unwrap();\n            // Python timezone from timedelta\n            let td = new_py_datetime_ob(py, \"timedelta\", (0, 3600, 0));\n            let py_timedelta = new_py_datetime_ob(py, \"timezone\", (td,));\n            // Should be equal\n            assert!(offset.eq(py_timedelta).unwrap());\n\n            // Same but with negative values\n            let offset = FixedOffset::east_opt(-3600)\n                .unwrap()\n                .into_pyobject(py)\n                .unwrap();\n            let td = new_py_datetime_ob(py, \"timedelta\", (0, -3600, 0));\n            let py_timedelta = new_py_datetime_ob(py, \"timezone\", (td,));\n            assert!(offset.eq(py_timedelta).unwrap());\n        })\n    }\n\n    #[test]\n    fn test_pyo3_offset_fixed_frompyobject() {\n        Python::attach(|py| {\n            let py_timedelta = new_py_datetime_ob(py, \"timedelta\", (0, 3600, 0));\n            let py_tzinfo = new_py_datetime_ob(py, \"timezone\", (py_timedelta,));\n            let offset: FixedOffset = py_tzinfo.extract().unwrap();\n            assert_eq!(FixedOffset::east_opt(3600).unwrap(), offset);\n        })\n    }\n\n    #[test]\n    fn test_pyo3_offset_utc_into_pyobject() {\n        Python::attach(|py| {\n            let utc = Utc.into_pyobject(py).unwrap();\n            let py_utc = python_utc(py);\n            assert!(utc.is(&py_utc));\n        })\n    }\n\n    #[test]\n    fn test_pyo3_offset_utc_frompyobject() {\n        Python::attach(|py| {\n            let py_utc = python_utc(py);\n            let py_utc: Utc = py_utc.extract().unwrap();\n            assert_eq!(Utc, py_utc);\n\n            let py_timedelta = new_py_datetime_ob(py, \"timedelta\", (0, 0, 0));\n            let py_timezone_utc = new_py_datetime_ob(py, \"timezone\", (py_timedelta,));\n            let py_timezone_utc: Utc = py_timezone_utc.extract().unwrap();\n            assert_eq!(Utc, py_timezone_utc);\n\n            let py_timedelta = new_py_datetime_ob(py, \"timedelta\", (0, 3600, 0));\n            let py_timezone = new_py_datetime_ob(py, \"timezone\", (py_timedelta,));\n            assert!(py_timezone.extract::<Utc>().is_err());\n        })\n    }\n\n    #[test]\n    fn test_pyo3_time_into_pyobject() {\n        Python::attach(|py| {\n            let check_time = |name: &'static str, hour, minute, second, ms, py_ms| {\n                let time = NaiveTime::from_hms_micro_opt(hour, minute, second, ms)\n                    .unwrap()\n                    .into_pyobject(py)\n                    .unwrap();\n                let py_time = new_py_datetime_ob(py, \"time\", (hour, minute, second, py_ms));\n                assert!(time.eq(&py_time).unwrap(), \"{name}: {time} != {py_time}\");\n            };\n\n            check_time(\"regular\", 3, 5, 7, 999_999, 999_999);\n\n            assert_warnings!(\n                py,\n                check_time(\"leap second\", 3, 5, 59, 1_999_999, 999_999),\n                [(\n                    PyUserWarning,\n                    \"ignored leap-second, `datetime` does not support leap-seconds\"\n                )]\n            );\n        })\n    }\n\n    #[test]\n    fn test_pyo3_time_frompyobject() {\n        let hour = 3;\n        let minute = 5;\n        let second = 7;\n        let micro = 999_999;\n        Python::attach(|py| {\n            let py_time = new_py_datetime_ob(py, \"time\", (hour, minute, second, micro));\n            let py_time: NaiveTime = py_time.extract().unwrap();\n            let time = NaiveTime::from_hms_micro_opt(hour, minute, second, micro).unwrap();\n            assert_eq!(py_time, time);\n        })\n    }\n\n    fn new_py_datetime_ob<'py, A>(py: Python<'py>, name: &str, args: A) -> Bound<'py, PyAny>\n    where\n        A: IntoPyObject<'py, Target = PyTuple>,\n    {\n        py.import(\"datetime\")\n            .unwrap()\n            .getattr(name)\n            .unwrap()\n            .call1(\n                args.into_pyobject(py)\n                    .map_err(Into::into)\n                    .unwrap()\n                    .into_bound(),\n            )\n            .unwrap()\n    }\n\n    fn python_utc(py: Python<'_>) -> Bound<'_, PyAny> {\n        py.import(\"datetime\")\n            .unwrap()\n            .getattr(\"timezone\")\n            .unwrap()\n            .getattr(\"utc\")\n            .unwrap()\n    }\n\n    #[cfg(all(Py_3_9, feature = \"chrono-tz\", not(windows)))]\n    fn python_zoneinfo<'py>(py: Python<'py>, timezone: &str) -> Bound<'py, PyAny> {\n        py.import(\"zoneinfo\")\n            .unwrap()\n            .getattr(\"ZoneInfo\")\n            .unwrap()\n            .call1((timezone,))\n            .unwrap()\n    }\n\n    #[cfg(not(any(target_arch = \"wasm32\")))]\n    mod proptests {\n        use super::*;\n        use crate::test_utils::CatchWarnings;\n        use crate::types::IntoPyDict;\n        use proptest::prelude::*;\n        use std::ffi::CString;\n\n        proptest! {\n\n            // Range is limited to 1970 to 2038 due to windows limitations\n            #[test]\n            fn test_pyo3_offset_fixed_frompyobject_created_in_python(timestamp in 0..(i32::MAX as i64), timedelta in -86399i32..=86399i32) {\n                Python::attach(|py| {\n\n                    let globals = [(\"datetime\", py.import(\"datetime\").unwrap())].into_py_dict(py).unwrap();\n                    let code = format!(\"datetime.datetime.fromtimestamp({timestamp}).replace(tzinfo=datetime.timezone(datetime.timedelta(seconds={timedelta})))\");\n                    let t = py.eval(&CString::new(code).unwrap(), Some(&globals), None).unwrap();\n\n                    // Get ISO 8601 string from python\n                    let py_iso_str = t.call_method0(\"isoformat\").unwrap();\n\n                    // Get ISO 8601 string from rust\n                    let t = t.extract::<DateTime<FixedOffset>>().unwrap();\n                    // Python doesn't print the seconds of the offset if they are 0\n                    let rust_iso_str = if timedelta % 60 == 0 {\n                        t.format(\"%Y-%m-%dT%H:%M:%S%:z\").to_string()\n                    } else {\n                        t.format(\"%Y-%m-%dT%H:%M:%S%::z\").to_string()\n                    };\n\n                    // They should be equal\n                    assert_eq!(py_iso_str.to_string(), rust_iso_str);\n                })\n            }\n\n            #[test]\n            fn test_duration_roundtrip(days in -999999999i64..=999999999i64) {\n                // Test roundtrip conversion rust->python->rust for all allowed\n                // python values of durations (from -999999999 to 999999999 days),\n                Python::attach(|py| {\n                    let dur = Duration::days(days);\n                    let py_delta = dur.into_pyobject(py).unwrap();\n                    let roundtripped: Duration = py_delta.extract().expect(\"Round trip\");\n                    assert_eq!(dur, roundtripped);\n                })\n            }\n\n            #[test]\n            fn test_fixed_offset_roundtrip(secs in -86399i32..=86399i32) {\n                Python::attach(|py| {\n                    let offset = FixedOffset::east_opt(secs).unwrap();\n                    let py_offset = offset.into_pyobject(py).unwrap();\n                    let roundtripped: FixedOffset = py_offset.extract().expect(\"Round trip\");\n                    assert_eq!(offset, roundtripped);\n                })\n            }\n\n            #[test]\n            fn test_naive_date_roundtrip(\n                year in 1i32..=9999i32,\n                month in 1u32..=12u32,\n                day in 1u32..=31u32\n            ) {\n                // Test roundtrip conversion rust->python->rust for all allowed\n                // python dates (from year 1 to year 9999)\n                Python::attach(|py| {\n                    // We use to `from_ymd_opt` constructor so that we only test valid `NaiveDate`s.\n                    // This is to skip the test if we are creating an invalid date, like February 31.\n                    if let Some(date) = NaiveDate::from_ymd_opt(year, month, day) {\n                        let py_date = date.into_pyobject(py).unwrap();\n                        let roundtripped: NaiveDate = py_date.extract().expect(\"Round trip\");\n                        assert_eq!(date, roundtripped);\n                    }\n                })\n            }\n\n            #[test]\n            fn test_naive_time_roundtrip(\n                hour in 0u32..=23u32,\n                min in 0u32..=59u32,\n                sec in 0u32..=59u32,\n                micro in 0u32..=1_999_999u32\n            ) {\n                // Test roundtrip conversion rust->python->rust for naive times.\n                // Python time has a resolution of microseconds, so we only test\n                // NaiveTimes with microseconds resolution, even if NaiveTime has nanosecond\n                // resolution.\n                Python::attach(|py| {\n                    if let Some(time) = NaiveTime::from_hms_micro_opt(hour, min, sec, micro) {\n                        // Wrap in CatchWarnings to avoid to_object firing warning for truncated leap second\n                        let py_time = CatchWarnings::enter(py, |_| time.into_pyobject(py)).unwrap();\n                        let roundtripped: NaiveTime = py_time.extract().expect(\"Round trip\");\n                        // Leap seconds are not roundtripped\n                        let expected_roundtrip_time = micro.checked_sub(1_000_000).map(|micro| NaiveTime::from_hms_micro_opt(hour, min, sec, micro).unwrap()).unwrap_or(time);\n                        assert_eq!(expected_roundtrip_time, roundtripped);\n                    }\n                })\n            }\n\n            #[test]\n            fn test_naive_datetime_roundtrip(\n                year in 1i32..=9999i32,\n                month in 1u32..=12u32,\n                day in 1u32..=31u32,\n                hour in 0u32..=24u32,\n                min in 0u32..=60u32,\n                sec in 0u32..=60u32,\n                micro in 0u32..=999_999u32\n            ) {\n                Python::attach(|py| {\n                    let date_opt = NaiveDate::from_ymd_opt(year, month, day);\n                    let time_opt = NaiveTime::from_hms_micro_opt(hour, min, sec, micro);\n                    if let (Some(date), Some(time)) = (date_opt, time_opt) {\n                        let dt = NaiveDateTime::new(date, time);\n                        let pydt = dt.into_pyobject(py).unwrap();\n                        let roundtripped: NaiveDateTime = pydt.extract().expect(\"Round trip\");\n                        assert_eq!(dt, roundtripped);\n                    }\n                })\n            }\n\n            #[test]\n            fn test_utc_datetime_roundtrip(\n                year in 1i32..=9999i32,\n                month in 1u32..=12u32,\n                day in 1u32..=31u32,\n                hour in 0u32..=23u32,\n                min in 0u32..=59u32,\n                sec in 0u32..=59u32,\n                micro in 0u32..=1_999_999u32\n            ) {\n                Python::attach(|py| {\n                    let date_opt = NaiveDate::from_ymd_opt(year, month, day);\n                    let time_opt = NaiveTime::from_hms_micro_opt(hour, min, sec, micro);\n                    if let (Some(date), Some(time)) = (date_opt, time_opt) {\n                        let dt: DateTime<Utc> = NaiveDateTime::new(date, time).and_utc();\n                        // Wrap in CatchWarnings to avoid into_py firing warning for truncated leap second\n                        let py_dt = CatchWarnings::enter(py, |_| dt.into_pyobject(py)).unwrap();\n                        let roundtripped: DateTime<Utc> = py_dt.extract().expect(\"Round trip\");\n                        // Leap seconds are not roundtripped\n                        let expected_roundtrip_time = micro.checked_sub(1_000_000).map(|micro| NaiveTime::from_hms_micro_opt(hour, min, sec, micro).unwrap()).unwrap_or(time);\n                        let expected_roundtrip_dt: DateTime<Utc> = NaiveDateTime::new(date, expected_roundtrip_time).and_utc();\n                        assert_eq!(expected_roundtrip_dt, roundtripped);\n                    }\n                })\n            }\n\n            #[test]\n            fn test_fixed_offset_datetime_roundtrip(\n                year in 1i32..=9999i32,\n                month in 1u32..=12u32,\n                day in 1u32..=31u32,\n                hour in 0u32..=23u32,\n                min in 0u32..=59u32,\n                sec in 0u32..=59u32,\n                micro in 0u32..=1_999_999u32,\n                offset_secs in -86399i32..=86399i32\n            ) {\n                Python::attach(|py| {\n                    let date_opt = NaiveDate::from_ymd_opt(year, month, day);\n                    let time_opt = NaiveTime::from_hms_micro_opt(hour, min, sec, micro);\n                    let offset = FixedOffset::east_opt(offset_secs).unwrap();\n                    if let (Some(date), Some(time)) = (date_opt, time_opt) {\n                        let dt: DateTime<FixedOffset> = NaiveDateTime::new(date, time).and_local_timezone(offset).unwrap();\n                        // Wrap in CatchWarnings to avoid into_py firing warning for truncated leap second\n                        let py_dt = CatchWarnings::enter(py, |_| dt.into_pyobject(py)).unwrap();\n                        let roundtripped: DateTime<FixedOffset> = py_dt.extract().expect(\"Round trip\");\n                        // Leap seconds are not roundtripped\n                        let expected_roundtrip_time = micro.checked_sub(1_000_000).map(|micro| NaiveTime::from_hms_micro_opt(hour, min, sec, micro).unwrap()).unwrap_or(time);\n                        let expected_roundtrip_dt: DateTime<FixedOffset> = NaiveDateTime::new(date, expected_roundtrip_time).and_local_timezone(offset).unwrap();\n                        assert_eq!(expected_roundtrip_dt, roundtripped);\n                    }\n                })\n            }\n\n            #[test]\n            #[cfg(all(feature = \"chrono-local\", not(target_os = \"windows\")))]\n            fn test_local_datetime_roundtrip(\n                year in 1i32..=9999i32,\n                month in 1u32..=12u32,\n                day in 1u32..=31u32,\n                hour in 0u32..=23u32,\n                min in 0u32..=59u32,\n                sec in 0u32..=59u32,\n                micro in 0u32..=1_999_999u32,\n            ) {\n                Python::attach(|py| {\n                    let date_opt = NaiveDate::from_ymd_opt(year, month, day);\n                    let time_opt = NaiveTime::from_hms_micro_opt(hour, min, sec, micro);\n                    if let (Some(date), Some(time)) = (date_opt, time_opt) {\n                        let dts = match NaiveDateTime::new(date, time).and_local_timezone(Local) {\n                            LocalResult::None => return,\n                            LocalResult::Single(dt) => [Some((dt, false)), None],\n                            LocalResult::Ambiguous(dt1, dt2) => [Some((dt1, false)), Some((dt2, true))],\n                        };\n                        for (dt, fold) in dts.iter().filter_map(|input| *input) {\n                            // Wrap in CatchWarnings to avoid into_py firing warning for truncated leap second\n                            let py_dt = CatchWarnings::enter(py, |_| dt.into_pyobject(py)).unwrap();\n                            let roundtripped: DateTime<Local> = py_dt.extract().expect(\"Round trip\");\n                            // Leap seconds are not roundtripped\n                            let expected_roundtrip_time = micro.checked_sub(1_000_000).map(|micro| NaiveTime::from_hms_micro_opt(hour, min, sec, micro).unwrap()).unwrap_or(time);\n                            let expected_roundtrip_dt: DateTime<Local> = if fold {\n                                NaiveDateTime::new(date, expected_roundtrip_time).and_local_timezone(Local).latest()\n                            } else {\n                                NaiveDateTime::new(date, expected_roundtrip_time).and_local_timezone(Local).earliest()\n                            }.unwrap();\n                            assert_eq!(expected_roundtrip_dt, roundtripped);\n                        }\n                    }\n                })\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/conversions/chrono_tz.rs",
    "content": "#![cfg(all(Py_3_9, feature = \"chrono-tz\"))]\n\n//! Conversions to and from [chrono-tz](https://docs.rs/chrono-tz/)’s `Tz`.\n//!\n//! This feature requires at least Python 3.9.\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! chrono-tz = \"0.8\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"chrono-tz\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of chrono, chrono-tz and PyO3.\n//! The required chrono version may vary based on the version of PyO3.\n//!\n//! # Example: Convert a `zoneinfo.ZoneInfo` to chrono-tz's `Tz`\n//!\n//! ```rust,no_run\n//! use chrono_tz::Tz;\n//! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods};\n//!\n//! fn main() -> PyResult<()> {\n//!     Python::initialize();\n//!     Python::attach(|py| {\n//!         // Convert to Python\n//!         let py_tzinfo = Tz::Europe__Paris.into_pyobject(py)?;\n//!         // Convert back to Rust\n//!         assert_eq!(py_tzinfo.extract::<Tz>()?, Tz::Europe__Paris);\n//!         Ok(())\n//!     })\n//! }\n//! ```\nuse crate::conversion::IntoPyObject;\nuse crate::exceptions::PyValueError;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_hint_identifier;\nuse crate::types::{any::PyAnyMethods, PyTzInfo};\n#[cfg(all(feature = \"experimental-inspect\", not(Py_3_9)))]\nuse crate::PyTypeInfo;\nuse crate::{intern, Borrowed, Bound, FromPyObject, PyAny, PyErr, Python};\nuse chrono_tz::Tz;\nuse std::borrow::Cow;\nuse std::str::FromStr;\n\nimpl<'py> IntoPyObject<'py> for Tz {\n    type Target = PyTzInfo;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(all(feature = \"experimental-inspect\", Py_3_9))]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"zoneinfo\", \"ZoneInfo\");\n\n    #[cfg(all(feature = \"experimental-inspect\", not(Py_3_9)))]\n    const OUTPUT_TYPE: PyStaticExpr = PyTzInfo::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        PyTzInfo::timezone(py, self.name())\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Tz {\n    type Target = PyTzInfo;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Tz::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl FromPyObject<'_, '_> for Tz {\n    type Error = PyErr;\n\n    #[cfg(all(feature = \"experimental-inspect\", Py_3_9))]\n    const INPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"zoneinfo\", \"ZoneInfo\");\n\n    #[cfg(all(feature = \"experimental-inspect\", not(Py_3_9)))]\n    const INPUT_TYPE: PyStaticExpr = PyTzInfo::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        Tz::from_str(\n            &ob.getattr(intern!(ob.py(), \"key\"))?\n                .extract::<Cow<'_, str>>()?,\n        )\n        .map_err(|e| PyValueError::new_err(e.to_string()))\n    }\n}\n\n#[cfg(all(test, not(windows)))] // Troubles loading timezones on Windows\nmod tests {\n    use super::*;\n    use crate::prelude::PyAnyMethods;\n    use crate::types::IntoPyDict;\n    use crate::types::PyTzInfo;\n    use crate::Bound;\n    use crate::Python;\n    use chrono::offset::LocalResult;\n    use chrono::NaiveDate;\n    use chrono::{DateTime, Utc};\n    use chrono_tz::Tz;\n\n    #[test]\n    fn test_frompyobject() {\n        Python::attach(|py| {\n            assert_eq!(\n                new_zoneinfo(py, \"Europe/Paris\").extract::<Tz>().unwrap(),\n                Tz::Europe__Paris\n            );\n            assert_eq!(new_zoneinfo(py, \"UTC\").extract::<Tz>().unwrap(), Tz::UTC);\n            assert_eq!(\n                new_zoneinfo(py, \"Etc/GMT-5\").extract::<Tz>().unwrap(),\n                Tz::Etc__GMTMinus5\n            );\n        });\n    }\n\n    #[test]\n    fn test_ambiguous_datetime_to_pyobject() {\n        let dates = [\n            DateTime::<Utc>::from_str(\"2020-10-24 23:00:00 UTC\").unwrap(),\n            DateTime::<Utc>::from_str(\"2020-10-25 00:00:00 UTC\").unwrap(),\n            DateTime::<Utc>::from_str(\"2020-10-25 01:00:00 UTC\").unwrap(),\n        ];\n\n        let dates = dates.map(|dt| dt.with_timezone(&Tz::Europe__London));\n\n        assert_eq!(\n            dates.map(|dt| dt.to_string()),\n            [\n                \"2020-10-25 00:00:00 BST\",\n                \"2020-10-25 01:00:00 BST\",\n                \"2020-10-25 01:00:00 GMT\"\n            ]\n        );\n\n        let dates = Python::attach(|py| {\n            let pydates = dates.map(|dt| dt.into_pyobject(py).unwrap());\n            assert_eq!(\n                pydates\n                    .clone()\n                    .map(|dt| dt.getattr(\"hour\").unwrap().extract::<usize>().unwrap()),\n                [0, 1, 1]\n            );\n\n            assert_eq!(\n                pydates\n                    .clone()\n                    .map(|dt| dt.getattr(\"fold\").unwrap().extract::<usize>().unwrap() > 0),\n                [false, false, true]\n            );\n\n            pydates.map(|dt| dt.extract::<DateTime<Tz>>().unwrap())\n        });\n\n        assert_eq!(\n            dates.map(|dt| dt.to_string()),\n            [\n                \"2020-10-25 00:00:00 BST\",\n                \"2020-10-25 01:00:00 BST\",\n                \"2020-10-25 01:00:00 GMT\"\n            ]\n        );\n    }\n\n    #[test]\n    fn test_nonexistent_datetime_from_pyobject() {\n        // Pacific_Apia skipped the 30th of December 2011 entirely\n\n        let naive_dt = NaiveDate::from_ymd_opt(2011, 12, 30)\n            .unwrap()\n            .and_hms_opt(2, 0, 0)\n            .unwrap();\n        let tz = Tz::Pacific__Apia;\n\n        // sanity check\n        assert_eq!(naive_dt.and_local_timezone(tz), LocalResult::None);\n\n        Python::attach(|py| {\n            // create as a Python object manually\n            let py_tz = tz.into_pyobject(py).unwrap();\n            let py_dt_naive = naive_dt.into_pyobject(py).unwrap();\n            let py_dt = py_dt_naive\n                .call_method(\n                    \"replace\",\n                    (),\n                    Some(&[(\"tzinfo\", py_tz)].into_py_dict(py).unwrap()),\n                )\n                .unwrap();\n\n            // now try to extract\n            let err = py_dt.extract::<DateTime<Tz>>().unwrap_err();\n            assert_eq!(err.to_string(), \"ValueError: The datetime datetime.datetime(2011, 12, 30, 2, 0, tzinfo=zoneinfo.ZoneInfo(key='Pacific/Apia')) contains an incompatible timezone\");\n        });\n    }\n\n    #[test]\n    #[cfg(not(Py_GIL_DISABLED))] // https://github.com/python/cpython/issues/116738#issuecomment-2404360445\n    fn test_into_pyobject() {\n        Python::attach(|py| {\n            let assert_eq = |l: Bound<'_, PyTzInfo>, r: Bound<'_, PyTzInfo>| {\n                assert!(l.eq(&r).unwrap(), \"{l:?} != {r:?}\");\n            };\n\n            assert_eq(\n                Tz::Europe__Paris.into_pyobject(py).unwrap(),\n                new_zoneinfo(py, \"Europe/Paris\"),\n            );\n            assert_eq(Tz::UTC.into_pyobject(py).unwrap(), new_zoneinfo(py, \"UTC\"));\n            assert_eq(\n                Tz::Etc__GMTMinus5.into_pyobject(py).unwrap(),\n                new_zoneinfo(py, \"Etc/GMT-5\"),\n            );\n        });\n    }\n\n    fn new_zoneinfo<'py>(py: Python<'py>, name: &str) -> Bound<'py, PyTzInfo> {\n        PyTzInfo::timezone(py, name).unwrap()\n    }\n}\n"
  },
  {
    "path": "src/conversions/either.rs",
    "content": "#![cfg(feature = \"either\")]\n\n//! Conversion to/from\n//! [either](https://docs.rs/either/ \"A library for easy idiomatic error handling and reporting in Rust applications\")’s\n//! [`Either`] type to a union of two Python types.\n//!\n//! Use of a generic sum type like [either] is common when you want to either accept one of two possible\n//! types as an argument or return one of two possible types from a function, without having to define\n//! a helper type manually yourself.\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! ## change * to the version you want to use, ideally the latest.\n//! either = \"*\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"either\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of either and PyO3.\n//! The required either version may vary based on the version of PyO3.\n//!\n//! # Example: Convert a `int | str` to `Either<i32, String>`.\n//!\n//! ```rust\n//! use either::Either;\n//! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods};\n//!\n//! fn main() -> PyResult<()> {\n//!     Python::initialize();\n//!     Python::attach(|py| {\n//!         // Create a string and an int in Python.\n//!         let py_str = \"crab\".into_pyobject(py)?;\n//!         let py_int = 42i32.into_pyobject(py)?;\n//!         // Now convert it to an Either<i32, String>.\n//!         let either_str: Either<i32, String> = py_str.extract()?;\n//!         let either_int: Either<i32, String> = py_int.extract()?;\n//!         Ok(())\n//!     })\n//! }\n//! ```\n//!\n//! [either](https://docs.rs/either/ \"A library for easy idiomatic error handling and reporting in Rust applications\")’s\n\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_hint_union;\nuse crate::{\n    exceptions::PyTypeError, Borrowed, Bound, FromPyObject, IntoPyObject, IntoPyObjectExt, PyAny,\n    PyErr, Python,\n};\nuse either::Either;\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"either\")))]\nimpl<'py, L, R> IntoPyObject<'py> for Either<L, R>\nwhere\n    L: IntoPyObject<'py>,\n    R: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_union!(L::OUTPUT_TYPE, R::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        match self {\n            Either::Left(l) => l.into_bound_py_any(py),\n            Either::Right(r) => r.into_bound_py_any(py),\n        }\n    }\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"either\")))]\nimpl<'a, 'py, L, R> IntoPyObject<'py> for &'a Either<L, R>\nwhere\n    &'a L: IntoPyObject<'py>,\n    &'a R: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_union!(<&L>::OUTPUT_TYPE, <&R>::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        match self {\n            Either::Left(l) => l.into_bound_py_any(py),\n            Either::Right(r) => r.into_bound_py_any(py),\n        }\n    }\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"either\")))]\nimpl<'a, 'py, L, R> FromPyObject<'a, 'py> for Either<L, R>\nwhere\n    L: FromPyObject<'a, 'py>,\n    R: FromPyObject<'a, 'py>,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_union!(L::INPUT_TYPE, R::INPUT_TYPE);\n\n    #[inline]\n    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        if let Ok(l) = obj.extract::<L>() {\n            Ok(Either::Left(l))\n        } else if let Ok(r) = obj.extract::<R>() {\n            Ok(Either::Right(r))\n        } else {\n            // TODO: it might be nice to use the `type_input()` name here once `type_input`\n            // is not experimental, rather than the Rust type names.\n            let err_msg = format!(\n                \"failed to convert the value to 'Union[{}, {}]'\",\n                std::any::type_name::<L>(),\n                std::any::type_name::<R>()\n            );\n            Err(PyTypeError::new_err(err_msg))\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::borrow::Cow;\n\n    use crate::exceptions::PyTypeError;\n    use crate::{IntoPyObject, Python};\n\n    use crate::types::PyAnyMethods;\n    use either::Either;\n\n    #[test]\n    fn test_either_conversion() {\n        type E = Either<i32, String>;\n        type E1 = Either<i32, f32>;\n        type E2 = Either<f32, i32>;\n\n        Python::attach(|py| {\n            let l = E::Left(42);\n            let obj_l = (&l).into_pyobject(py).unwrap();\n            assert_eq!(obj_l.extract::<i32>().unwrap(), 42);\n            assert_eq!(obj_l.extract::<E>().unwrap(), l);\n\n            let r = E::Right(\"foo\".to_owned());\n            let obj_r = (&r).into_pyobject(py).unwrap();\n            assert_eq!(obj_r.extract::<Cow<'_, str>>().unwrap(), \"foo\");\n            assert_eq!(obj_r.extract::<E>().unwrap(), r);\n\n            let obj_s = \"foo\".into_pyobject(py).unwrap();\n            let err = obj_s.extract::<E1>().unwrap_err();\n            assert!(err.is_instance_of::<PyTypeError>(py));\n            assert_eq!(\n                err.to_string(),\n                \"TypeError: failed to convert the value to 'Union[i32, f32]'\"\n            );\n\n            let obj_i = 42i32.into_pyobject(py).unwrap();\n            assert_eq!(obj_i.extract::<E1>().unwrap(), E1::Left(42));\n            assert_eq!(obj_i.extract::<E2>().unwrap(), E2::Left(42.0));\n\n            let obj_f = 42.0f64.into_pyobject(py).unwrap();\n            assert_eq!(obj_f.extract::<E1>().unwrap(), E1::Right(42.0));\n            assert_eq!(obj_f.extract::<E2>().unwrap(), E2::Left(42.0));\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/eyre.rs",
    "content": "#![cfg(feature = \"eyre\")]\n\n//! A conversion from\n//! [eyre](https://docs.rs/eyre/ \"A library for easy idiomatic error handling and reporting in Rust applications.\")’s\n//! [`Report`] type to [`PyErr`].\n//!\n//! Use of an error handling library like [eyre] is common in application code and when you just\n//! want error handling to be easy. If you are writing a library or you need more control over your\n//! errors you might want to design your own error type instead.\n//!\n//! When the inner error is a [`PyErr`] without source, it will be extracted out.\n//! Otherwise a Python [`RuntimeError`] will be created.\n//! You might find that you need to map the error from your Rust code into another Python exception.\n//! See [`PyErr::new`] for more information about that.\n//!\n//! For information about error handling in general, see the [Error handling] chapter of the Rust\n//! book.\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! ## change * to the version you want to use, ideally the latest.\n//! eyre = \"*\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"eyre\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of eyre and PyO3.\n//! The required eyre version may vary based on the version of PyO3.\n//!\n//! # Example: Propagating a `PyErr` into [`eyre::Report`]\n//!\n//! ```rust\n//! use pyo3::prelude::*;\n//! use std::path::PathBuf;\n//!\n//! // A wrapper around a Rust function.\n//! // The pyfunction macro performs the conversion to a PyErr\n//! #[pyfunction]\n//! fn py_open(filename: PathBuf) -> eyre::Result<Vec<u8>> {\n//!     let data = std::fs::read(filename)?;\n//!     Ok(data)\n//! }\n//!\n//! fn main() {\n//!     let error = Python::attach(|py| -> PyResult<Vec<u8>> {\n//!         let fun = wrap_pyfunction!(py_open, py)?;\n//!         let text = fun.call1((\"foo.txt\",))?.extract::<Vec<u8>>()?;\n//!         Ok(text)\n//!     }).unwrap_err();\n//!\n//!     println!(\"{}\", error);\n//! }\n//! ```\n//!\n//! # Example: Using `eyre` in general\n//!\n//! Note that you don't need this feature to convert a [`PyErr`] into an [`eyre::Report`], because\n//! it can already convert anything that implements [`Error`](std::error::Error):\n//!\n//! ```rust\n//! use pyo3::prelude::*;\n//! use pyo3::types::PyBytes;\n//!\n//! // An example function that must handle multiple error types.\n//! //\n//! // To do this you usually need to design your own error type or use\n//! // `Box<dyn Error>`. `eyre` is a convenient alternative for this.\n//! pub fn decompress(bytes: &[u8]) -> eyre::Result<String> {\n//!     // An arbitrary example of a Python api you\n//!     // could call inside an application...\n//!     // This might return a `PyErr`.\n//!     let res = Python::attach(|py| {\n//!         let zlib = PyModule::import(py, \"zlib\")?;\n//!         let decompress = zlib.getattr(\"decompress\")?;\n//!         let bytes = PyBytes::new(py, bytes);\n//!         let value = decompress.call1((bytes,))?;\n//!         value.extract::<Vec<u8>>()\n//!     })?;\n//!\n//!     // This might be a `FromUtf8Error`.\n//!     let text = String::from_utf8(res)?;\n//!\n//!     Ok(text)\n//! }\n//!\n//! fn main() -> eyre::Result<()> {\n//!     let bytes: &[u8] = b\"x\\x9c\\x8b\\xcc/U(\\xce\\xc8/\\xcdIQ((\\xcaOJL\\xca\\xa9T\\\n//!                         (-NU(\\xc9HU\\xc8\\xc9LJ\\xcbI,IUH.\\x02\\x91\\x99y\\xc5%\\\n//!                         \\xa9\\x89)z\\x00\\xf2\\x15\\x12\\xfe\";\n//!     let text = decompress(bytes)?;\n//!\n//!     println!(\"The text is \\\"{}\\\"\", text);\n//! # assert_eq!(text, \"You should probably use the libflate crate instead.\");\n//!     Ok(())\n//! }\n//! ```\n//!\n//! [eyre]: https://docs.rs/eyre/ \"A library for easy idiomatic error handling and reporting in Rust applications.\"\n//! [`RuntimeError`]: https://docs.python.org/3/library/exceptions.html#RuntimeError \"Built-in Exceptions — Python documentation\"\n//! [Error handling]: https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html \"Recoverable Errors with Result - The Rust Programming Language\"\n\nuse crate::exceptions::PyRuntimeError;\nuse crate::PyErr;\nuse eyre::Report;\n\n/// Converts [`eyre::Report`] to a [`PyErr`] containing a [`PyRuntimeError`].\n///\n/// If you want to raise a different Python exception you will have to do so manually. See\n/// [`PyErr::new`] for more information about that.\nimpl From<eyre::Report> for PyErr {\n    fn from(mut error: Report) -> Self {\n        // Errors containing a PyErr without chain or context are returned as the underlying error\n        if error.source().is_none() {\n            error = match error.downcast::<Self>() {\n                Ok(py_err) => return py_err,\n                Err(error) => error,\n            };\n        }\n        PyRuntimeError::new_err(format!(\"{error:?}\"))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::exceptions::{PyRuntimeError, PyValueError};\n    use crate::prelude::*;\n    use crate::types::IntoPyDict;\n\n    use eyre::{bail, eyre, Report, Result, WrapErr};\n\n    fn f() -> Result<()> {\n        use std::io;\n        bail!(io::Error::new(io::ErrorKind::PermissionDenied, \"oh no!\"));\n    }\n\n    fn g() -> Result<()> {\n        f().wrap_err(\"f failed\")\n    }\n\n    fn h() -> Result<()> {\n        g().wrap_err(\"g failed\")\n    }\n\n    #[test]\n    fn test_pyo3_exception_contents() {\n        let err = h().unwrap_err();\n        let expected_contents = format!(\"{err:?}\");\n        let pyerr = PyErr::from(err);\n\n        Python::attach(|py| {\n            let locals = [(\"err\", pyerr)].into_py_dict(py).unwrap();\n            let pyerr = py.run(c\"raise err\", None, Some(&locals)).unwrap_err();\n            assert_eq!(pyerr.value(py).to_string(), expected_contents);\n        })\n    }\n\n    fn k() -> Result<()> {\n        Err(eyre!(\"Some sort of error\"))\n    }\n\n    #[test]\n    fn test_pyo3_exception_contents2() {\n        let err = k().unwrap_err();\n        let expected_contents = format!(\"{err:?}\");\n        let pyerr = PyErr::from(err);\n\n        Python::attach(|py| {\n            let locals = [(\"err\", pyerr)].into_py_dict(py).unwrap();\n            let pyerr = py.run(c\"raise err\", None, Some(&locals)).unwrap_err();\n            assert_eq!(pyerr.value(py).to_string(), expected_contents);\n        })\n    }\n\n    #[test]\n    fn test_pyo3_unwrap_simple_err() {\n        let origin_exc = PyValueError::new_err(\"Value Error\");\n        let report: Report = origin_exc.into();\n        let converted: PyErr = report.into();\n        assert!(Python::attach(\n            |py| converted.is_instance_of::<PyValueError>(py)\n        ))\n    }\n    #[test]\n    fn test_pyo3_unwrap_complex_err() {\n        let origin_exc = PyValueError::new_err(\"Value Error\");\n        let mut report: Report = origin_exc.into();\n        report = report.wrap_err(\"Wrapped\");\n        let converted: PyErr = report.into();\n        assert!(Python::attach(\n            |py| converted.is_instance_of::<PyRuntimeError>(py)\n        ))\n    }\n}\n"
  },
  {
    "path": "src/conversions/hashbrown.rs",
    "content": "#![cfg(feature = \"hashbrown\")]\n\n//!  Conversions to and from [hashbrown](https://docs.rs/hashbrown/)’s\n//! `HashMap` and `HashSet`.\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! # change * to the latest versions\n//! hashbrown = \"*\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"hashbrown\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of hashbrown and PyO3.\n//! The required hashbrown version may vary based on the version of PyO3.\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::{\n    conversion::{FromPyObjectOwned, IntoPyObject},\n    types::{\n        any::PyAnyMethods, dict::PyDictMethods, frozenset::PyFrozenSetMethods, set::PySetMethods,\n        PyDict, PyFrozenSet, PySet,\n    },\n    Borrowed, Bound, FromPyObject, PyAny, PyErr, PyResult, Python,\n};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::{type_hint_subscript, type_hint_union, PyTypeInfo};\nuse std::hash;\n\nimpl<'py, K, V, H> IntoPyObject<'py> for hashbrown::HashMap<K, V, H>\nwhere\n    K: IntoPyObject<'py> + Eq + hash::Hash,\n    V: IntoPyObject<'py>,\n    H: hash::BuildHasher,\n{\n    type Target = PyDict;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyDict::TYPE_HINT, K::OUTPUT_TYPE, V::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let dict = PyDict::new(py);\n        for (k, v) in self {\n            dict.set_item(k, v)?;\n        }\n        Ok(dict)\n    }\n}\n\nimpl<'a, 'py, K, V, H> IntoPyObject<'py> for &'a hashbrown::HashMap<K, V, H>\nwhere\n    &'a K: IntoPyObject<'py> + Eq + hash::Hash,\n    &'a V: IntoPyObject<'py>,\n    H: hash::BuildHasher,\n{\n    type Target = PyDict;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyDict::TYPE_HINT, <&K>::OUTPUT_TYPE, <&V>::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let dict = PyDict::new(py);\n        for (k, v) in self {\n            dict.set_item(k, v)?;\n        }\n        Ok(dict)\n    }\n}\n\nimpl<'py, K, V, S> FromPyObject<'_, 'py> for hashbrown::HashMap<K, V, S>\nwhere\n    K: FromPyObjectOwned<'py> + Eq + hash::Hash,\n    V: FromPyObjectOwned<'py>,\n    S: hash::BuildHasher + Default,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyDict::TYPE_HINT, K::INPUT_TYPE, V::INPUT_TYPE);\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> Result<Self, PyErr> {\n        let dict = ob.cast::<PyDict>()?;\n        let mut ret = hashbrown::HashMap::with_capacity_and_hasher(dict.len(), S::default());\n        for (k, v) in dict.iter() {\n            ret.insert(\n                k.extract().map_err(Into::into)?,\n                v.extract().map_err(Into::into)?,\n            );\n        }\n        Ok(ret)\n    }\n}\n\nimpl<'py, K, H> IntoPyObject<'py> for hashbrown::HashSet<K, H>\nwhere\n    K: IntoPyObject<'py> + Eq + hash::Hash,\n    H: hash::BuildHasher,\n{\n    type Target = PySet;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_subscript!(PySet::TYPE_HINT, K::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        PySet::new(py, self)\n    }\n}\n\nimpl<'a, 'py, K, H> IntoPyObject<'py> for &'a hashbrown::HashSet<K, H>\nwhere\n    &'a K: IntoPyObject<'py> + Eq + hash::Hash,\n    H: hash::BuildHasher,\n{\n    type Target = PySet;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_subscript!(PySet::TYPE_HINT, <&K>::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        PySet::new(py, self)\n    }\n}\n\nimpl<'py, K, S> FromPyObject<'_, 'py> for hashbrown::HashSet<K, S>\nwhere\n    K: FromPyObjectOwned<'py> + Eq + hash::Hash,\n    S: hash::BuildHasher + Default,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_union!(\n        type_hint_subscript!(PySet::TYPE_HINT, K::INPUT_TYPE),\n        type_hint_subscript!(PyFrozenSet::TYPE_HINT, K::INPUT_TYPE)\n    );\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {\n        match ob.cast::<PySet>() {\n            Ok(set) => set\n                .iter()\n                .map(|any| any.extract().map_err(Into::into))\n                .collect(),\n            Err(err) => {\n                if let Ok(frozen_set) = ob.cast::<PyFrozenSet>() {\n                    frozen_set\n                        .iter()\n                        .map(|any| any.extract().map_err(Into::into))\n                        .collect()\n                } else {\n                    Err(PyErr::from(err))\n                }\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::IntoPyDict;\n    use std::collections::hash_map::RandomState;\n\n    #[test]\n    fn test_hashbrown_hashmap_into_pyobject() {\n        Python::attach(|py| {\n            let mut map =\n                hashbrown::HashMap::<i32, i32, RandomState>::with_hasher(RandomState::new());\n            map.insert(1, 1);\n\n            let py_map = (&map).into_pyobject(py).unwrap();\n\n            assert_eq!(py_map.len(), 1);\n            assert!(\n                py_map\n                    .get_item(1)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n                    == 1\n            );\n            assert_eq!(map, py_map.extract().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_hashbrown_hashmap_into_dict() {\n        Python::attach(|py| {\n            let mut map =\n                hashbrown::HashMap::<i32, i32, RandomState>::with_hasher(RandomState::new());\n            map.insert(1, 1);\n\n            let py_map = map.into_py_dict(py).unwrap();\n\n            assert_eq!(py_map.len(), 1);\n            assert_eq!(\n                py_map\n                    .get_item(1)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                1\n            );\n        });\n    }\n\n    #[test]\n    fn test_extract_hashbrown_hashset() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1, 2, 3, 4, 5]).unwrap();\n            let hash_set: hashbrown::HashSet<usize, RandomState> = set.extract().unwrap();\n            assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect());\n\n            let set = PyFrozenSet::new(py, [1, 2, 3, 4, 5]).unwrap();\n            let hash_set: hashbrown::HashSet<usize, RandomState> = set.extract().unwrap();\n            assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect());\n        });\n    }\n\n    #[test]\n    fn test_hashbrown_hashset_into_pyobject() {\n        Python::attach(|py| {\n            let hs: hashbrown::HashSet<u64, RandomState> =\n                [1, 2, 3, 4, 5].iter().cloned().collect();\n\n            let hso = hs.clone().into_pyobject(py).unwrap();\n\n            assert_eq!(hs, hso.extract().unwrap());\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/indexmap.rs",
    "content": "#![cfg(feature = \"indexmap\")]\n\n//!  Conversions to and from [indexmap](https://docs.rs/indexmap/)’s\n//! `IndexMap`.\n//!\n//! [`indexmap::IndexMap`] is a hash table that is closely compatible with the standard [`std::collections::HashMap`],\n//! with the difference that it preserves the insertion order when iterating over keys. It was inspired\n//! by Python's 3.6+ dict implementation.\n//!\n//! Dictionary order is guaranteed to be insertion order in Python, hence IndexMap is a good candidate\n//! for maintaining an equivalent behaviour in Rust.\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! # change * to the latest versions\n//! indexmap = \"*\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"indexmap\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of indexmap and PyO3.\n//! The required indexmap version may vary based on the version of PyO3.\n//!\n//! # Examples\n//!\n//! Using [indexmap](https://docs.rs/indexmap) to return a dictionary with some statistics\n//! about a list of numbers. Because of the insertion order guarantees, the Python code will\n//! always print the same result, matching users' expectations about Python's dict.\n//! ```rust\n//! use indexmap::{indexmap, IndexMap};\n//! use pyo3::prelude::*;\n//!\n//! fn median(data: &Vec<i32>) -> f32 {\n//!     let sorted_data = data.clone().sort();\n//!     let mid = data.len() / 2;\n//!     if data.len() % 2 == 0 {\n//!         data[mid] as f32\n//!     }\n//!     else {\n//!         (data[mid] + data[mid - 1]) as f32 / 2.0\n//!     }\n//! }\n//!\n//! fn mean(data: &Vec<i32>) -> f32 {\n//!     data.iter().sum::<i32>() as f32 / data.len() as f32\n//! }\n//! fn mode(data: &Vec<i32>) -> f32 {\n//!     let mut frequency = IndexMap::new(); // we can use IndexMap as any hash table\n//!\n//!     for &element in data {\n//!         *frequency.entry(element).or_insert(0) += 1;\n//!     }\n//!\n//!     frequency\n//!         .iter()\n//!         .max_by(|a, b| a.1.cmp(&b.1))\n//!         .map(|(k, _v)| *k)\n//!         .unwrap() as f32\n//!   }\n//!\n//! #[pyfunction]\n//! fn calculate_statistics(data: Vec<i32>) -> IndexMap<&'static str, f32> {\n//!     indexmap! {\n//!        \"median\" => median(&data),\n//!        \"mean\" => mean(&data),\n//!        \"mode\" => mode(&data),\n//!     }\n//! }\n//!\n//! #[pymodule]\n//! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n//!     m.add_function(wrap_pyfunction!(calculate_statistics, m)?)?;\n//!     Ok(())\n//! }\n//! ```\n//!\n//! Python code:\n//! ```python\n//! from my_module import calculate_statistics\n//!\n//! data = [1, 1, 1, 3, 4, 5]\n//! print(calculate_statistics(data))\n//! # always prints {\"median\": 2.0, \"mean\": 2.5, \"mode\": 1.0} in the same order\n//! # if another hash table was used, the order could be random\n//! ```\n\nuse crate::conversion::{FromPyObjectOwned, IntoPyObject};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::types::*;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::{type_hint_subscript, PyTypeInfo};\nuse crate::{Borrowed, Bound, FromPyObject, PyErr, Python};\nuse std::hash;\n\nimpl<'py, K, V, H> IntoPyObject<'py> for indexmap::IndexMap<K, V, H>\nwhere\n    K: IntoPyObject<'py> + Eq + hash::Hash,\n    V: IntoPyObject<'py>,\n    H: hash::BuildHasher,\n{\n    type Target = PyDict;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyDict::TYPE_HINT, K::OUTPUT_TYPE, V::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let dict = PyDict::new(py);\n        for (k, v) in self {\n            dict.set_item(k, v)?;\n        }\n        Ok(dict)\n    }\n}\n\nimpl<'a, 'py, K, V, H> IntoPyObject<'py> for &'a indexmap::IndexMap<K, V, H>\nwhere\n    &'a K: IntoPyObject<'py> + Eq + hash::Hash,\n    &'a V: IntoPyObject<'py>,\n    H: hash::BuildHasher,\n{\n    type Target = PyDict;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyDict::TYPE_HINT, <&K>::OUTPUT_TYPE, <&V>::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let dict = PyDict::new(py);\n        for (k, v) in self {\n            dict.set_item(k, v)?;\n        }\n        Ok(dict)\n    }\n}\n\nimpl<'py, K, V, S> FromPyObject<'_, 'py> for indexmap::IndexMap<K, V, S>\nwhere\n    K: FromPyObjectOwned<'py> + Eq + hash::Hash,\n    V: FromPyObjectOwned<'py>,\n    S: hash::BuildHasher + Default,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyDict::TYPE_HINT, K::INPUT_TYPE, V::INPUT_TYPE);\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        let dict = ob.cast::<PyDict>()?;\n        let mut ret = indexmap::IndexMap::with_capacity_and_hasher(dict.len(), S::default());\n        for (k, v) in dict.iter() {\n            ret.insert(\n                k.extract().map_err(Into::into)?,\n                v.extract().map_err(Into::into)?,\n            );\n        }\n        Ok(ret)\n    }\n}\n\n#[cfg(test)]\nmod test_indexmap {\n\n    use crate::types::*;\n    use crate::{IntoPyObject, Python};\n\n    #[test]\n    fn test_indexmap_indexmap_into_pyobject() {\n        Python::attach(|py| {\n            let mut map = indexmap::IndexMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let py_map = (&map).into_pyobject(py).unwrap();\n\n            assert_eq!(py_map.len(), 1);\n            assert!(\n                py_map\n                    .get_item(1)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n                    == 1\n            );\n            assert_eq!(\n                map,\n                py_map.extract::<indexmap::IndexMap::<i32, i32>>().unwrap()\n            );\n        });\n    }\n\n    #[test]\n    fn test_indexmap_indexmap_into_dict() {\n        Python::attach(|py| {\n            let mut map = indexmap::IndexMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let py_map = map.into_py_dict(py).unwrap();\n\n            assert_eq!(py_map.len(), 1);\n            assert_eq!(\n                py_map\n                    .get_item(1)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                1\n            );\n        });\n    }\n\n    #[test]\n    fn test_indexmap_indexmap_insertion_order_round_trip() {\n        Python::attach(|py| {\n            let n = 20;\n            let mut map = indexmap::IndexMap::<i32, i32>::new();\n\n            for i in 1..=n {\n                if i % 2 == 1 {\n                    map.insert(i, i);\n                } else {\n                    map.insert(n - i, i);\n                }\n            }\n\n            let py_map = (&map).into_py_dict(py).unwrap();\n\n            let trip_map = py_map.extract::<indexmap::IndexMap<i32, i32>>().unwrap();\n\n            for (((k1, v1), (k2, v2)), (k3, v3)) in\n                map.iter().zip(py_map.iter()).zip(trip_map.iter())\n            {\n                let k2 = k2.extract::<i32>().unwrap();\n                let v2 = v2.extract::<i32>().unwrap();\n                assert_eq!((k1, v1), (&k2, &v2));\n                assert_eq!((k1, v1), (k3, v3));\n                assert_eq!((&k2, &v2), (k3, v3));\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/jiff.rs",
    "content": "#![cfg(feature = \"jiff-02\")]\n\n//! Conversions to and from [jiff](https://docs.rs/jiff/)’s `Span`, `SignedDuration`, `TimeZone`,\n//! `Offset`, `Date`, `Time`, `DateTime`, `Zoned`, and `Timestamp`.\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! jiff = \"0.2\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"jiff-02\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of jiff and PyO3.\n//! The required jiff version may vary based on the version of PyO3.\n//!\n//! # Example: Convert a `datetime.datetime` to jiff `Zoned`\n//!\n//! ```rust\n//! # #![cfg_attr(windows, allow(unused_imports))]\n//! # use jiff_02 as jiff;\n//! use jiff::{Zoned, SignedDuration, ToSpan};\n//! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods};\n//!\n//! # #[cfg(windows)]\n//! # fn main() -> () {}\n//! # #[cfg(not(windows))]\n//! fn main() -> PyResult<()> {\n//!     Python::initialize();\n//!     Python::attach(|py| {\n//!         // Build some jiff values\n//!         let jiff_zoned = Zoned::now();\n//!         let jiff_span = 1.second();\n//!         // Convert them to Python\n//!         let py_datetime = jiff_zoned.into_pyobject(py)?;\n//!         let py_timedelta = SignedDuration::try_from(jiff_span)?.into_pyobject(py)?;\n//!         // Do an operation in Python\n//!         let py_sum = py_datetime.call_method1(\"__add__\", (py_timedelta,))?;\n//!         // Convert back to Rust\n//!         let jiff_sum: Zoned = py_sum.extract()?;\n//!         println!(\"Zoned: {}\", jiff_sum);\n//!         Ok(())\n//!     })\n//! }\n//! ```\nuse crate::exceptions::{PyTypeError, PyValueError};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::types::{PyAnyMethods, PyNone};\nuse crate::types::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo, PyTzInfoAccess};\n#[cfg(not(Py_LIMITED_API))]\nuse crate::types::{PyDateAccess, PyDeltaAccess, PyTimeAccess};\nuse crate::{intern, Borrowed, Bound, FromPyObject, IntoPyObject, PyAny, PyErr, PyResult, Python};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::{type_hint_identifier, PyTypeInfo};\nuse jiff::civil::{Date, DateTime, ISOWeekDate, Time};\nuse jiff::tz::{Offset, TimeZone};\nuse jiff::{SignedDuration, Span, Timestamp, Zoned};\n#[cfg(feature = \"jiff-02\")]\nuse jiff_02 as jiff;\nuse std::borrow::Cow;\n\nfn datetime_to_pydatetime<'py>(\n    py: Python<'py>,\n    datetime: DateTime,\n    fold: bool,\n    timezone: Option<&TimeZone>,\n) -> PyResult<Bound<'py, PyDateTime>> {\n    PyDateTime::new_with_fold(\n        py,\n        datetime.year().into(),\n        datetime.month().try_into()?,\n        datetime.day().try_into()?,\n        datetime.hour().try_into()?,\n        datetime.minute().try_into()?,\n        datetime.second().try_into()?,\n        (datetime.subsec_nanosecond() / 1000).try_into()?,\n        timezone\n            .map(|tz| tz.into_pyobject(py))\n            .transpose()?\n            .as_ref(),\n        fold,\n    )\n}\n\n#[cfg(not(Py_LIMITED_API))]\nfn pytime_to_time(time: &impl PyTimeAccess) -> PyResult<Time> {\n    Ok(Time::new(\n        time.get_hour().try_into()?,\n        time.get_minute().try_into()?,\n        time.get_second().try_into()?,\n        (time.get_microsecond() * 1000).try_into()?,\n    )?)\n}\n\n#[cfg(Py_LIMITED_API)]\nfn pytime_to_time(time: &Bound<'_, PyAny>) -> PyResult<Time> {\n    let py = time.py();\n    Ok(Time::new(\n        time.getattr(intern!(py, \"hour\"))?.extract()?,\n        time.getattr(intern!(py, \"minute\"))?.extract()?,\n        time.getattr(intern!(py, \"second\"))?.extract()?,\n        time.getattr(intern!(py, \"microsecond\"))?.extract::<i32>()? * 1000,\n    )?)\n}\n\nimpl<'py> IntoPyObject<'py> for Timestamp {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Zoned::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.to_zoned(TimeZone::UTC).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Timestamp {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Timestamp::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'a, 'py> FromPyObject<'a, 'py> for Timestamp {\n    type Error = <Zoned as FromPyObject<'a, 'py>>::Error;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = Zoned::INPUT_TYPE;\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        let zoned = ob.extract::<Zoned>()?;\n        Ok(zoned.timestamp())\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Date {\n    type Target = PyDate;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDate::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        PyDate::new(\n            py,\n            self.year().into(),\n            self.month().try_into()?,\n            self.day().try_into()?,\n        )\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Date {\n    type Target = PyDate;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Date::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> FromPyObject<'_, 'py> for Date {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDate::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {\n        let date = ob.cast::<PyDate>()?;\n\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            Ok(Date::new(\n                date.get_year().try_into()?,\n                date.get_month().try_into()?,\n                date.get_day().try_into()?,\n            )?)\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        {\n            let py = date.py();\n            Ok(Date::new(\n                date.getattr(intern!(py, \"year\"))?.extract()?,\n                date.getattr(intern!(py, \"month\"))?.extract()?,\n                date.getattr(intern!(py, \"day\"))?.extract()?,\n            )?)\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Time {\n    type Target = PyTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyTime::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        PyTime::new(\n            py,\n            self.hour().try_into()?,\n            self.minute().try_into()?,\n            self.second().try_into()?,\n            (self.subsec_nanosecond() / 1000).try_into()?,\n            None,\n        )\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Time {\n    type Target = PyTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Time::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> FromPyObject<'_, 'py> for Time {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyTime::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {\n        let ob = ob.cast::<PyTime>()?;\n        #[allow(clippy::explicit_auto_deref)]\n        pytime_to_time(&*ob)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for DateTime {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        datetime_to_pydatetime(py, self, false, None)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &DateTime {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = DateTime::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> FromPyObject<'_, 'py> for DateTime {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn extract(dt: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {\n        let dt = dt.cast::<PyDateTime>()?;\n        let has_tzinfo = dt.get_tzinfo().is_some();\n\n        if has_tzinfo {\n            return Err(PyTypeError::new_err(\"expected a datetime without tzinfo\"));\n        }\n\n        #[allow(clippy::explicit_auto_deref)]\n        Ok(DateTime::from_parts(dt.extract()?, pytime_to_time(&*dt)?))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Zoned {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&Self>::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (&self).into_pyobject(py)\n    }\n}\nimpl<'py> IntoPyObject<'py> for &Zoned {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        fn fold(zoned: &Zoned) -> Option<bool> {\n            let prev = zoned.time_zone().preceding(zoned.timestamp()).next()?;\n            let next = zoned.time_zone().following(prev.timestamp()).next()?;\n            let start_of_current_offset = if next.timestamp() == zoned.timestamp() {\n                next.timestamp()\n            } else {\n                prev.timestamp()\n            };\n            Some(zoned.timestamp() + (zoned.offset() - prev.offset()) <= start_of_current_offset)\n        }\n\n        datetime_to_pydatetime(\n            py,\n            self.datetime(),\n            fold(self).unwrap_or(false),\n            Some(self.time_zone()),\n        )\n    }\n}\n\nimpl<'py> FromPyObject<'_, 'py> for Zoned {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn extract(dt: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {\n        let dt = dt.cast::<PyDateTime>()?;\n\n        let tz = dt\n            .get_tzinfo()\n            .map(|tz| tz.extract::<TimeZone>())\n            .unwrap_or_else(|| {\n                Err(PyTypeError::new_err(\n                    \"expected a datetime with non-None tzinfo\",\n                ))\n            })?;\n        #[allow(clippy::explicit_auto_deref)]\n        let datetime = DateTime::from_parts(dt.extract()?, pytime_to_time(&*dt)?);\n        let zoned = tz.into_ambiguous_zoned(datetime);\n\n        #[cfg(not(Py_LIMITED_API))]\n        let fold = dt.get_fold();\n\n        #[cfg(Py_LIMITED_API)]\n        let fold = dt.getattr(intern!(dt.py(), \"fold\"))?.extract::<usize>()? > 0;\n\n        if fold {\n            Ok(zoned.later()?)\n        } else {\n            Ok(zoned.earlier()?)\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for TimeZone {\n    type Target = PyTzInfo;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&Self>::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (&self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &TimeZone {\n    type Target = PyTzInfo;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyTzInfo::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        if self == &TimeZone::UTC {\n            return Ok(PyTzInfo::utc(py)?.to_owned());\n        }\n\n        if let Some(iana_name) = self.iana_name() {\n            return PyTzInfo::timezone(py, iana_name);\n        }\n\n        self.to_fixed_offset()?.into_pyobject(py)\n    }\n}\n\nimpl<'py> FromPyObject<'_, 'py> for TimeZone {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyTzInfo::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {\n        let ob = ob.cast::<PyTzInfo>()?;\n\n        let attr = intern!(ob.py(), \"key\");\n        if ob.hasattr(attr)? {\n            Ok(TimeZone::get(\n                &ob.getattr(attr)?.extract::<Cow<'_, str>>()?,\n            )?)\n        } else {\n            Ok(ob.extract::<Offset>()?.to_time_zone())\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Offset {\n    type Target = PyTzInfo;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"datetime\", \"timezone\");\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        if self == Offset::UTC {\n            return Ok(PyTzInfo::utc(py)?.to_owned());\n        }\n\n        PyTzInfo::fixed_offset(py, self.duration_since(Offset::UTC))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Offset {\n    type Target = PyTzInfo;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Offset::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> FromPyObject<'_, 'py> for Offset {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyTzInfo::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {\n        let py = ob.py();\n        let ob = ob.cast::<PyTzInfo>()?;\n\n        let py_timedelta = ob.call_method1(intern!(py, \"utcoffset\"), (PyNone::get(py),))?;\n        if py_timedelta.is_none() {\n            return Err(PyTypeError::new_err(format!(\n                \"{ob:?} is not a fixed offset timezone\"\n            )));\n        }\n\n        let total_seconds = py_timedelta.extract::<SignedDuration>()?.as_secs();\n        debug_assert!(\n            (total_seconds / 3600).abs() <= 24,\n            \"Offset must be between -24 hours and 24 hours but was {}h\",\n            total_seconds / 3600\n        );\n        // This cast is safe since the timedelta is limited to -24 hours and 24 hours.\n        Ok(Offset::from_seconds(total_seconds as i32)?)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for SignedDuration {\n    type Target = PyDelta;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDelta::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let total_seconds = self.as_secs();\n        let days: i32 = (total_seconds / (24 * 60 * 60)).try_into()?;\n        let seconds: i32 = (total_seconds % (24 * 60 * 60)).try_into()?;\n        let microseconds = self.subsec_micros();\n\n        PyDelta::new(py, days, seconds, microseconds, true)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &SignedDuration {\n    type Target = PyDelta;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = SignedDuration::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> FromPyObject<'_, 'py> for SignedDuration {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDelta::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {\n        let delta = ob.cast::<PyDelta>()?;\n\n        #[cfg(not(Py_LIMITED_API))]\n        let (seconds, microseconds) = {\n            let days = delta.get_days() as i64;\n            let seconds = delta.get_seconds() as i64;\n            let microseconds = delta.get_microseconds();\n            (days * 24 * 60 * 60 + seconds, microseconds)\n        };\n\n        #[cfg(Py_LIMITED_API)]\n        let (seconds, microseconds) = {\n            let py = delta.py();\n            let days = delta.getattr(intern!(py, \"days\"))?.extract::<i64>()?;\n            let seconds = delta.getattr(intern!(py, \"seconds\"))?.extract::<i64>()?;\n            let microseconds = ob.getattr(intern!(py, \"microseconds\"))?.extract::<i32>()?;\n            (days * 24 * 60 * 60 + seconds, microseconds)\n        };\n\n        Ok(SignedDuration::new(seconds, microseconds * 1000))\n    }\n}\n\nimpl<'py> FromPyObject<'_, 'py> for Span {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = SignedDuration::INPUT_TYPE;\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {\n        let duration = ob.extract::<SignedDuration>()?;\n        Ok(duration.try_into()?)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for ISOWeekDate {\n    type Target = PyDate;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Date::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.date().into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &ISOWeekDate {\n    type Target = PyDate;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = ISOWeekDate::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl FromPyObject<'_, '_> for ISOWeekDate {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = Date::INPUT_TYPE;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {\n        Ok(ob.extract::<Date>()?.iso_week_date())\n    }\n}\n\nimpl From<jiff::Error> for PyErr {\n    fn from(e: jiff::Error) -> Self {\n        PyValueError::new_err(e.to_string())\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::{types::PyTuple, BoundObject};\n    use jiff::tz::Offset;\n    use std::cmp::Ordering;\n\n    #[test]\n    // Only Python>=3.9 has the zoneinfo package\n    // We skip the test on windows too since we'd need to install\n    // tzdata there to make this work.\n    #[cfg(all(Py_3_9, not(target_os = \"windows\")))]\n    fn test_zoneinfo_is_not_fixed_offset() {\n        use crate::types::any::PyAnyMethods;\n        use crate::types::dict::PyDictMethods;\n\n        Python::attach(|py| {\n            let locals = crate::types::PyDict::new(py);\n            py.run(\n                c\"import zoneinfo; zi = zoneinfo.ZoneInfo('Europe/London')\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let result: PyResult<Offset> = locals.get_item(\"zi\").unwrap().unwrap().extract();\n            assert!(result.is_err());\n            let res = result.err().unwrap();\n            // Also check the error message is what we expect\n            let msg = res.value(py).repr().unwrap().to_string();\n            assert_eq!(msg, \"TypeError(\\\"zoneinfo.ZoneInfo(key='Europe/London') is not a fixed offset timezone\\\")\");\n        });\n    }\n\n    #[test]\n    fn test_timezone_aware_to_naive_fails() {\n        // Test that if a user tries to convert a python's timezone aware datetime into a naive\n        // one, the conversion fails.\n        Python::attach(|py| {\n            let py_datetime =\n                new_py_datetime_ob(py, \"datetime\", (2022, 1, 1, 1, 0, 0, 0, python_utc(py)));\n            // Now test that converting a PyDateTime with tzinfo to a NaiveDateTime fails\n            let res: PyResult<DateTime> = py_datetime.extract();\n            assert_eq!(\n                res.unwrap_err().value(py).repr().unwrap().to_string(),\n                \"TypeError('expected a datetime without tzinfo')\"\n            );\n        });\n    }\n\n    #[test]\n    fn test_naive_to_timezone_aware_fails() {\n        // Test that if a user tries to convert a python's naive datetime into a timezone aware\n        // one, the conversion fails.\n        Python::attach(|py| {\n            let py_datetime = new_py_datetime_ob(py, \"datetime\", (2022, 1, 1, 1, 0, 0, 0));\n            let res: PyResult<Zoned> = py_datetime.extract();\n            assert_eq!(\n                res.unwrap_err().value(py).repr().unwrap().to_string(),\n                \"TypeError('expected a datetime with non-None tzinfo')\"\n            );\n        });\n    }\n\n    #[test]\n    fn test_invalid_types_fail() {\n        Python::attach(|py| {\n            let none = py.None().into_bound(py);\n            assert_eq!(\n                none.extract::<Span>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'timedelta'\"\n            );\n            assert_eq!(\n                none.extract::<Offset>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'tzinfo'\"\n            );\n            assert_eq!(\n                none.extract::<TimeZone>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'tzinfo'\"\n            );\n            assert_eq!(\n                none.extract::<Time>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'time'\"\n            );\n            assert_eq!(\n                none.extract::<Date>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'date'\"\n            );\n            assert_eq!(\n                none.extract::<DateTime>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'datetime'\"\n            );\n            assert_eq!(\n                none.extract::<Zoned>().unwrap_err().to_string(),\n                \"TypeError: 'None' is not an instance of 'datetime'\"\n            );\n        });\n    }\n\n    #[test]\n    fn test_pyo3_date_into_pyobject() {\n        let eq_ymd = |name: &'static str, year, month, day| {\n            Python::attach(|py| {\n                let date = Date::new(year, month, day)\n                    .unwrap()\n                    .into_pyobject(py)\n                    .unwrap();\n                let py_date = new_py_datetime_ob(py, \"date\", (year, month, day));\n                assert_eq!(\n                    date.compare(&py_date).unwrap(),\n                    Ordering::Equal,\n                    \"{name}: {date} != {py_date}\"\n                );\n            })\n        };\n\n        eq_ymd(\"past date\", 2012, 2, 29);\n        eq_ymd(\"min date\", 1, 1, 1);\n        eq_ymd(\"future date\", 3000, 6, 5);\n        eq_ymd(\"max date\", 9999, 12, 31);\n    }\n\n    #[test]\n    fn test_pyo3_date_frompyobject() {\n        let eq_ymd = |name: &'static str, year, month, day| {\n            Python::attach(|py| {\n                let py_date = new_py_datetime_ob(py, \"date\", (year, month, day));\n                let py_date: Date = py_date.extract().unwrap();\n                let date = Date::new(year, month, day).unwrap();\n                assert_eq!(py_date, date, \"{name}: {date} != {py_date}\");\n            })\n        };\n\n        eq_ymd(\"past date\", 2012, 2, 29);\n        eq_ymd(\"min date\", 1, 1, 1);\n        eq_ymd(\"future date\", 3000, 6, 5);\n        eq_ymd(\"max date\", 9999, 12, 31);\n    }\n\n    #[test]\n    fn test_pyo3_datetime_into_pyobject_utc() {\n        Python::attach(|py| {\n            let check_utc =\n                |name: &'static str, year, month, day, hour, minute, second, ms, py_ms| {\n                    let datetime = DateTime::new(year, month, day, hour, minute, second, ms * 1000)\n                        .unwrap()\n                        .to_zoned(TimeZone::UTC)\n                        .unwrap();\n                    let datetime = datetime.into_pyobject(py).unwrap();\n                    let py_datetime = new_py_datetime_ob(\n                        py,\n                        \"datetime\",\n                        (\n                            year,\n                            month,\n                            day,\n                            hour,\n                            minute,\n                            second,\n                            py_ms,\n                            python_utc(py),\n                        ),\n                    );\n                    assert_eq!(\n                        datetime.compare(&py_datetime).unwrap(),\n                        Ordering::Equal,\n                        \"{name}: {datetime} != {py_datetime}\"\n                    );\n                };\n\n            check_utc(\"regular\", 2014, 5, 6, 7, 8, 9, 999_999, 999_999);\n        })\n    }\n\n    #[test]\n    fn test_pyo3_datetime_into_pyobject_fixed_offset() {\n        Python::attach(|py| {\n            let check_fixed_offset =\n                |name: &'static str, year, month, day, hour, minute, second, ms, py_ms| {\n                    let offset = Offset::from_seconds(3600).unwrap();\n                    let datetime = DateTime::new(year, month, day, hour, minute, second, ms * 1000)\n                        .map_err(|e| {\n                            eprintln!(\"{name}: {e}\");\n                            e\n                        })\n                        .unwrap()\n                        .to_zoned(offset.to_time_zone())\n                        .unwrap();\n                    let datetime = datetime.into_pyobject(py).unwrap();\n                    let py_tz = offset.into_pyobject(py).unwrap();\n                    let py_datetime = new_py_datetime_ob(\n                        py,\n                        \"datetime\",\n                        (year, month, day, hour, minute, second, py_ms, py_tz),\n                    );\n                    assert_eq!(\n                        datetime.compare(&py_datetime).unwrap(),\n                        Ordering::Equal,\n                        \"{name}: {datetime} != {py_datetime}\"\n                    );\n                };\n\n            check_fixed_offset(\"regular\", 2014, 5, 6, 7, 8, 9, 999_999, 999_999);\n        })\n    }\n\n    #[test]\n    #[cfg(all(Py_3_9, not(windows)))]\n    fn test_pyo3_datetime_into_pyobject_tz() {\n        Python::attach(|py| {\n            let datetime = DateTime::new(2024, 12, 11, 23, 3, 13, 0)\n                .unwrap()\n                .to_zoned(TimeZone::get(\"Europe/London\").unwrap())\n                .unwrap();\n            let datetime = datetime.into_pyobject(py).unwrap();\n            let py_datetime = new_py_datetime_ob(\n                py,\n                \"datetime\",\n                (\n                    2024,\n                    12,\n                    11,\n                    23,\n                    3,\n                    13,\n                    0,\n                    python_zoneinfo(py, \"Europe/London\"),\n                ),\n            );\n            assert_eq!(datetime.compare(&py_datetime).unwrap(), Ordering::Equal);\n        })\n    }\n\n    #[test]\n    fn test_pyo3_datetime_frompyobject_utc() {\n        Python::attach(|py| {\n            let year = 2014;\n            let month = 5;\n            let day = 6;\n            let hour = 7;\n            let minute = 8;\n            let second = 9;\n            let micro = 999_999;\n            let tz_utc = PyTzInfo::utc(py).unwrap();\n            let py_datetime = new_py_datetime_ob(\n                py,\n                \"datetime\",\n                (year, month, day, hour, minute, second, micro, tz_utc),\n            );\n            let py_datetime: Zoned = py_datetime.extract().unwrap();\n            let datetime = DateTime::new(year, month, day, hour, minute, second, micro * 1000)\n                .unwrap()\n                .to_zoned(TimeZone::UTC)\n                .unwrap();\n            assert_eq!(py_datetime, datetime,);\n        })\n    }\n\n    #[test]\n    #[cfg(all(Py_3_9, not(windows)))]\n    fn test_ambiguous_datetime_to_pyobject() {\n        use std::str::FromStr;\n        let dates = [\n            Zoned::from_str(\"2020-10-24 23:00:00[UTC]\").unwrap(),\n            Zoned::from_str(\"2020-10-25 00:00:00[UTC]\").unwrap(),\n            Zoned::from_str(\"2020-10-25 01:00:00[UTC]\").unwrap(),\n            Zoned::from_str(\"2020-10-25 02:00:00[UTC]\").unwrap(),\n        ];\n\n        let tz = TimeZone::get(\"Europe/London\").unwrap();\n        let dates = dates.map(|dt| dt.with_time_zone(tz.clone()));\n\n        assert_eq!(\n            dates.clone().map(|ref dt| dt.to_string()),\n            [\n                \"2020-10-25T00:00:00+01:00[Europe/London]\",\n                \"2020-10-25T01:00:00+01:00[Europe/London]\",\n                \"2020-10-25T01:00:00+00:00[Europe/London]\",\n                \"2020-10-25T02:00:00+00:00[Europe/London]\",\n            ]\n        );\n\n        let dates = Python::attach(|py| {\n            let pydates = dates.map(|dt| dt.into_pyobject(py).unwrap());\n            assert_eq!(\n                pydates\n                    .clone()\n                    .map(|dt| dt.getattr(\"hour\").unwrap().extract::<usize>().unwrap()),\n                [0, 1, 1, 2]\n            );\n\n            assert_eq!(\n                pydates\n                    .clone()\n                    .map(|dt| dt.getattr(\"fold\").unwrap().extract::<usize>().unwrap() > 0),\n                [false, false, true, false]\n            );\n\n            pydates.map(|dt| dt.extract::<Zoned>().unwrap())\n        });\n\n        assert_eq!(\n            dates.map(|dt| dt.to_string()),\n            [\n                \"2020-10-25T00:00:00+01:00[Europe/London]\",\n                \"2020-10-25T01:00:00+01:00[Europe/London]\",\n                \"2020-10-25T01:00:00+00:00[Europe/London]\",\n                \"2020-10-25T02:00:00+00:00[Europe/London]\",\n            ]\n        );\n    }\n\n    #[test]\n    fn test_pyo3_datetime_frompyobject_fixed_offset() {\n        Python::attach(|py| {\n            let year = 2014;\n            let month = 5;\n            let day = 6;\n            let hour = 7;\n            let minute = 8;\n            let second = 9;\n            let micro = 999_999;\n            let offset = Offset::from_seconds(3600).unwrap();\n            let py_tz = offset.into_pyobject(py).unwrap();\n            let py_datetime = new_py_datetime_ob(\n                py,\n                \"datetime\",\n                (year, month, day, hour, minute, second, micro, py_tz),\n            );\n            let datetime_from_py: Zoned = py_datetime.extract().unwrap();\n            let datetime =\n                DateTime::new(year, month, day, hour, minute, second, micro * 1000).unwrap();\n            let datetime = datetime.to_zoned(offset.to_time_zone()).unwrap();\n\n            assert_eq!(datetime_from_py, datetime);\n        })\n    }\n\n    #[test]\n    fn test_pyo3_offset_fixed_into_pyobject() {\n        Python::attach(|py| {\n            // jiff offset\n            let offset = Offset::from_seconds(3600)\n                .unwrap()\n                .into_pyobject(py)\n                .unwrap();\n            // Python timezone from timedelta\n            let td = new_py_datetime_ob(py, \"timedelta\", (0, 3600, 0));\n            let py_timedelta = new_py_datetime_ob(py, \"timezone\", (td,));\n            // Should be equal\n            assert!(offset.eq(py_timedelta).unwrap());\n\n            // Same but with negative values\n            let offset = Offset::from_seconds(-3600)\n                .unwrap()\n                .into_pyobject(py)\n                .unwrap();\n            let td = new_py_datetime_ob(py, \"timedelta\", (0, -3600, 0));\n            let py_timedelta = new_py_datetime_ob(py, \"timezone\", (td,));\n            assert!(offset.eq(py_timedelta).unwrap());\n        })\n    }\n\n    #[test]\n    fn test_pyo3_offset_fixed_frompyobject() {\n        Python::attach(|py| {\n            let py_timedelta = new_py_datetime_ob(py, \"timedelta\", (0, 3600, 0));\n            let py_tzinfo = new_py_datetime_ob(py, \"timezone\", (py_timedelta,));\n            let offset: Offset = py_tzinfo.extract().unwrap();\n            assert_eq!(Offset::from_seconds(3600).unwrap(), offset);\n        })\n    }\n\n    #[test]\n    fn test_pyo3_offset_utc_into_pyobject() {\n        Python::attach(|py| {\n            let utc = Offset::UTC.into_pyobject(py).unwrap();\n            let py_utc = python_utc(py);\n            assert!(utc.is(&py_utc));\n        })\n    }\n\n    #[test]\n    fn test_pyo3_offset_utc_frompyobject() {\n        Python::attach(|py| {\n            let py_utc = python_utc(py);\n            let py_utc: Offset = py_utc.extract().unwrap();\n            assert_eq!(Offset::UTC, py_utc);\n\n            let py_timedelta = new_py_datetime_ob(py, \"timedelta\", (0, 0, 0));\n            let py_timezone_utc = new_py_datetime_ob(py, \"timezone\", (py_timedelta,));\n            let py_timezone_utc: Offset = py_timezone_utc.extract().unwrap();\n            assert_eq!(Offset::UTC, py_timezone_utc);\n\n            let py_timedelta = new_py_datetime_ob(py, \"timedelta\", (0, 3600, 0));\n            let py_timezone = new_py_datetime_ob(py, \"timezone\", (py_timedelta,));\n            assert_ne!(Offset::UTC, py_timezone.extract::<Offset>().unwrap());\n        })\n    }\n\n    #[test]\n    fn test_pyo3_time_into_pyobject() {\n        Python::attach(|py| {\n            let check_time = |name: &'static str, hour, minute, second, ms, py_ms| {\n                let time = Time::new(hour, minute, second, ms * 1000)\n                    .unwrap()\n                    .into_pyobject(py)\n                    .unwrap();\n                let py_time = new_py_datetime_ob(py, \"time\", (hour, minute, second, py_ms));\n                assert!(time.eq(&py_time).unwrap(), \"{name}: {time} != {py_time}\");\n            };\n\n            check_time(\"regular\", 3, 5, 7, 999_999, 999_999);\n        })\n    }\n\n    #[test]\n    fn test_pyo3_time_frompyobject() {\n        let hour = 3;\n        let minute = 5;\n        let second = 7;\n        let micro = 999_999;\n        Python::attach(|py| {\n            let py_time = new_py_datetime_ob(py, \"time\", (hour, minute, second, micro));\n            let py_time: Time = py_time.extract().unwrap();\n            let time = Time::new(hour, minute, second, micro * 1000).unwrap();\n            assert_eq!(py_time, time);\n        })\n    }\n\n    fn new_py_datetime_ob<'py, A>(py: Python<'py>, name: &str, args: A) -> Bound<'py, PyAny>\n    where\n        A: IntoPyObject<'py, Target = PyTuple>,\n    {\n        py.import(\"datetime\")\n            .unwrap()\n            .getattr(name)\n            .unwrap()\n            .call1(\n                args.into_pyobject(py)\n                    .map_err(Into::into)\n                    .unwrap()\n                    .into_bound(),\n            )\n            .unwrap()\n    }\n\n    fn python_utc(py: Python<'_>) -> Bound<'_, PyAny> {\n        py.import(\"datetime\")\n            .unwrap()\n            .getattr(\"timezone\")\n            .unwrap()\n            .getattr(\"utc\")\n            .unwrap()\n    }\n\n    #[cfg(all(Py_3_9, not(windows)))]\n    fn python_zoneinfo<'py>(py: Python<'py>, timezone: &str) -> Bound<'py, PyAny> {\n        py.import(\"zoneinfo\")\n            .unwrap()\n            .getattr(\"ZoneInfo\")\n            .unwrap()\n            .call1((timezone,))\n            .unwrap()\n    }\n\n    #[cfg(not(any(target_arch = \"wasm32\", Py_GIL_DISABLED)))]\n    mod proptests {\n        use super::*;\n        use crate::types::IntoPyDict;\n        use jiff::tz::TimeZoneTransition;\n        use jiff::SpanRelativeTo;\n        use proptest::prelude::*;\n        use std::ffi::CString;\n\n        // This is to skip the test if we are creating an invalid date, like February 31.\n        #[track_caller]\n        fn try_date(year: i16, month: i8, day: i8) -> Result<Date, TestCaseError> {\n            let location = std::panic::Location::caller();\n            Date::new(year, month, day)\n                .map_err(|err| TestCaseError::reject(format!(\"{location}: {err:?}\")))\n        }\n\n        #[track_caller]\n        fn try_time(hour: i8, min: i8, sec: i8, micro: i32) -> Result<Time, TestCaseError> {\n            let location = std::panic::Location::caller();\n            Time::new(hour, min, sec, micro * 1000)\n                .map_err(|err| TestCaseError::reject(format!(\"{location}: {err:?}\")))\n        }\n\n        #[expect(clippy::too_many_arguments)]\n        fn try_zoned(\n            year: i16,\n            month: i8,\n            day: i8,\n            hour: i8,\n            min: i8,\n            sec: i8,\n            micro: i32,\n            tz: TimeZone,\n        ) -> Result<Zoned, TestCaseError> {\n            let date = try_date(year, month, day)?;\n            let time = try_time(hour, min, sec, micro)?;\n            let location = std::panic::Location::caller();\n            DateTime::from_parts(date, time)\n                .to_zoned(tz)\n                .map_err(|err| TestCaseError::reject(format!(\"{location}: {err:?}\")))\n        }\n\n        prop_compose! {\n            fn timezone_transitions(timezone: &TimeZone)\n                            (year in 1900i16..=2100i16, month in 1i8..=12i8)\n                            -> TimeZoneTransition<'_> {\n                let datetime = DateTime::new(year, month, 1, 0, 0, 0, 0).unwrap();\n                let timestamp= timezone.to_zoned(datetime).unwrap().timestamp();\n                timezone.following(timestamp).next().unwrap()\n            }\n        }\n\n        proptest! {\n\n            // Range is limited to 1970 to 2038 due to windows limitations\n            #[test]\n            fn test_pyo3_offset_fixed_frompyobject_created_in_python(timestamp in 0..(i32::MAX as i64), timedelta in -86399i32..=86399i32) {\n                Python::attach(|py| {\n                    let globals = [(\"datetime\", py.import(\"datetime\").unwrap())].into_py_dict(py).unwrap();\n                    let code = format!(\"datetime.datetime.fromtimestamp({timestamp}).replace(tzinfo=datetime.timezone(datetime.timedelta(seconds={timedelta})))\");\n                    let t = py.eval(&CString::new(code).unwrap(), Some(&globals), None).unwrap();\n\n                    // Get ISO 8601 string from python\n                    let py_iso_str = t.call_method0(\"isoformat\").unwrap();\n\n                    // Get ISO 8601 string from rust\n                    let rust_iso_str = t.extract::<Zoned>().unwrap().strftime(\"%Y-%m-%dT%H:%M:%S%:z\").to_string();\n\n                    // They should be equal\n                    prop_assert_eq!(py_iso_str.to_string(), rust_iso_str);\n                    Ok(())\n                })?;\n            }\n\n            #[test]\n            fn test_duration_roundtrip(days in -999999999i64..=999999999i64) {\n                // Test roundtrip conversion rust->python->rust for all allowed\n                // python values of durations (from -999999999 to 999999999 days),\n                Python::attach(|py| {\n                    let dur = SignedDuration::new(days * 24 * 60 * 60, 0);\n                    let py_delta = dur.into_pyobject(py).unwrap();\n                    let roundtripped: SignedDuration = py_delta.extract().expect(\"Round trip\");\n                    prop_assert_eq!(dur, roundtripped);\n                    Ok(())\n                })?;\n            }\n\n            #[test]\n            fn test_span_roundtrip(days in -999999999i64..=999999999i64) {\n                // Test roundtrip conversion rust->python->rust for all allowed\n                // python values of durations (from -999999999 to 999999999 days),\n                Python::attach(|py| {\n                    if let Ok(span) = Span::new().try_days(days) {\n                        let relative_to = SpanRelativeTo::days_are_24_hours();\n                        let jiff_duration = span.to_duration(relative_to).unwrap();\n                        let py_delta = jiff_duration.into_pyobject(py).unwrap();\n                        let roundtripped: Span = py_delta.extract().expect(\"Round trip\");\n                        prop_assert_eq!(span.compare((roundtripped, relative_to)).unwrap(), Ordering::Equal);\n                    }\n                    Ok(())\n                })?;\n            }\n\n            #[test]\n            fn test_fixed_offset_roundtrip(secs in -86399i32..=86399i32) {\n                Python::attach(|py| {\n                    let offset = Offset::from_seconds(secs).unwrap();\n                    let py_offset = offset.into_pyobject(py).unwrap();\n                    let roundtripped: Offset = py_offset.extract().expect(\"Round trip\");\n                    prop_assert_eq!(offset, roundtripped);\n                    Ok(())\n                })?;\n            }\n\n            #[test]\n            fn test_naive_date_roundtrip(\n                year in 1i16..=9999i16,\n                month in 1i8..=12i8,\n                day in 1i8..=31i8\n            ) {\n                // Test roundtrip conversion rust->python->rust for all allowed\n                // python dates (from year 1 to year 9999)\n                Python::attach(|py| {\n                    let date = try_date(year, month, day)?;\n                    let py_date = date.into_pyobject(py).unwrap();\n                    let roundtripped: Date = py_date.extract().expect(\"Round trip\");\n                    prop_assert_eq!(date, roundtripped);\n                    Ok(())\n                })?;\n            }\n\n            #[test]\n            fn test_weekdate_roundtrip(\n                year in 1i16..=9999i16,\n                month in 1i8..=12i8,\n                day in 1i8..=31i8\n            ) {\n                // Test roundtrip conversion rust->python->rust for all allowed\n                // python dates (from year 1 to year 9999)\n                Python::attach(|py| {\n                    let weekdate = try_date(year, month, day)?.iso_week_date();\n                    let py_date = weekdate.into_pyobject(py).unwrap();\n                    let roundtripped = py_date.extract::<ISOWeekDate>().expect(\"Round trip\");\n                    prop_assert_eq!(weekdate, roundtripped);\n                    Ok(())\n                })?;\n            }\n\n            #[test]\n            fn test_naive_time_roundtrip(\n                hour in 0i8..=23i8,\n                min in 0i8..=59i8,\n                sec in 0i8..=59i8,\n                micro in 0i32..=999_999i32\n            ) {\n                Python::attach(|py| {\n                    let time = try_time(hour, min, sec, micro)?;\n                    let py_time = time.into_pyobject(py).unwrap();\n                    let roundtripped: Time = py_time.extract().expect(\"Round trip\");\n                    prop_assert_eq!(time, roundtripped);\n                    Ok(())\n                })?;\n            }\n\n            #[test]\n            fn test_naive_datetime_roundtrip(\n                year in 1i16..=9999i16,\n                month in 1i8..=12i8,\n                day in 1i8..=31i8,\n                hour in 0i8..=23i8,\n                min in 0i8..=59i8,\n                sec in 0i8..=59i8,\n                micro in 0i32..=999_999i32\n            ) {\n                Python::attach(|py| {\n                    let date = try_date(year, month, day)?;\n                    let time = try_time(hour, min, sec, micro)?;\n                    let dt = DateTime::from_parts(date, time);\n                    let pydt = dt.into_pyobject(py).unwrap();\n                    let roundtripped: DateTime = pydt.extract().expect(\"Round trip\");\n                    prop_assert_eq!(dt, roundtripped);\n                    Ok(())\n                })?;\n            }\n\n            #[test]\n            fn test_utc_datetime_roundtrip(\n                year in 1i16..=9999i16,\n                month in 1i8..=12i8,\n                day in 1i8..=31i8,\n                hour in 0i8..=23i8,\n                min in 0i8..=59i8,\n                sec in 0i8..=59i8,\n                micro in 0i32..=999_999i32\n            ) {\n                Python::attach(|py| {\n                    let dt: Zoned = try_zoned(year, month, day, hour, min, sec, micro, TimeZone::UTC)?;\n                    let py_dt = (&dt).into_pyobject(py).unwrap();\n                    let roundtripped: Zoned = py_dt.extract().expect(\"Round trip\");\n                    prop_assert_eq!(dt, roundtripped);\n                    Ok(())\n                })?;\n            }\n\n            #[test]\n            fn test_fixed_offset_datetime_roundtrip(\n                year in 1i16..=9999i16,\n                month in 1i8..=12i8,\n                day in 1i8..=31i8,\n                hour in 0i8..=23i8,\n                min in 0i8..=59i8,\n                sec in 0i8..=59i8,\n                micro in 0i32..=999_999i32,\n                offset_secs in -86399i32..=86399i32\n            ) {\n                Python::attach(|py| {\n                    let offset = Offset::from_seconds(offset_secs).unwrap();\n                    let dt = try_zoned(year, month, day, hour, min, sec, micro, offset.to_time_zone())?;\n                    let py_dt = (&dt).into_pyobject(py).unwrap();\n                    let roundtripped: Zoned = py_dt.extract().expect(\"Round trip\");\n                    prop_assert_eq!(dt, roundtripped);\n                    Ok(())\n                })?;\n            }\n\n            #[test]\n            #[cfg(all(Py_3_9, not(windows)))]\n            fn test_zoned_datetime_roundtrip_around_timezone_transition(\n                (timezone, transition) in prop_oneof![\n                                Just(&TimeZone::get(\"Europe/London\").unwrap()),\n                                Just(&TimeZone::get(\"America/New_York\").unwrap()),\n                                Just(&TimeZone::get(\"Australia/Sydney\").unwrap()),\n                            ].prop_flat_map(|tz| (Just(tz), timezone_transitions(tz))),\n                hour in -2i32..=2i32,\n                min in 0u32..=59u32,\n            ) {\n                Python::attach(|py| {\n                    let transition_moment = transition.timestamp();\n                    let zoned = (transition_moment - Span::new().hours(hour).minutes(min))\n                        .to_zoned(timezone.clone());\n\n                    let py_dt = (&zoned).into_pyobject(py).unwrap();\n                    let roundtripped: Zoned = py_dt.extract().expect(\"Round trip\");\n                    prop_assert_eq!(zoned, roundtripped);\n                    Ok(())\n                })?;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/conversions/mod.rs",
    "content": "//! This module contains conversions between various Rust object and their representation in Python.\n\npub mod anyhow;\npub mod bigdecimal;\npub mod bytes;\npub mod chrono;\npub mod chrono_tz;\npub mod either;\npub mod eyre;\npub mod hashbrown;\npub mod indexmap;\npub mod jiff;\npub mod num_bigint;\npub mod num_complex;\npub mod num_rational;\npub mod ordered_float;\npub mod rust_decimal;\npub mod serde;\npub mod smallvec;\npub(crate) mod std;\npub mod time;\npub mod uuid;\n"
  },
  {
    "path": "src/conversions/num_bigint.rs",
    "content": "#![cfg(feature = \"num-bigint\")]\n//!  Conversions to and from [num-bigint](https://docs.rs/num-bigint)’s [`BigInt`] and [`BigUint`] types.\n//!\n//! This is useful for converting Python integers when they may not fit in Rust's built-in integer types.\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! num-bigint = \"*\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"num-bigint\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of num-bigint and PyO3.\n//! The required num-bigint version may vary based on the version of PyO3.\n//!\n//! ## Examples\n//!\n//! Using [`BigInt`] to correctly increment an arbitrary precision integer.\n//! This is not possible with Rust's native integers if the Python integer is too large,\n//! in which case it will fail its conversion and raise `OverflowError`.\n//! ```rust,no_run\n//! use num_bigint::BigInt;\n//! use pyo3::prelude::*;\n//!\n//! #[pyfunction]\n//! fn add_one(n: BigInt) -> BigInt {\n//!     n + 1\n//! }\n//!\n//! #[pymodule]\n//! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n//!     m.add_function(wrap_pyfunction!(add_one, m)?)?;\n//!     Ok(())\n//! }\n//! ```\n//!\n//! Python code:\n//! ```python\n//! from my_module import add_one\n//!\n//! n = 1 << 1337\n//! value = add_one(n)\n//!\n//! assert n + 1 == value\n//! ```\n\n#[cfg(Py_LIMITED_API)]\nuse crate::types::{bytes::PyBytesMethods, PyBytes};\nuse crate::{\n    conversion::IntoPyObject, std::num::nb_index, types::PyInt, Borrowed, Bound, FromPyObject,\n    PyAny, PyErr, PyResult, Python,\n};\n\nuse num_bigint::{BigInt, BigUint};\n\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::PyTypeInfo;\n#[cfg(not(Py_LIMITED_API))]\nuse num_bigint::Sign;\n\n// for identical functionality between BigInt and BigUint\nmacro_rules! bigint_conversion {\n    ($rust_ty: ty, $is_signed: literal) => {\n        #[cfg_attr(docsrs, doc(cfg(feature = \"num-bigint\")))]\n        impl<'py> IntoPyObject<'py> for $rust_ty {\n            type Target = PyInt;\n            type Output = Bound<'py, Self::Target>;\n            type Error = PyErr;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = <&$rust_ty>::OUTPUT_TYPE;\n\n            #[inline]\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                (&self).into_pyobject(py)\n            }\n        }\n\n        #[cfg_attr(docsrs, doc(cfg(feature = \"num-bigint\")))]\n        impl<'py> IntoPyObject<'py> for &$rust_ty {\n            type Target = PyInt;\n            type Output = Bound<'py, Self::Target>;\n            type Error = PyErr;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                use num_traits::ToBytes;\n\n                #[cfg(all(not(Py_LIMITED_API), Py_3_13))]\n                {\n                    use crate::conversions::std::num::int_from_ne_bytes;\n                    let bytes = self.to_ne_bytes();\n                    Ok(int_from_ne_bytes::<{ $is_signed }>(py, &bytes))\n                }\n\n                #[cfg(all(not(Py_LIMITED_API), not(Py_3_13)))]\n                {\n                    use crate::conversions::std::num::int_from_le_bytes;\n                    let bytes = self.to_le_bytes();\n                    Ok(int_from_le_bytes::<{ $is_signed }>(py, &bytes))\n                }\n\n                #[cfg(Py_LIMITED_API)]\n                {\n                    use $crate::py_result_ext::PyResultExt;\n                    use $crate::types::any::PyAnyMethods;\n                    let bytes = self.to_le_bytes();\n                    let bytes_obj = PyBytes::new(py, &bytes);\n                    let kwargs = if $is_signed {\n                        let kwargs = crate::types::PyDict::new(py);\n                        kwargs.set_item(crate::intern!(py, \"signed\"), true)?;\n                        Some(kwargs)\n                    } else {\n                        None\n                    };\n                    unsafe {\n                        py.get_type::<PyInt>()\n                            .call_method(\"from_bytes\", (bytes_obj, \"little\"), kwargs.as_ref())\n                            .cast_into_unchecked()\n                    }\n                }\n            }\n        }\n    };\n}\n\nbigint_conversion!(BigUint, false);\nbigint_conversion!(BigInt, true);\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"num-bigint\")))]\nimpl<'py> FromPyObject<'_, 'py> for BigInt {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> Result<BigInt, Self::Error> {\n        // fast path - checking for subclass of `int` just checks a bit in the type object\n        let num_owned: Bound<'_, PyInt>;\n        let num = if let Ok(long) = ob.cast::<PyInt>() {\n            long\n        } else {\n            num_owned = nb_index(&ob)?;\n            num_owned.as_borrowed()\n        };\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            let mut buffer = int_to_u32_vec::<true>(&num)?;\n            let sign = if buffer.last().copied().is_some_and(|last| last >> 31 != 0) {\n                // BigInt::new takes an unsigned array, so need to convert from two's complement\n                // flip all bits, 'subtract' 1 (by adding one to the unsigned array)\n                let mut elements = buffer.iter_mut();\n                for element in elements.by_ref() {\n                    *element = (!*element).wrapping_add(1);\n                    if *element != 0 {\n                        // if the element didn't wrap over, no need to keep adding further ...\n                        break;\n                    }\n                }\n                // ... so just two's complement the rest\n                for element in elements {\n                    *element = !*element;\n                }\n                Sign::Minus\n            } else {\n                Sign::Plus\n            };\n            Ok(BigInt::new(sign, buffer))\n        }\n        #[cfg(Py_LIMITED_API)]\n        {\n            let n_bits = int_n_bits(&num)?;\n            if n_bits == 0 {\n                return Ok(BigInt::from(0isize));\n            }\n            let bytes = int_to_py_bytes(&num, (n_bits + 8) / 8, true)?;\n            Ok(BigInt::from_signed_bytes_le(bytes.as_bytes()))\n        }\n    }\n}\n\n#[cfg_attr(docsrs, doc(cfg(feature = \"num-bigint\")))]\nimpl<'py> FromPyObject<'_, 'py> for BigUint {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> Result<BigUint, Self::Error> {\n        // fast path - checking for subclass of `int` just checks a bit in the type object\n        let num_owned: Bound<'_, PyInt>;\n        let num = if let Ok(long) = ob.cast::<PyInt>() {\n            long\n        } else {\n            num_owned = nb_index(&ob)?;\n            num_owned.as_borrowed()\n        };\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            let buffer = int_to_u32_vec::<false>(&num)?;\n            Ok(BigUint::new(buffer))\n        }\n        #[cfg(Py_LIMITED_API)]\n        {\n            let n_bits = int_n_bits(&num)?;\n            if n_bits == 0 {\n                return Ok(BigUint::from(0usize));\n            }\n            let bytes = int_to_py_bytes(&num, n_bits.div_ceil(8), false)?;\n            Ok(BigUint::from_bytes_le(bytes.as_bytes()))\n        }\n    }\n}\n\n#[cfg(not(any(Py_LIMITED_API, Py_3_13)))]\n#[inline]\nfn int_to_u32_vec<const SIGNED: bool>(long: &Bound<'_, PyInt>) -> PyResult<Vec<u32>> {\n    use crate::ffi;\n\n    let mut buffer = Vec::new();\n    let n_bits = int_n_bits(long)?;\n    if n_bits == 0 {\n        return Ok(buffer);\n    }\n    let n_digits = if SIGNED {\n        (n_bits + 32) / 32\n    } else {\n        n_bits.div_ceil(32)\n    };\n    buffer.reserve_exact(n_digits);\n    unsafe {\n        crate::err::error_on_minusone(\n            long.py(),\n            ffi::_PyLong_AsByteArray(\n                long.as_ptr().cast(),\n                buffer.as_mut_ptr() as *mut u8,\n                n_digits * 4,\n                1,\n                SIGNED.into(),\n            ),\n        )?;\n        buffer.set_len(n_digits)\n    };\n    buffer\n        .iter_mut()\n        .for_each(|chunk| *chunk = u32::from_le(*chunk));\n\n    Ok(buffer)\n}\n\n#[cfg(all(not(Py_LIMITED_API), Py_3_13))]\n#[inline]\nfn int_to_u32_vec<const SIGNED: bool>(long: &Bound<'_, PyInt>) -> PyResult<Vec<u32>> {\n    use crate::ffi;\n\n    let mut buffer = Vec::new();\n    let mut flags = ffi::Py_ASNATIVEBYTES_LITTLE_ENDIAN;\n    if !SIGNED {\n        flags |= ffi::Py_ASNATIVEBYTES_UNSIGNED_BUFFER | ffi::Py_ASNATIVEBYTES_REJECT_NEGATIVE;\n    }\n    let n_bytes =\n        unsafe { ffi::PyLong_AsNativeBytes(long.as_ptr().cast(), std::ptr::null_mut(), 0, flags) };\n    let n_bytes_unsigned: usize = n_bytes\n        .try_into()\n        .map_err(|_| crate::PyErr::fetch(long.py()))?;\n    if n_bytes == 0 {\n        return Ok(buffer);\n    }\n    let n_digits = n_bytes_unsigned.div_ceil(4);\n    buffer.reserve_exact(n_digits);\n    unsafe {\n        ffi::PyLong_AsNativeBytes(\n            long.as_ptr().cast(),\n            buffer.as_mut_ptr().cast(),\n            (n_digits * 4).try_into().unwrap(),\n            flags,\n        );\n        buffer.set_len(n_digits);\n    };\n    buffer\n        .iter_mut()\n        .for_each(|chunk| *chunk = u32::from_le(*chunk));\n\n    Ok(buffer)\n}\n\n#[cfg(Py_LIMITED_API)]\nfn int_to_py_bytes<'py>(\n    long: &Bound<'py, PyInt>,\n    n_bytes: usize,\n    is_signed: bool,\n) -> PyResult<Bound<'py, PyBytes>> {\n    use crate::intern;\n    use crate::types::any::PyAnyMethods;\n    let py = long.py();\n    let kwargs = if is_signed {\n        let kwargs = crate::types::PyDict::new(py);\n        kwargs.set_item(intern!(py, \"signed\"), true)?;\n        Some(kwargs)\n    } else {\n        None\n    };\n    let bytes = long.call_method(\n        intern!(py, \"to_bytes\"),\n        (n_bytes, intern!(py, \"little\")),\n        kwargs.as_ref(),\n    )?;\n    Ok(bytes.cast_into()?)\n}\n\n#[inline]\n#[cfg(any(not(Py_3_13), Py_LIMITED_API))]\nfn int_n_bits(long: &Bound<'_, PyInt>) -> PyResult<usize> {\n    let py = long.py();\n    #[cfg(not(Py_LIMITED_API))]\n    {\n        // fast path\n        let n_bits = unsafe { crate::ffi::_PyLong_NumBits(long.as_ptr()) };\n        if n_bits == (-1isize as usize) {\n            return Err(crate::PyErr::fetch(py));\n        }\n        Ok(n_bits)\n    }\n\n    #[cfg(Py_LIMITED_API)]\n    {\n        // slow path\n        use crate::types::PyAnyMethods;\n        long.call_method0(crate::intern!(py, \"bit_length\"))\n            .and_then(|any| any.extract())\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::exceptions::PyTypeError;\n    use crate::test_utils::generate_unique_module_name;\n    use crate::types::{PyAnyMethods as _, PyDict, PyModule};\n    use pyo3_ffi::c_str;\n\n    fn rust_fib<T>() -> impl Iterator<Item = T>\n    where\n        T: From<u16>,\n        for<'a> &'a T: std::ops::Add<Output = T>,\n    {\n        let mut f0: T = T::from(1);\n        let mut f1: T = T::from(1);\n        std::iter::from_fn(move || {\n            let f2 = &f0 + &f1;\n            Some(std::mem::replace(&mut f0, std::mem::replace(&mut f1, f2)))\n        })\n    }\n\n    fn python_fib(py: Python<'_>) -> impl Iterator<Item = Bound<'_, PyAny>> + '_ {\n        let mut f0 = 1i32.into_pyobject(py).unwrap().into_any();\n        let mut f1 = 1i32.into_pyobject(py).unwrap().into_any();\n        std::iter::from_fn(move || {\n            let f2 = f0.call_method1(\"__add__\", (&f1,)).unwrap();\n            Some(std::mem::replace(&mut f0, std::mem::replace(&mut f1, f2)))\n        })\n    }\n\n    #[test]\n    fn convert_biguint() {\n        Python::attach(|py| {\n            // check the first 2000 numbers in the fibonacci sequence\n            for (py_result, rs_result) in python_fib(py).zip(rust_fib::<BigUint>()).take(2000) {\n                // Python -> Rust\n                assert_eq!(py_result.extract::<BigUint>().unwrap(), rs_result);\n                // Rust -> Python\n                assert!(py_result.eq(rs_result).unwrap());\n            }\n        });\n    }\n\n    #[test]\n    fn convert_bigint() {\n        Python::attach(|py| {\n            // check the first 2000 numbers in the fibonacci sequence\n            for (py_result, rs_result) in python_fib(py).zip(rust_fib::<BigInt>()).take(2000) {\n                // Python -> Rust\n                assert_eq!(py_result.extract::<BigInt>().unwrap(), rs_result);\n                // Rust -> Python\n                assert!(py_result.eq(&rs_result).unwrap());\n\n                // negate\n\n                let rs_result = rs_result * -1;\n                let py_result = py_result.call_method0(\"__neg__\").unwrap();\n\n                // Python -> Rust\n                assert_eq!(py_result.extract::<BigInt>().unwrap(), rs_result);\n                // Rust -> Python\n                assert!(py_result.eq(rs_result).unwrap());\n            }\n        });\n    }\n\n    fn python_index_class(py: Python<'_>) -> Bound<'_, PyModule> {\n        let index_code = c_str!(\n            r#\"\nclass C:\n    def __init__(self, x):\n        self.x = x\n    def __index__(self):\n        return self.x\n\"#\n        );\n        PyModule::from_code(\n            py,\n            index_code,\n            c\"index.py\",\n            &generate_unique_module_name(\"index\"),\n        )\n        .unwrap()\n    }\n\n    #[test]\n    fn convert_index_class() {\n        Python::attach(|py| {\n            let index = python_index_class(py);\n            let locals = PyDict::new(py);\n            locals.set_item(\"index\", index).unwrap();\n            let ob = py.eval(c\"index.C(10)\", None, Some(&locals)).unwrap();\n            let _: BigInt = ob.extract().unwrap();\n            let _: BigUint = ob.extract().unwrap();\n        });\n    }\n\n    #[test]\n    fn handle_zero() {\n        Python::attach(|py| {\n            let zero: BigInt = 0i32.into_pyobject(py).unwrap().extract().unwrap();\n            assert_eq!(zero, BigInt::from(0));\n        })\n    }\n\n    /// `OverflowError` on converting Python int to BigInt, see issue #629\n    #[test]\n    fn check_overflow() {\n        Python::attach(|py| {\n            macro_rules! test {\n                ($T:ty, $value:expr, $py:expr) => {\n                    let value = $value;\n                    println!(\"{}: {}\", stringify!($T), value);\n                    let python_value = value.clone().into_pyobject(py).unwrap();\n                    let roundtrip_value = python_value.extract::<$T>().unwrap();\n                    assert_eq!(value, roundtrip_value);\n                };\n            }\n\n            for i in 0..=256usize {\n                // test a lot of values to help catch other bugs too\n                test!(BigInt, BigInt::from(i), py);\n                test!(BigUint, BigUint::from(i), py);\n                test!(BigInt, -BigInt::from(i), py);\n                test!(BigInt, BigInt::from(1) << i, py);\n                test!(BigUint, BigUint::from(1u32) << i, py);\n                test!(BigInt, -BigInt::from(1) << i, py);\n                test!(BigInt, (BigInt::from(1) << i) + 1u32, py);\n                test!(BigUint, (BigUint::from(1u32) << i) + 1u32, py);\n                test!(BigInt, (-BigInt::from(1) << i) + 1u32, py);\n                test!(BigInt, (BigInt::from(1) << i) - 1u32, py);\n                test!(BigUint, (BigUint::from(1u32) << i) - 1u32, py);\n                test!(BigInt, (-BigInt::from(1) << i) - 1u32, py);\n            }\n        });\n    }\n\n    #[test]\n    fn from_py_float_type_error() {\n        Python::attach(|py| {\n            let obj = (12.3f64).into_pyobject(py).unwrap();\n            let err = obj.extract::<BigInt>().unwrap_err();\n            assert!(err.is_instance_of::<PyTypeError>(py));\n\n            let err = obj.extract::<BigUint>().unwrap_err();\n            assert!(err.is_instance_of::<PyTypeError>(py));\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/num_complex.rs",
    "content": "#![cfg(feature = \"num-complex\")]\n\n//!  Conversions to and from [num-complex](https://docs.rs/num-complex)’\n//! [`Complex`]`<`[`f32`]`>` and [`Complex`]`<`[`f64`]`>`.\n//!\n//! num-complex’ [`Complex`] supports more operations than PyO3's [`PyComplex`]\n//! and can be used with the rest of the Rust ecosystem.\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! # change * to the latest versions\n//! num-complex = \"*\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"num-complex\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of num-complex and PyO3.\n//! The required num-complex version may vary based on the version of PyO3.\n//!\n//! # Examples\n//!\n//! Using [num-complex](https://docs.rs/num-complex) and [nalgebra](https://docs.rs/nalgebra)\n//! to create a pyfunction that calculates the eigenvalues of a 2x2 matrix.\n//! ```ignore\n//! # // not tested because nalgebra isn't supported on msrv\n//! # // please file an issue if it breaks!\n//! use nalgebra::base::{dimension::Const, Matrix};\n//! use num_complex::Complex;\n//! use pyo3::prelude::*;\n//!\n//! type T = Complex<f64>;\n//!\n//! #[pyfunction]\n//! fn get_eigenvalues(m11: T, m12: T, m21: T, m22: T) -> Vec<T> {\n//!     let mat = Matrix::<T, Const<2>, Const<2>, _>::new(m11, m12, m21, m22);\n//!\n//!     match mat.eigenvalues() {\n//!         Some(e) => e.data.as_slice().to_vec(),\n//!         None => vec![],\n//!     }\n//! }\n//!\n//! #[pymodule]\n//! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n//!     m.add_function(wrap_pyfunction!(get_eigenvalues, m)?)?;\n//!     Ok(())\n//! }\n//! # // test\n//! # use assert_approx_eq::assert_approx_eq;\n//! # use nalgebra::ComplexField;\n//! # use pyo3::types::PyComplex;\n//! #\n//! # fn main() -> PyResult<()> {\n//! #     Python::attach(|py| -> PyResult<()> {\n//! #         let module = PyModule::new(py, \"my_module\")?;\n//! #\n//! #         module.add_function(&wrap_pyfunction!(get_eigenvalues, module)?)?;\n//! #\n//! #         let m11 = PyComplex::from_doubles(py, 0_f64, -1_f64);\n//! #         let m12 = PyComplex::from_doubles(py, 1_f64, 0_f64);\n//! #         let m21 = PyComplex::from_doubles(py, 2_f64, -1_f64);\n//! #         let m22 = PyComplex::from_doubles(py, -1_f64, 0_f64);\n//! #\n//! #         let result = module\n//! #             .getattr(\"get_eigenvalues\")?\n//! #             .call1((m11, m12, m21, m22))?;\n//! #         println!(\"eigenvalues: {:?}\", result);\n//! #\n//! #         let result = result.extract::<Vec<T>>()?;\n//! #         let e0 = result[0];\n//! #         let e1 = result[1];\n//! #\n//! #         assert_approx_eq!(e0, Complex::new(1_f64, -1_f64));\n//! #         assert_approx_eq!(e1, Complex::new(-2_f64, 0_f64));\n//! #\n//! #         Ok(())\n//! #     })\n//! # }\n//! ```\n//!\n//! Python code:\n//! ```python\n//! from my_module import get_eigenvalues\n//!\n//! m11 = complex(0,-1)\n//! m12 = complex(1,0)\n//! m21 = complex(2,-1)\n//! m22 = complex(-1,0)\n//!\n//! result = get_eigenvalues(m11,m12,m21,m22)\n//! assert result == [complex(1,-1), complex(-2,0)]\n//! ```\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_hint_identifier;\nuse crate::{\n    ffi, ffi_ptr_ext::FfiPtrExt, types::PyComplex, Borrowed, Bound, FromPyObject, PyAny, PyErr,\n    Python,\n};\nuse num_complex::Complex;\nuse std::ffi::c_double;\n\nimpl PyComplex {\n    /// Creates a new Python `PyComplex` object from `num_complex`'s [`Complex`].\n    pub fn from_complex_bound<F: Into<c_double>>(\n        py: Python<'_>,\n        complex: Complex<F>,\n    ) -> Bound<'_, PyComplex> {\n        unsafe {\n            ffi::PyComplex_FromDoubles(complex.re.into(), complex.im.into())\n                .assume_owned(py)\n                .cast_into_unchecked()\n        }\n    }\n}\n\nmacro_rules! complex_conversion {\n    ($float: ty) => {\n        #[cfg_attr(docsrs, doc(cfg(feature = \"num-complex\")))]\n        impl<'py> crate::conversion::IntoPyObject<'py> for Complex<$float> {\n            type Target = PyComplex;\n            type Output = Bound<'py, Self::Target>;\n            type Error = std::convert::Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"builtins\", \"complex\");\n\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                unsafe {\n                    Ok(\n                        ffi::PyComplex_FromDoubles(self.re as c_double, self.im as c_double)\n                            .assume_owned(py)\n                            .cast_into_unchecked(),\n                    )\n                }\n            }\n        }\n\n        #[cfg_attr(docsrs, doc(cfg(feature = \"num-complex\")))]\n        impl<'py> crate::conversion::IntoPyObject<'py> for &Complex<$float> {\n            type Target = PyComplex;\n            type Output = Bound<'py, Self::Target>;\n            type Error = std::convert::Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = <Complex<$float>>::OUTPUT_TYPE;\n\n            #[inline]\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                (*self).into_pyobject(py)\n            }\n        }\n\n        #[cfg_attr(docsrs, doc(cfg(feature = \"num-complex\")))]\n        impl FromPyObject<'_, '_> for Complex<$float> {\n            type Error = PyErr;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const INPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"builtins\", \"complex\");\n\n            fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Complex<$float>, Self::Error> {\n                #[cfg(not(any(Py_LIMITED_API, PyPy)))]\n                unsafe {\n                    let val = ffi::PyComplex_AsCComplex(obj.as_ptr());\n                    if val.real == -1.0 {\n                        if let Some(err) = PyErr::take(obj.py()) {\n                            return Err(err);\n                        }\n                    }\n                    Ok(Complex::new(val.real as $float, val.imag as $float))\n                }\n\n                #[cfg(any(Py_LIMITED_API, PyPy))]\n                unsafe {\n                    use $crate::types::any::PyAnyMethods;\n                    let complex;\n                    let obj = if obj.is_instance_of::<PyComplex>() {\n                        obj\n                    } else if let Some(method) =\n                        obj.lookup_special(crate::intern!(obj.py(), \"__complex__\"))?\n                    {\n                        complex = method.call0()?;\n                        complex.as_borrowed()\n                    } else {\n                        // `obj` might still implement `__float__` or `__index__`, which will be\n                        // handled by `PyComplex_{Real,Imag}AsDouble`, including propagating any\n                        // errors if those methods don't exist / raise exceptions.\n                        obj\n                    };\n                    let ptr = obj.as_ptr();\n                    let real = ffi::PyComplex_RealAsDouble(ptr);\n                    if real == -1.0 {\n                        if let Some(err) = PyErr::take(obj.py()) {\n                            return Err(err);\n                        }\n                    }\n                    let imag = ffi::PyComplex_ImagAsDouble(ptr);\n                    Ok(Complex::new(real as $float, imag as $float))\n                }\n            }\n        }\n    };\n}\ncomplex_conversion!(f32);\ncomplex_conversion!(f64);\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::test_utils::generate_unique_module_name;\n    use crate::types::PyAnyMethods as _;\n    use crate::types::{complex::PyComplexMethods, PyModule};\n    use crate::IntoPyObject;\n\n    #[test]\n    fn from_complex() {\n        Python::attach(|py| {\n            let complex = Complex::new(3.0, 1.2);\n            let py_c = PyComplex::from_complex_bound(py, complex);\n            assert_eq!(py_c.real(), 3.0);\n            assert_eq!(py_c.imag(), 1.2);\n        });\n    }\n    #[test]\n    fn to_from_complex() {\n        Python::attach(|py| {\n            let val = Complex::new(3.0f64, 1.2);\n            let obj = val.into_pyobject(py).unwrap();\n            assert_eq!(obj.extract::<Complex<f64>>().unwrap(), val);\n        });\n    }\n    #[test]\n    fn from_complex_err() {\n        Python::attach(|py| {\n            let obj = vec![1i32].into_pyobject(py).unwrap();\n            assert!(obj.extract::<Complex<f64>>().is_err());\n        });\n    }\n    #[test]\n    fn from_python_magic() {\n        Python::attach(|py| {\n            let module = PyModule::from_code(\n                py,\n                cr#\"\nclass A:\n    def __complex__(self): return 3.0+1.2j\nclass B:\n    def __float__(self): return 3.0\nclass C:\n    def __index__(self): return 3\n                \"#,\n                c\"test.py\",\n                &generate_unique_module_name(\"test\"),\n            )\n            .unwrap();\n            let from_complex = module.getattr(\"A\").unwrap().call0().unwrap();\n            assert_eq!(\n                from_complex.extract::<Complex<f64>>().unwrap(),\n                Complex::new(3.0, 1.2)\n            );\n            let from_float = module.getattr(\"B\").unwrap().call0().unwrap();\n            assert_eq!(\n                from_float.extract::<Complex<f64>>().unwrap(),\n                Complex::new(3.0, 0.0)\n            );\n            // Before Python 3.8, `__index__` wasn't tried by `float`/`complex`.\n            #[cfg(Py_3_8)]\n            {\n                let from_index = module.getattr(\"C\").unwrap().call0().unwrap();\n                assert_eq!(\n                    from_index.extract::<Complex<f64>>().unwrap(),\n                    Complex::new(3.0, 0.0)\n                );\n            }\n        })\n    }\n    #[test]\n    fn from_python_inherited_magic() {\n        Python::attach(|py| {\n            let module = PyModule::from_code(\n                py,\n                cr#\"\nclass First: pass\nclass ComplexMixin:\n    def __complex__(self): return 3.0+1.2j\nclass FloatMixin:\n    def __float__(self): return 3.0\nclass IndexMixin:\n    def __index__(self): return 3\nclass A(First, ComplexMixin): pass\nclass B(First, FloatMixin): pass\nclass C(First, IndexMixin): pass\n                \"#,\n                c\"test.py\",\n                &generate_unique_module_name(\"test\"),\n            )\n            .unwrap();\n            let from_complex = module.getattr(\"A\").unwrap().call0().unwrap();\n            assert_eq!(\n                from_complex.extract::<Complex<f64>>().unwrap(),\n                Complex::new(3.0, 1.2)\n            );\n            let from_float = module.getattr(\"B\").unwrap().call0().unwrap();\n            assert_eq!(\n                from_float.extract::<Complex<f64>>().unwrap(),\n                Complex::new(3.0, 0.0)\n            );\n            #[cfg(Py_3_8)]\n            {\n                let from_index = module.getattr(\"C\").unwrap().call0().unwrap();\n                assert_eq!(\n                    from_index.extract::<Complex<f64>>().unwrap(),\n                    Complex::new(3.0, 0.0)\n                );\n            }\n        })\n    }\n    #[test]\n    fn from_python_noncallable_descriptor_magic() {\n        // Functions and lambdas implement the descriptor protocol in a way that makes\n        // `type(inst).attr(inst)` equivalent to `inst.attr()` for methods, but this isn't the only\n        // way the descriptor protocol might be implemented.\n        Python::attach(|py| {\n            let module = PyModule::from_code(\n                py,\n                cr#\"\nclass A:\n    @property\n    def __complex__(self):\n        return lambda: 3.0+1.2j\n                \"#,\n                c\"test.py\",\n                &generate_unique_module_name(\"test\"),\n            )\n            .unwrap();\n            let obj = module.getattr(\"A\").unwrap().call0().unwrap();\n            assert_eq!(\n                obj.extract::<Complex<f64>>().unwrap(),\n                Complex::new(3.0, 1.2)\n            );\n        })\n    }\n    #[test]\n    fn from_python_nondescriptor_magic() {\n        // Magic methods don't need to implement the descriptor protocol, if they're callable.\n        Python::attach(|py| {\n            let module = PyModule::from_code(\n                py,\n                cr#\"\nclass MyComplex:\n    def __call__(self): return 3.0+1.2j\nclass A:\n    __complex__ = MyComplex()\n                \"#,\n                c\"test.py\",\n                &generate_unique_module_name(\"test\"),\n            )\n            .unwrap();\n            let obj = module.getattr(\"A\").unwrap().call0().unwrap();\n            assert_eq!(\n                obj.extract::<Complex<f64>>().unwrap(),\n                Complex::new(3.0, 1.2)\n            );\n        })\n    }\n}\n"
  },
  {
    "path": "src/conversions/num_rational.rs",
    "content": "#![cfg(feature = \"num-rational\")]\n//! Conversions to and from [num-rational](https://docs.rs/num-rational) types.\n//!\n//! This is useful for converting between Python's [fractions.Fraction](https://docs.python.org/3/library/fractions.html) into and from a native Rust\n//! type.\n//!\n//!\n//! To use this feature, add to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"num-rational\\\"] }\")]\n//! num-rational = \"0.4.1\"\n//! ```\n//!\n//! # Example\n//!\n//! Rust code to create a function that adds five to a fraction:\n//!\n//! ```rust,no_run\n//! use num_rational::Ratio;\n//! use pyo3::prelude::*;\n//!\n//! #[pyfunction]\n//! fn add_five_to_fraction(fraction: Ratio<i32>) -> Ratio<i32> {\n//!     fraction + Ratio::new(5, 1)\n//! }\n//!\n//! #[pymodule]\n//! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n//!     m.add_function(wrap_pyfunction!(add_five_to_fraction, m)?)?;\n//!     Ok(())\n//! }\n//! ```\n//!\n//! Python code that validates the functionality:\n//! ```python\n//! from my_module import add_five_to_fraction\n//! from fractions import Fraction\n//!\n//! fraction = Fraction(2,1)\n//! fraction_plus_five = add_five_to_fraction(f)\n//! assert fraction + 5 == fraction_plus_five\n//! ```\n\nuse crate::conversion::IntoPyObject;\nuse crate::ffi;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::sync::PyOnceLock;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_hint_identifier;\nuse crate::types::any::PyAnyMethods;\nuse crate::types::PyType;\nuse crate::{Borrowed, Bound, FromPyObject, Py, PyAny, PyErr, PyResult, Python};\n#[cfg(feature = \"num-bigint\")]\nuse num_bigint::BigInt;\nuse num_rational::Ratio;\n\nstatic FRACTION_CLS: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n\nfn get_fraction_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> {\n    FRACTION_CLS.import(py, \"fractions\", \"Fraction\")\n}\n\nmacro_rules! rational_conversion {\n    ($int: ty) => {\n        impl<'py> FromPyObject<'_, 'py> for Ratio<$int> {\n            type Error = PyErr;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const INPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"fractions\", \"Fraction\");\n\n            fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n                let py = obj.py();\n                let py_numerator_obj = obj.getattr(crate::intern!(py, \"numerator\"))?;\n                let py_denominator_obj = obj.getattr(crate::intern!(py, \"denominator\"))?;\n                let numerator_owned = unsafe {\n                    Bound::from_owned_ptr_or_err(py, ffi::PyNumber_Long(py_numerator_obj.as_ptr()))?\n                };\n                let denominator_owned = unsafe {\n                    Bound::from_owned_ptr_or_err(\n                        py,\n                        ffi::PyNumber_Long(py_denominator_obj.as_ptr()),\n                    )?\n                };\n                let rs_numerator: $int = numerator_owned.extract()?;\n                let rs_denominator: $int = denominator_owned.extract()?;\n                Ok(Ratio::new(rs_numerator, rs_denominator))\n            }\n        }\n\n        impl<'py> IntoPyObject<'py> for Ratio<$int> {\n            type Target = PyAny;\n            type Output = Bound<'py, Self::Target>;\n            type Error = PyErr;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = <&Ratio<$int>>::OUTPUT_TYPE;\n\n            #[inline]\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                (&self).into_pyobject(py)\n            }\n        }\n\n        impl<'py> IntoPyObject<'py> for &Ratio<$int> {\n            type Target = PyAny;\n            type Output = Bound<'py, Self::Target>;\n            type Error = PyErr;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"fractions\", \"Fraction\");\n\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                get_fraction_cls(py)?.call1((self.numer().clone(), self.denom().clone()))\n            }\n        }\n    };\n}\nrational_conversion!(i8);\nrational_conversion!(i16);\nrational_conversion!(i32);\nrational_conversion!(isize);\nrational_conversion!(i64);\n#[cfg(feature = \"num-bigint\")]\nrational_conversion!(BigInt);\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::dict::PyDictMethods;\n    use crate::types::PyDict;\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use proptest::prelude::*;\n    #[test]\n    fn test_negative_fraction() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            py.run(\n                c\"import fractions\\npy_frac = fractions.Fraction(-0.125)\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let py_frac = locals.get_item(\"py_frac\").unwrap().unwrap();\n            let roundtripped: Ratio<i32> = py_frac.extract().unwrap();\n            let rs_frac = Ratio::new(-1, 8);\n            assert_eq!(roundtripped, rs_frac);\n        })\n    }\n    #[test]\n    fn test_obj_with_incorrect_atts() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            py.run(\n                c\"not_fraction = \\\"contains_incorrect_atts\\\"\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let py_frac = locals.get_item(\"not_fraction\").unwrap().unwrap();\n            assert!(py_frac.extract::<Ratio<i32>>().is_err());\n        })\n    }\n\n    #[test]\n    fn test_fraction_with_fraction_type() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            py.run(\n                c\"import fractions\\npy_frac = fractions.Fraction(fractions.Fraction(10))\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let py_frac = locals.get_item(\"py_frac\").unwrap().unwrap();\n            let roundtripped: Ratio<i32> = py_frac.extract().unwrap();\n            let rs_frac = Ratio::new(10, 1);\n            assert_eq!(roundtripped, rs_frac);\n        })\n    }\n\n    #[test]\n    fn test_fraction_with_decimal() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            py.run(\n                c\"import fractions\\n\\nfrom decimal import Decimal\\npy_frac = fractions.Fraction(Decimal(\\\"1.1\\\"))\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let py_frac = locals.get_item(\"py_frac\").unwrap().unwrap();\n            let roundtripped: Ratio<i32> = py_frac.extract().unwrap();\n            let rs_frac = Ratio::new(11, 10);\n            assert_eq!(roundtripped, rs_frac);\n        })\n    }\n\n    #[test]\n    fn test_fraction_with_num_den() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            py.run(\n                c\"import fractions\\npy_frac = fractions.Fraction(10,5)\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let py_frac = locals.get_item(\"py_frac\").unwrap().unwrap();\n            let roundtripped: Ratio<i32> = py_frac.extract().unwrap();\n            let rs_frac = Ratio::new(10, 5);\n            assert_eq!(roundtripped, rs_frac);\n        })\n    }\n\n    #[cfg(target_arch = \"wasm32\")]\n    #[test]\n    fn test_int_roundtrip() {\n        Python::attach(|py| {\n            let rs_frac = Ratio::new(1i32, 2);\n            let py_frac = rs_frac.into_pyobject(py).unwrap();\n            let roundtripped: Ratio<i32> = py_frac.extract().unwrap();\n            assert_eq!(rs_frac, roundtripped);\n            // float conversion\n        })\n    }\n\n    #[cfg(target_arch = \"wasm32\")]\n    #[test]\n    fn test_big_int_roundtrip() {\n        Python::attach(|py| {\n            let rs_frac = Ratio::from_float(5.5).unwrap();\n            let py_frac = rs_frac.clone().into_pyobject(py).unwrap();\n            let roundtripped: Ratio<BigInt> = py_frac.extract().unwrap();\n            assert_eq!(rs_frac, roundtripped);\n        })\n    }\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    proptest! {\n        #[test]\n        fn test_int_roundtrip(num in any::<i32>(), den in any::<i32>()) {\n            Python::attach(|py| {\n                let rs_frac = Ratio::new(num, den);\n                let py_frac = rs_frac.into_pyobject(py).unwrap();\n                let roundtripped: Ratio<i32> = py_frac.extract().unwrap();\n                assert_eq!(rs_frac, roundtripped);\n            })\n        }\n\n        #[test]\n        #[cfg(feature = \"num-bigint\")]\n        fn test_big_int_roundtrip(num in any::<f32>()) {\n            Python::attach(|py| {\n                let rs_frac = Ratio::from_float(num).unwrap();\n                let py_frac = rs_frac.clone().into_pyobject(py).unwrap();\n                let roundtripped: Ratio<BigInt> = py_frac.extract().unwrap();\n                assert_eq!(roundtripped, rs_frac);\n            })\n        }\n\n    }\n\n    #[test]\n    fn test_infinity() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            let py_bound = py.run(\n                c\"import fractions\\npy_frac = fractions.Fraction(\\\"Infinity\\\")\",\n                None,\n                Some(&locals),\n            );\n            assert!(py_bound.is_err());\n        })\n    }\n}\n"
  },
  {
    "path": "src/conversions/ordered_float.rs",
    "content": "#![cfg(feature = \"ordered-float\")]\n//! Conversions to and from [ordered-float](https://docs.rs/ordered-float) types.\n//! [`NotNan`]`<`[`f32`]`>` and [`NotNan`]`<`[`f64`]`>`.\n//! [`OrderedFloat`]`<`[`f32`]`>` and [`OrderedFloat`]`<`[`f64`]`>`.\n//!\n//! This is useful for converting between Python's float into and from a native Rust type.\n//!\n//! Take care when comparing sorted collections of float types between Python and Rust.\n//! They will likely differ due to the ambiguous sort order of NaNs in Python.\n//\n//!\n//! To use this feature, add to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"ordered-float\\\"] }\")]\n//! ordered-float = \"5.0.0\"\n//! ```\n//!\n//! # Example\n//!\n//! Rust code to create functions that add ordered floats:\n//!\n//! ```rust,no_run\n//! use ordered_float::{NotNan, OrderedFloat};\n//! use pyo3::prelude::*;\n//!\n//! #[pyfunction]\n//! fn add_not_nans(a: NotNan<f64>, b: NotNan<f64>) -> NotNan<f64> {\n//!     a + b\n//! }\n//!\n//! #[pyfunction]\n//! fn add_ordered_floats(a: OrderedFloat<f64>, b: OrderedFloat<f64>) -> OrderedFloat<f64> {\n//!     a + b\n//! }\n//!\n//! #[pymodule]\n//! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n//!     m.add_function(wrap_pyfunction!(add_not_nans, m)?)?;\n//!     m.add_function(wrap_pyfunction!(add_ordered_floats, m)?)?;\n//!     Ok(())\n//! }\n//! ```\n//!\n//! Python code that validates the functionality:\n//! ```python\n//! from my_module import add_not_nans, add_ordered_floats\n//!\n//! assert add_not_nans(1.0,2.0) == 3.0\n//! assert add_ordered_floats(1.0,2.0) == 3.0\n//! ```\n\nuse crate::conversion::IntoPyObject;\nuse crate::exceptions::PyValueError;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::types::PyFloat;\nuse crate::{Borrowed, Bound, FromPyObject, PyAny, Python};\nuse ordered_float::{NotNan, OrderedFloat};\nuse std::convert::Infallible;\n\nmacro_rules! float_conversions {\n    ($wrapper:ident, $float_type:ty, $constructor:expr) => {\n        impl<'a, 'py> FromPyObject<'a, 'py> for $wrapper<$float_type> {\n            type Error = <$float_type as FromPyObject<'a, 'py>>::Error;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const INPUT_TYPE: PyStaticExpr = <$float_type>::INPUT_TYPE;\n\n            fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n                let val: $float_type = obj.extract()?;\n                $constructor(val)\n            }\n        }\n\n        impl<'py> IntoPyObject<'py> for $wrapper<$float_type> {\n            type Target = PyFloat;\n            type Output = Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = <$float_type>::OUTPUT_TYPE;\n\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                self.into_inner().into_pyobject(py)\n            }\n        }\n\n        impl<'py> IntoPyObject<'py> for &$wrapper<$float_type> {\n            type Target = PyFloat;\n            type Output = Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = <$wrapper<$float_type>>::OUTPUT_TYPE;\n\n            #[inline]\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                (*self).into_pyobject(py)\n            }\n        }\n    };\n}\nfloat_conversions!(OrderedFloat, f32, |val| Ok(OrderedFloat(val)));\nfloat_conversions!(OrderedFloat, f64, |val| Ok(OrderedFloat(val)));\nfloat_conversions!(NotNan, f32, |val| NotNan::new(val)\n    .map_err(|e| PyValueError::new_err(e.to_string())));\nfloat_conversions!(NotNan, f64, |val| NotNan::new(val)\n    .map_err(|e| PyValueError::new_err(e.to_string())));\n\n#[cfg(test)]\nmod test_ordered_float {\n    use super::*;\n    use crate::types::dict::IntoPyDict;\n    use crate::types::PyAnyMethods;\n    use std::ffi::CStr;\n    use std::ffi::CString;\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use proptest::prelude::*;\n\n    fn py_run<'py>(py: Python<'py>, script: &CStr, locals: impl IntoPyDict<'py>) {\n        py.run(script, None, Some(&locals.into_py_dict(py).unwrap()))\n            .unwrap()\n    }\n\n    macro_rules! float_roundtrip_tests {\n        ($wrapper:ident, $float_type:ty, $constructor:expr, $standard_test:ident, $wasm_test:ident, $infinity_test:ident, $zero_test:ident) => {\n            #[cfg(not(target_arch = \"wasm32\"))]\n            proptest! {\n            #[test]\n            fn $standard_test(inner_f: $float_type) {\n                let f = $constructor(inner_f);\n\n                Python::attach(|py| {\n                    let f_py: Bound<'_, PyFloat>  = f.into_pyobject(py).unwrap();\n\n                    py_run(py, &CString::new(format!(\n                            \"import math\\nassert math.isclose(f_py, {})\",\n                             inner_f as f64 // Always interpret the literal rs float value as f64\n                                            // so that it's comparable with the python float\n                        )).unwrap(), [(\"f_py\", &f_py)]);\n\n                    let roundtripped_f: $wrapper<$float_type> = f_py.extract().unwrap();\n\n                    assert_eq!(f, roundtripped_f);\n                })\n            }\n            }\n\n            #[cfg(target_arch = \"wasm32\")]\n            #[test]\n            fn $wasm_test() {\n                let inner_f = 10.0;\n                let f = $constructor(inner_f);\n\n                Python::attach(|py| {\n                    let f_py: Bound<'_, PyFloat> = f.into_pyobject(py).unwrap();\n\n                    py_run(\n                        py,\n                        &CString::new(format!(\n                            \"import math\\nassert math.isclose(f_py, {})\",\n                            inner_f as f64 // Always interpret the literal rs float value as f64\n                                           // so that it's comparable with the python float\n                        ))\n                        .unwrap(),\n                        [(\"f_py\", &f_py)],\n                    );\n\n                    let roundtripped_f: $wrapper<$float_type> = f_py.extract().unwrap();\n\n                    assert_eq!(f, roundtripped_f);\n                })\n            }\n\n            #[test]\n            fn $infinity_test() {\n                let inner_pinf = <$float_type>::INFINITY;\n                let pinf = $constructor(inner_pinf);\n\n                let inner_ninf = <$float_type>::NEG_INFINITY;\n                let ninf = $constructor(inner_ninf);\n\n                Python::attach(|py| {\n                    let pinf_py: Bound<'_, PyFloat> = pinf.into_pyobject(py).unwrap();\n                    let ninf_py: Bound<'_, PyFloat> = ninf.into_pyobject(py).unwrap();\n\n                    py_run(\n                        py,\n                        c\"\\\n                        assert pinf_py == float('inf')\\n\\\n                        assert ninf_py == float('-inf')\",\n                        [(\"pinf_py\", &pinf_py), (\"ninf_py\", &ninf_py)],\n                    );\n\n                    let roundtripped_pinf: $wrapper<$float_type> = pinf_py.extract().unwrap();\n                    let roundtripped_ninf: $wrapper<$float_type> = ninf_py.extract().unwrap();\n\n                    assert_eq!(pinf, roundtripped_pinf);\n                    assert_eq!(ninf, roundtripped_ninf);\n                })\n            }\n\n            #[test]\n            fn $zero_test() {\n                let inner_pzero: $float_type = 0.0;\n                let pzero = $constructor(inner_pzero);\n\n                let inner_nzero: $float_type = -0.0;\n                let nzero = $constructor(inner_nzero);\n\n                Python::attach(|py| {\n                    let pzero_py: Bound<'_, PyFloat> = pzero.into_pyobject(py).unwrap();\n                    let nzero_py: Bound<'_, PyFloat> = nzero.into_pyobject(py).unwrap();\n\n                    // This python script verifies that the values are 0.0 in magnitude\n                    // and that the signs are correct(+0.0 vs -0.0)\n                    py_run(\n                        py,\n                        c\"\\\n                        import math\\n\\\n                        assert pzero_py == 0.0\\n\\\n                        assert math.copysign(1.0, pzero_py) > 0.0\\n\\\n                        assert nzero_py == 0.0\\n\\\n                        assert math.copysign(1.0, nzero_py) < 0.0\",\n                        [(\"pzero_py\", &pzero_py), (\"nzero_py\", &nzero_py)],\n                    );\n\n                    let roundtripped_pzero: $wrapper<$float_type> = pzero_py.extract().unwrap();\n                    let roundtripped_nzero: $wrapper<$float_type> = nzero_py.extract().unwrap();\n\n                    assert_eq!(pzero, roundtripped_pzero);\n                    assert_eq!(roundtripped_pzero.signum(), 1.0);\n                    assert_eq!(nzero, roundtripped_nzero);\n                    assert_eq!(roundtripped_nzero.signum(), -1.0);\n                })\n            }\n        };\n    }\n    float_roundtrip_tests!(\n        OrderedFloat,\n        f32,\n        OrderedFloat,\n        ordered_float_f32_standard,\n        ordered_float_f32_wasm,\n        ordered_float_f32_infinity,\n        ordered_float_f32_zero\n    );\n    float_roundtrip_tests!(\n        OrderedFloat,\n        f64,\n        OrderedFloat,\n        ordered_float_f64_standard,\n        ordered_float_f64_wasm,\n        ordered_float_f64_infinity,\n        ordered_float_f64_zero\n    );\n    float_roundtrip_tests!(\n        NotNan,\n        f32,\n        |val| NotNan::new(val).unwrap(),\n        not_nan_f32_standard,\n        not_nan_f32_wasm,\n        not_nan_f32_infinity,\n        not_nan_f32_zero\n    );\n    float_roundtrip_tests!(\n        NotNan,\n        f64,\n        |val| NotNan::new(val).unwrap(),\n        not_nan_f64_standard,\n        not_nan_f64_wasm,\n        not_nan_f64_infinity,\n        not_nan_f64_zero\n    );\n\n    macro_rules! ordered_float_pynan_tests {\n        ($test_name:ident, $float_type:ty) => {\n            #[test]\n            fn $test_name() {\n                let inner_nan: $float_type = <$float_type>::NAN;\n                let nan = OrderedFloat(inner_nan);\n\n                Python::attach(|py| {\n                    let nan_py: Bound<'_, PyFloat> = nan.into_pyobject(py).unwrap();\n\n                    py_run(\n                        py,\n                        c\"import math\\nassert math.isnan(nan_py)\",\n                        [(\"nan_py\", &nan_py)],\n                    );\n\n                    let roundtripped_nan: OrderedFloat<$float_type> = nan_py.extract().unwrap();\n\n                    assert_eq!(nan, roundtripped_nan);\n                })\n            }\n        };\n    }\n    ordered_float_pynan_tests!(test_ordered_float_pynan_f32, f32);\n    ordered_float_pynan_tests!(test_ordered_float_pynan_f64, f64);\n\n    macro_rules! not_nan_pynan_tests {\n        ($test_name:ident, $float_type:ty) => {\n            #[test]\n            fn $test_name() {\n                Python::attach(|py| {\n                    let nan_py = py.eval(c\"float('nan')\", None, None).unwrap();\n\n                    let nan_rs: Result<NotNan<$float_type>, _> = nan_py.extract();\n\n                    assert!(nan_rs.is_err());\n                })\n            }\n        };\n    }\n    not_nan_pynan_tests!(test_not_nan_pynan_f32, f32);\n    not_nan_pynan_tests!(test_not_nan_pynan_f64, f64);\n\n    macro_rules! py64_rs32 {\n        ($test_name:ident, $wrapper:ident, $float_type:ty) => {\n            #[test]\n            fn $test_name() {\n                Python::attach(|py| {\n                    let py_64 = py\n                        .import(\"sys\")\n                        .unwrap()\n                        .getattr(\"float_info\")\n                        .unwrap()\n                        .getattr(\"max\")\n                        .unwrap();\n                    let rs_32 = py_64.extract::<$wrapper<f32>>().unwrap();\n                    // The python f64 is not representable in a rust f32\n                    assert!(rs_32.is_infinite());\n                })\n            }\n        };\n    }\n    py64_rs32!(ordered_float_f32, OrderedFloat, f32);\n    py64_rs32!(ordered_float_f64, OrderedFloat, f64);\n    py64_rs32!(not_nan_f32, NotNan, f32);\n    py64_rs32!(not_nan_f64, NotNan, f64);\n}\n"
  },
  {
    "path": "src/conversions/rust_decimal.rs",
    "content": "#![cfg(feature = \"rust_decimal\")]\n//! Conversions to and from [rust_decimal](https://docs.rs/rust_decimal)'s [`Decimal`] type.\n//!\n//! This is useful for converting Python's decimal.Decimal into and from a native Rust type.\n//!\n//! # Setup\n//!\n//! To use this feature, add to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"rust_decimal\\\"] }\")]\n//! rust_decimal = \"1.0\"\n//! ```\n//!\n//! Note that you must use a compatible version of rust_decimal and PyO3.\n//! The required rust_decimal version may vary based on the version of PyO3.\n//!\n//! # Example\n//!\n//! Rust code to create a function that adds one to a Decimal\n//!\n//! ```rust,no_run\n//! use rust_decimal::Decimal;\n//! use pyo3::prelude::*;\n//!\n//! #[pyfunction]\n//! fn add_one(d: Decimal) -> Decimal {\n//!     d + Decimal::ONE\n//! }\n//!\n//! #[pymodule]\n//! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n//!     m.add_function(wrap_pyfunction!(add_one, m)?)?;\n//!     Ok(())\n//! }\n//! ```\n//!\n//! Python code that validates the functionality\n//!\n//!\n//! ```python\n//! from my_module import add_one\n//! from decimal import Decimal\n//!\n//! d = Decimal(\"2\")\n//! value = add_one(d)\n//!\n//! assert d + 1 == value\n//! ```\n\nuse crate::conversion::IntoPyObject;\nuse crate::exceptions::PyValueError;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::sync::PyOnceLock;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_hint_identifier;\nuse crate::types::any::PyAnyMethods;\nuse crate::types::string::PyStringMethods;\nuse crate::types::PyType;\nuse crate::{Borrowed, Bound, FromPyObject, Py, PyAny, PyErr, PyResult, Python};\nuse rust_decimal::Decimal;\nuse std::str::FromStr;\n\nimpl FromPyObject<'_, '_> for Decimal {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"decimal\", \"Decimal\");\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        // use the string representation to not be lossy\n        if let Ok(val) = obj.extract() {\n            Ok(Decimal::new(val, 0))\n        } else {\n            let py_str = &obj.str()?;\n            let rs_str = &py_str.to_cow()?;\n            Decimal::from_str(rs_str).or_else(|_| {\n                Decimal::from_scientific(rs_str).map_err(|e| PyValueError::new_err(e.to_string()))\n            })\n        }\n    }\n}\n\nstatic DECIMAL_CLS: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n\nfn get_decimal_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> {\n    DECIMAL_CLS.import(py, \"decimal\", \"Decimal\")\n}\n\nimpl<'py> IntoPyObject<'py> for Decimal {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"decimal\", \"Decimal\");\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let dec_cls = get_decimal_cls(py)?;\n        // now call the constructor with the Rust Decimal string-ified\n        // to not be lossy\n        dec_cls.call1((self.to_string(),))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Decimal {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Decimal::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\n#[cfg(test)]\nmod test_rust_decimal {\n    use super::*;\n    use crate::types::dict::PyDictMethods;\n    use crate::types::PyDict;\n    use std::ffi::CString;\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use proptest::prelude::*;\n\n    macro_rules! convert_constants {\n        ($name:ident, $rs:expr, $py:literal) => {\n            #[test]\n            fn $name() {\n                Python::attach(|py| {\n                    let rs_orig = $rs;\n                    let rs_dec = rs_orig.into_pyobject(py).unwrap();\n                    let locals = PyDict::new(py);\n                    locals.set_item(\"rs_dec\", &rs_dec).unwrap();\n                    // Checks if Rust Decimal -> Python Decimal conversion is correct\n                    py.run(\n                        &CString::new(format!(\n                            \"import decimal\\npy_dec = decimal.Decimal({})\\nassert py_dec == rs_dec\",\n                            $py\n                        ))\n                        .unwrap(),\n                        None,\n                        Some(&locals),\n                    )\n                    .unwrap();\n                    // Checks if Python Decimal -> Rust Decimal conversion is correct\n                    let py_dec = locals.get_item(\"py_dec\").unwrap().unwrap();\n                    let py_result: Decimal = py_dec.extract().unwrap();\n                    assert_eq!(rs_orig, py_result);\n                })\n            }\n        };\n    }\n\n    convert_constants!(convert_zero, Decimal::ZERO, \"0\");\n    convert_constants!(convert_one, Decimal::ONE, \"1\");\n    convert_constants!(convert_neg_one, Decimal::NEGATIVE_ONE, \"-1\");\n    convert_constants!(convert_two, Decimal::TWO, \"2\");\n    convert_constants!(convert_ten, Decimal::TEN, \"10\");\n    convert_constants!(convert_one_hundred, Decimal::ONE_HUNDRED, \"100\");\n    convert_constants!(convert_one_thousand, Decimal::ONE_THOUSAND, \"1000\");\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    proptest! {\n        #[test]\n        fn test_roundtrip(\n            lo in any::<u32>(),\n            mid in any::<u32>(),\n            high in any::<u32>(),\n            negative in any::<bool>(),\n            scale in 0..28u32\n        ) {\n            let num = Decimal::from_parts(lo, mid, high, negative, scale);\n            Python::attach(|py| {\n                let rs_dec = num.into_pyobject(py).unwrap();\n                let locals = PyDict::new(py);\n                locals.set_item(\"rs_dec\", &rs_dec).unwrap();\n                py.run(\n                    &CString::new(format!(\n                       \"import decimal\\npy_dec = decimal.Decimal(\\\"{num}\\\")\\nassert py_dec == rs_dec\")).unwrap(),\n                None, Some(&locals)).unwrap();\n                let roundtripped: Decimal = rs_dec.extract().unwrap();\n                assert_eq!(num, roundtripped);\n            })\n        }\n\n        #[test]\n        fn test_integers(num in any::<i64>()) {\n            Python::attach(|py| {\n                let py_num = num.into_pyobject(py).unwrap();\n                let roundtripped: Decimal = py_num.extract().unwrap();\n                let rs_dec = Decimal::new(num, 0);\n                assert_eq!(rs_dec, roundtripped);\n            })\n        }\n    }\n\n    #[test]\n    fn test_nan() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            py.run(\n                c\"import decimal\\npy_dec = decimal.Decimal(\\\"NaN\\\")\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let py_dec = locals.get_item(\"py_dec\").unwrap().unwrap();\n            let roundtripped: Result<Decimal, PyErr> = py_dec.extract();\n            assert!(roundtripped.is_err());\n        })\n    }\n\n    #[test]\n    fn test_scientific_notation() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            py.run(\n                c\"import decimal\\npy_dec = decimal.Decimal(\\\"1e3\\\")\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let py_dec = locals.get_item(\"py_dec\").unwrap().unwrap();\n            let roundtripped: Decimal = py_dec.extract().unwrap();\n            let rs_dec = Decimal::from_scientific(\"1e3\").unwrap();\n            assert_eq!(rs_dec, roundtripped);\n        })\n    }\n\n    #[test]\n    fn test_infinity() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            py.run(\n                c\"import decimal\\npy_dec = decimal.Decimal(\\\"Infinity\\\")\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let py_dec = locals.get_item(\"py_dec\").unwrap().unwrap();\n            let roundtripped: Result<Decimal, PyErr> = py_dec.extract();\n            assert!(roundtripped.is_err());\n        })\n    }\n}\n"
  },
  {
    "path": "src/conversions/serde.rs",
    "content": "#![cfg(feature = \"serde\")]\n\n//! Enables (de)serialization of [`Py`]`<T>` objects via [serde](https://docs.rs/serde).\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"serde\\\"] }\")]\n//! serde = \"1.0\"\n//! ```\n\nuse crate::{Py, PyAny, PyClass, Python};\nuse serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};\n\nimpl<T> Serialize for Py<T>\nwhere\n    T: Serialize + PyClass,\n{\n    fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>\n    where\n        S: Serializer,\n    {\n        Python::attach(|py| {\n            self.try_borrow(py)\n                .map_err(|e| ser::Error::custom(e.to_string()))?\n                .serialize(serializer)\n        })\n    }\n}\n\nimpl<'de, T> Deserialize<'de> for Py<T>\nwhere\n    T: PyClass<BaseType = PyAny> + Deserialize<'de>,\n{\n    fn deserialize<D>(deserializer: D) -> Result<Py<T>, D::Error>\n    where\n        D: Deserializer<'de>,\n    {\n        let deserialized = T::deserialize(deserializer)?;\n\n        Python::attach(|py| Py::new(py, deserialized).map_err(|e| de::Error::custom(e.to_string())))\n    }\n}\n"
  },
  {
    "path": "src/conversions/smallvec.rs",
    "content": "#![cfg(feature = \"smallvec\")]\n\n//!  Conversions to and from [smallvec](https://docs.rs/smallvec/).\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! # change * to the latest versions\n//! smallvec = \"*\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"smallvec\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of smallvec and PyO3.\n//! The required smallvec version may vary based on the version of PyO3.\nuse crate::conversion::{FromPyObjectOwned, IntoPyObject};\nuse crate::exceptions::PyTypeError;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_hint_subscript;\nuse crate::types::any::PyAnyMethods;\nuse crate::types::{PySequence, PyString};\nuse crate::{\n    err::CastError, ffi, Borrowed, Bound, FromPyObject, PyAny, PyErr, PyResult, PyTypeInfo, Python,\n};\nuse smallvec::{Array, SmallVec};\n\nimpl<'py, A> IntoPyObject<'py> for SmallVec<A>\nwhere\n    A: Array,\n    A::Item: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = A::Item::SEQUENCE_OUTPUT_TYPE;\n\n    /// Turns [`SmallVec<u8>`] into [`PyBytes`], all other `T`s will be turned into a [`PyList`]\n    ///\n    /// [`PyBytes`]: crate::types::PyBytes\n    /// [`PyList`]: crate::types::PyList\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        <A::Item>::owned_sequence_into_pyobject(self, py, crate::conversion::private::Token)\n    }\n}\n\nimpl<'a, 'py, A> IntoPyObject<'py> for &'a SmallVec<A>\nwhere\n    A: Array,\n    &'a A::Item: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&[A::Item]>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.as_slice().into_pyobject(py)\n    }\n}\n\nimpl<'py, A> FromPyObject<'_, 'py> for SmallVec<A>\nwhere\n    A: Array,\n    A::Item: FromPyObjectOwned<'py>,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PySequence::TYPE_HINT, A::Item::INPUT_TYPE);\n\n    fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        if obj.is_instance_of::<PyString>() {\n            return Err(PyTypeError::new_err(\"Can't extract `str` to `SmallVec`\"));\n        }\n        extract_sequence(obj)\n    }\n}\n\nfn extract_sequence<'py, A>(obj: Borrowed<'_, 'py, PyAny>) -> PyResult<SmallVec<A>>\nwhere\n    A: Array,\n    A::Item: FromPyObjectOwned<'py>,\n{\n    // Types that pass `PySequence_Check` usually implement enough of the sequence protocol\n    // to support this function and if not, we will only fail extraction safely.\n    if unsafe { ffi::PySequence_Check(obj.as_ptr()) } == 0 {\n        return Err(CastError::new(obj, PySequence::type_object(obj.py()).into_any()).into());\n    }\n\n    let mut sv = SmallVec::with_capacity(obj.len().unwrap_or(0));\n    for item in obj.try_iter()? {\n        sv.push(item?.extract::<A::Item>().map_err(Into::into)?);\n    }\n    Ok(sv)\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::{PyBytes, PyBytesMethods, PyDict, PyList};\n\n    #[test]\n    fn test_smallvec_from_py_object() {\n        Python::attach(|py| {\n            let l = PyList::new(py, [1, 2, 3, 4, 5]).unwrap();\n            let sv: SmallVec<[u64; 8]> = l.extract().unwrap();\n            assert_eq!(sv.as_slice(), [1, 2, 3, 4, 5]);\n        });\n    }\n\n    #[test]\n    fn test_smallvec_from_py_object_fails() {\n        Python::attach(|py| {\n            let dict = PyDict::new(py);\n            let sv: PyResult<SmallVec<[u64; 8]>> = dict.extract();\n            assert_eq!(\n                sv.unwrap_err().to_string(),\n                \"TypeError: 'dict' object is not an instance of 'Sequence'\"\n            );\n        });\n    }\n\n    #[test]\n    fn test_smallvec_into_pyobject() {\n        Python::attach(|py| {\n            let sv: SmallVec<[u64; 8]> = [1, 2, 3, 4, 5].iter().cloned().collect();\n            let hso = sv.into_pyobject(py).unwrap();\n            let l = PyList::new(py, [1, 2, 3, 4, 5]).unwrap();\n            assert!(l.eq(hso).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_smallvec_intopyobject_impl() {\n        Python::attach(|py| {\n            let bytes: SmallVec<[u8; 8]> = [1, 2, 3, 4, 5].iter().cloned().collect();\n            let obj = bytes.clone().into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyBytes>());\n            let obj = obj.cast_into::<PyBytes>().unwrap();\n            assert_eq!(obj.as_bytes(), &*bytes);\n\n            let nums: SmallVec<[u16; 8]> = [1, 2, 3, 4, 5].iter().cloned().collect();\n            let obj = nums.into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyList>());\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/array.rs",
    "content": "use crate::conversion::{FromPyObjectOwned, FromPyObjectSequence, IntoPyObject};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_subscript, PyStaticExpr};\nuse crate::types::any::PyAnyMethods;\nuse crate::types::PySequence;\nuse crate::{err::CastError, ffi, FromPyObject, PyAny, PyResult, PyTypeInfo, Python};\nuse crate::{exceptions, Borrowed, Bound, PyErr};\n\nimpl<'py, T, const N: usize> IntoPyObject<'py> for [T; N]\nwhere\n    T: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::SEQUENCE_OUTPUT_TYPE;\n\n    /// Turns [`[u8; N]`](std::array) into [`PyBytes`], all other `T`s will be turned into a [`PyList`]\n    ///\n    /// [`PyBytes`]: crate::types::PyBytes\n    /// [`PyList`]: crate::types::PyList\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        T::owned_sequence_into_pyobject(self, py, crate::conversion::private::Token)\n    }\n}\n\nimpl<'a, 'py, T, const N: usize> IntoPyObject<'py> for &'a [T; N]\nwhere\n    &'a T: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&[T]>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.as_slice().into_pyobject(py)\n    }\n}\n\nimpl<'py, T, const N: usize> FromPyObject<'_, 'py> for [T; N]\nwhere\n    T: FromPyObjectOwned<'py>,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_subscript!(PySequence::TYPE_HINT, T::INPUT_TYPE);\n\n    fn extract(obj: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {\n        if let Some(extractor) = T::sequence_extractor(obj, crate::conversion::private::Token) {\n            return extractor.to_array();\n        }\n\n        create_array_from_obj(obj)\n    }\n}\n\nfn create_array_from_obj<'py, T, const N: usize>(obj: Borrowed<'_, 'py, PyAny>) -> PyResult<[T; N]>\nwhere\n    T: FromPyObjectOwned<'py>,\n{\n    // Types that pass `PySequence_Check` usually implement enough of the sequence protocol\n    // to support this function and if not, we will only fail extraction safely.\n    if unsafe { ffi::PySequence_Check(obj.as_ptr()) } == 0 {\n        return Err(CastError::new(obj, PySequence::type_object(obj.py()).into_any()).into());\n    }\n\n    let seq_len = obj.len()?;\n    if seq_len != N {\n        return Err(invalid_sequence_length(N, seq_len));\n    }\n    array_try_from_fn(|idx| {\n        obj.get_item(idx)\n            .and_then(|any| any.extract().map_err(Into::into))\n    })\n}\n\n// TODO use std::array::try_from_fn, if that stabilises:\n// (https://github.com/rust-lang/rust/issues/89379)\nfn array_try_from_fn<E, F, T, const N: usize>(mut cb: F) -> Result<[T; N], E>\nwhere\n    F: FnMut(usize) -> Result<T, E>,\n{\n    // Helper to safely create arrays since the standard library doesn't\n    // provide one yet. Shouldn't be necessary in the future.\n    struct ArrayGuard<T, const N: usize> {\n        dst: *mut T,\n        initialized: usize,\n    }\n\n    impl<T, const N: usize> Drop for ArrayGuard<T, N> {\n        fn drop(&mut self) {\n            debug_assert!(self.initialized <= N);\n            let initialized_part = core::ptr::slice_from_raw_parts_mut(self.dst, self.initialized);\n            unsafe {\n                core::ptr::drop_in_place(initialized_part);\n            }\n        }\n    }\n\n    // [MaybeUninit<T>; N] would be \"nicer\" but is actually difficult to create - there are nightly\n    // APIs which would make this easier.\n    let mut array: core::mem::MaybeUninit<[T; N]> = core::mem::MaybeUninit::uninit();\n    let mut guard: ArrayGuard<T, N> = ArrayGuard {\n        dst: array.as_mut_ptr() as _,\n        initialized: 0,\n    };\n    unsafe {\n        let mut value_ptr = array.as_mut_ptr() as *mut T;\n        for i in 0..N {\n            core::ptr::write(value_ptr, cb(i)?);\n            value_ptr = value_ptr.offset(1);\n            guard.initialized += 1;\n        }\n        core::mem::forget(guard);\n        Ok(array.assume_init())\n    }\n}\n\npub(crate) fn invalid_sequence_length(expected: usize, actual: usize) -> PyErr {\n    exceptions::PyValueError::new_err(format!(\n        \"expected a sequence of length {expected} (got {actual})\"\n    ))\n}\n\n#[cfg(test)]\nmod tests {\n    #[cfg(panic = \"unwind\")]\n    use std::{\n        panic,\n        sync::atomic::{AtomicUsize, Ordering},\n    };\n\n    use crate::{\n        conversion::IntoPyObject,\n        types::{any::PyAnyMethods, PyBytes, PyBytesMethods},\n    };\n    use crate::{types::PyList, PyResult, Python};\n\n    #[test]\n    #[cfg(panic = \"unwind\")]\n    fn array_try_from_fn() {\n        static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0);\n        struct CountDrop;\n        impl Drop for CountDrop {\n            fn drop(&mut self) {\n                DROP_COUNTER.fetch_add(1, Ordering::SeqCst);\n            }\n        }\n        let _ = catch_unwind_silent(move || {\n            let _: Result<[CountDrop; 4], ()> = super::array_try_from_fn(|idx| {\n                #[expect(clippy::manual_assert, reason = \"testing panic during array creation\")]\n                if idx == 2 {\n                    panic!(\"peek a boo\");\n                }\n                Ok(CountDrop)\n            });\n        });\n        assert_eq!(DROP_COUNTER.load(Ordering::SeqCst), 2);\n    }\n\n    #[test]\n    fn test_extract_bytes_to_array() {\n        Python::attach(|py| {\n            let v: [u8; 33] = py\n                .eval(c\"b'abcabcabcabcabcabcabcabcabcabcabc'\", None, None)\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(&v, b\"abcabcabcabcabcabcabcabcabcabcabc\");\n        })\n    }\n\n    #[test]\n    fn test_extract_bytes_wrong_length() {\n        Python::attach(|py| {\n            let v: PyResult<[u8; 3]> = py.eval(c\"b'abcdefg'\", None, None).unwrap().extract();\n            assert_eq!(\n                v.unwrap_err().to_string(),\n                \"ValueError: expected a sequence of length 3 (got 7)\"\n            );\n        })\n    }\n\n    #[test]\n    fn test_extract_bytearray_to_array() {\n        Python::attach(|py| {\n            let v: [u8; 33] = py\n                .eval(\n                    c\"bytearray(b'abcabcabcabcabcabcabcabcabcabcabc')\",\n                    None,\n                    None,\n                )\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(&v, b\"abcabcabcabcabcabcabcabcabcabcabc\");\n        })\n    }\n\n    #[test]\n    fn test_extract_small_bytearray_to_array() {\n        Python::attach(|py| {\n            let v: [u8; 3] = py\n                .eval(c\"bytearray(b'abc')\", None, None)\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(&v, b\"abc\");\n        });\n    }\n    #[test]\n    fn test_into_pyobject_array_conversion() {\n        Python::attach(|py| {\n            let array: [f32; 4] = [0.0, -16.0, 16.0, 42.0];\n            let pyobject = array.into_pyobject(py).unwrap();\n            let pylist = pyobject.cast::<PyList>().unwrap();\n            assert_eq!(pylist.get_item(0).unwrap().extract::<f32>().unwrap(), 0.0);\n            assert_eq!(pylist.get_item(1).unwrap().extract::<f32>().unwrap(), -16.0);\n            assert_eq!(pylist.get_item(2).unwrap().extract::<f32>().unwrap(), 16.0);\n            assert_eq!(pylist.get_item(3).unwrap().extract::<f32>().unwrap(), 42.0);\n        });\n    }\n\n    #[test]\n    fn test_extract_invalid_sequence_length() {\n        Python::attach(|py| {\n            let v: PyResult<[u8; 3]> = py\n                .eval(c\"bytearray(b'abcdefg')\", None, None)\n                .unwrap()\n                .extract();\n            assert_eq!(\n                v.unwrap_err().to_string(),\n                \"ValueError: expected a sequence of length 3 (got 7)\"\n            );\n        })\n    }\n\n    #[test]\n    fn test_intopyobject_array_conversion() {\n        Python::attach(|py| {\n            let array: [f32; 4] = [0.0, -16.0, 16.0, 42.0];\n            let pylist = array\n                .into_pyobject(py)\n                .unwrap()\n                .cast_into::<PyList>()\n                .unwrap();\n\n            assert_eq!(pylist.get_item(0).unwrap().extract::<f32>().unwrap(), 0.0);\n            assert_eq!(pylist.get_item(1).unwrap().extract::<f32>().unwrap(), -16.0);\n            assert_eq!(pylist.get_item(2).unwrap().extract::<f32>().unwrap(), 16.0);\n            assert_eq!(pylist.get_item(3).unwrap().extract::<f32>().unwrap(), 42.0);\n        });\n    }\n\n    #[test]\n    fn test_array_intopyobject_impl() {\n        Python::attach(|py| {\n            let bytes: [u8; 6] = *b\"foobar\";\n            let obj = bytes.into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyBytes>());\n            let obj = obj.cast_into::<PyBytes>().unwrap();\n            assert_eq!(obj.as_bytes(), &bytes);\n\n            let nums: [u16; 4] = [0, 1, 2, 3];\n            let obj = nums.into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyList>());\n        });\n    }\n\n    #[test]\n    fn test_extract_non_iterable_to_array() {\n        Python::attach(|py| {\n            let v = py.eval(c\"42\", None, None).unwrap();\n            v.extract::<i32>().unwrap();\n            v.extract::<[i32; 1]>().unwrap_err();\n        });\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[test]\n    fn test_pyclass_intopy_array_conversion() {\n        #[crate::pyclass(crate = \"crate\")]\n        struct Foo;\n\n        Python::attach(|py| {\n            let array: [Foo; 8] = [Foo, Foo, Foo, Foo, Foo, Foo, Foo, Foo];\n            let list = array\n                .into_pyobject(py)\n                .unwrap()\n                .cast_into::<PyList>()\n                .unwrap();\n            let _bound = list.get_item(4).unwrap().cast::<Foo>().unwrap();\n        });\n    }\n\n    // https://stackoverflow.com/a/59211505\n    #[cfg(panic = \"unwind\")]\n    fn catch_unwind_silent<F, R>(f: F) -> std::thread::Result<R>\n    where\n        F: FnOnce() -> R + panic::UnwindSafe,\n    {\n        let prev_hook = panic::take_hook();\n        panic::set_hook(Box::new(|_| {}));\n        let result = panic::catch_unwind(f);\n        panic::set_hook(prev_hook);\n        result\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/cell.rs",
    "content": "use std::cell::Cell;\n\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::{conversion::IntoPyObject, Borrowed, FromPyObject, PyAny, Python};\n\nimpl<'py, T: Copy + IntoPyObject<'py>> IntoPyObject<'py> for Cell<T> {\n    type Target = T::Target;\n    type Output = T::Output;\n    type Error = T::Error;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.get().into_pyobject(py)\n    }\n}\n\nimpl<'py, T: Copy + IntoPyObject<'py>> IntoPyObject<'py> for &Cell<T> {\n    type Target = T::Target;\n    type Output = T::Output;\n    type Error = T::Error;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.get().into_pyobject(py)\n    }\n}\n\nimpl<'a, 'py, T: FromPyObject<'a, 'py>> FromPyObject<'a, 'py> for Cell<T> {\n    type Error = T::Error;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = T::INPUT_TYPE;\n\n    fn extract(ob: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        ob.extract().map(Cell::new)\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/cstring.rs",
    "content": "use crate::exceptions::PyUnicodeDecodeError;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::types::PyString;\nuse crate::{Borrowed, Bound, FromPyObject, IntoPyObject, PyAny, PyErr, Python};\nuse std::borrow::Cow;\nuse std::ffi::{CStr, CString};\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\nuse {\n    crate::{exceptions::PyValueError, ffi},\n    std::slice,\n};\n\nimpl<'py> IntoPyObject<'py> for &CStr {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&str>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.to_str()\n            .map_err(|e| PyUnicodeDecodeError::new_err_from_utf8(py, self.to_bytes(), e))?\n            .into_pyobject(py)\n            .map_err(|err| match err {})\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for CString {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&CStr>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (&*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &CString {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&CStr>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (&**self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Cow<'_, CStr> {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&CStr>::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Cow<'_, CStr> {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&CStr>::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (&**self).into_pyobject(py)\n    }\n}\n\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\nimpl<'a> FromPyObject<'a, '_> for &'a CStr {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'a, '_, PyAny>) -> Result<Self, Self::Error> {\n        let obj = obj.cast::<PyString>()?;\n        let mut size = 0;\n        // SAFETY: obj is a PyString so we can safely call PyUnicode_AsUTF8AndSize\n        let ptr = unsafe { ffi::PyUnicode_AsUTF8AndSize(obj.as_ptr(), &mut size) };\n\n        if ptr.is_null() {\n            return Err(PyErr::fetch(obj.py()));\n        }\n\n        // SAFETY: PyUnicode_AsUTF8AndSize always returns a NUL-terminated string but size does not\n        // include the NUL terminator. So we add 1 to the size to include it.\n        let slice = unsafe { slice::from_raw_parts(ptr.cast(), size as usize + 1) };\n\n        CStr::from_bytes_with_nul(slice).map_err(|err| PyValueError::new_err(err.to_string()))\n    }\n}\n\nimpl<'a> FromPyObject<'a, '_> for Cow<'a, CStr> {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'a, '_, PyAny>) -> Result<Self, Self::Error> {\n        #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n        {\n            Ok(Cow::Borrowed(obj.extract::<&CStr>()?))\n        }\n\n        #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))]\n        {\n            Ok(Cow::Owned(obj.extract::<CString>()?))\n        }\n    }\n}\nimpl FromPyObject<'_, '_> for CString {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n        {\n            Ok(obj.extract::<&CStr>()?.to_owned())\n        }\n\n        #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))]\n        {\n            CString::new(&*obj.cast::<PyString>()?.to_cow()?).map_err(Into::into)\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::string::PyStringMethods;\n    use crate::types::PyAnyMethods;\n    use crate::Python;\n\n    #[test]\n    fn test_into_pyobject() {\n        Python::attach(|py| {\n            let s = \"Hello, Python!\";\n            let cstr = CString::new(s).unwrap();\n\n            let py_string = cstr.as_c_str().into_pyobject(py).unwrap();\n            assert_eq!(py_string.to_cow().unwrap(), s);\n\n            let py_string = cstr.into_pyobject(py).unwrap();\n            assert_eq!(py_string.to_cow().unwrap(), s);\n        })\n    }\n\n    #[test]\n    fn test_extract_with_nul_error() {\n        Python::attach(|py| {\n            let s = \"Hello\\0Python\";\n            let py_string = s.into_pyobject(py).unwrap();\n\n            #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n            {\n                let err = py_string.extract::<&CStr>();\n                assert!(err.is_err());\n            }\n\n            let err = py_string.extract::<CString>();\n            assert!(err.is_err());\n        })\n    }\n\n    #[test]\n    fn test_extract_cstr_and_cstring() {\n        Python::attach(|py| {\n            let s = \"Hello, world!\";\n            let cstr = CString::new(s).unwrap();\n            let py_string = cstr.as_c_str().into_pyobject(py).unwrap();\n\n            #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n            {\n                let extracted_cstr: &CStr = py_string.extract().unwrap();\n                assert_eq!(extracted_cstr.to_str().unwrap(), s);\n            }\n\n            let extracted_cstring: CString = py_string.extract().unwrap();\n            assert_eq!(extracted_cstring.to_str().unwrap(), s);\n        })\n    }\n\n    #[test]\n    fn test_cow_roundtrip() {\n        Python::attach(|py| {\n            let s = \"Hello, world!\";\n            let cstr = CString::new(s).unwrap();\n            let cow: Cow<'_, CStr> = Cow::Borrowed(cstr.as_c_str());\n\n            let py_string = cow.into_pyobject(py).unwrap();\n            assert_eq!(py_string.to_cow().unwrap(), s);\n\n            let roundtripped: Cow<'_, CStr> = py_string.extract().unwrap();\n            assert_eq!(roundtripped.as_ref(), cstr.as_c_str());\n        })\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/ipaddr.rs",
    "content": "use crate::conversion::IntoPyObject;\nuse crate::exceptions::PyValueError;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_identifier, type_hint_union, PyStaticExpr};\nuse crate::sync::PyOnceLock;\nuse crate::types::any::PyAnyMethods;\nuse crate::types::string::PyStringMethods;\nuse crate::types::PyType;\nuse crate::{intern, Borrowed, Bound, FromPyObject, Py, PyAny, PyErr, Python};\nuse std::net::{IpAddr, Ipv4Addr, Ipv6Addr};\n\nimpl FromPyObject<'_, '_> for IpAddr {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_union!(\n        type_hint_identifier!(\"ipaddress\", \"IPv4Address\"),\n        type_hint_identifier!(\"ipaddress\", \"IPv6Address\")\n    );\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        match obj.getattr(intern!(obj.py(), \"packed\")) {\n            Ok(packed) => {\n                if let Ok(packed) = packed.extract::<[u8; 4]>() {\n                    Ok(IpAddr::V4(Ipv4Addr::from(packed)))\n                } else if let Ok(packed) = packed.extract::<[u8; 16]>() {\n                    Ok(IpAddr::V6(Ipv6Addr::from(packed)))\n                } else {\n                    Err(PyValueError::new_err(\"invalid packed length\"))\n                }\n            }\n            Err(_) => {\n                // We don't have a .packed attribute, so we try to construct an IP from str().\n                obj.str()?.to_cow()?.parse().map_err(PyValueError::new_err)\n            }\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Ipv4Addr {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"ipaddress\", \"IPv4Address\");\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        static IPV4_ADDRESS: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        IPV4_ADDRESS\n            .import(py, \"ipaddress\", \"IPv4Address\")?\n            .call1((u32::from_be_bytes(self.octets()),))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Ipv4Addr {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Ipv4Addr::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Ipv6Addr {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"ipaddress\", \"IPv6Address\");\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        static IPV6_ADDRESS: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        IPV6_ADDRESS\n            .import(py, \"ipaddress\", \"IPv6Address\")?\n            .call1((u128::from_be_bytes(self.octets()),))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Ipv6Addr {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Ipv6Addr::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for IpAddr {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr =\n        type_hint_union!(&Ipv4Addr::OUTPUT_TYPE, &Ipv6Addr::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        match self {\n            IpAddr::V4(ip) => ip.into_pyobject(py),\n            IpAddr::V6(ip) => ip.into_pyobject(py),\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &IpAddr {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = IpAddr::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\n#[cfg(test)]\nmod test_ipaddr {\n    use std::str::FromStr;\n\n    use crate::types::PyString;\n\n    use super::*;\n\n    #[test]\n    fn test_roundtrip() {\n        Python::attach(|py| {\n            fn roundtrip(py: Python<'_>, ip: &str) {\n                let ip = IpAddr::from_str(ip).unwrap();\n                let py_cls = if ip.is_ipv4() {\n                    \"IPv4Address\"\n                } else {\n                    \"IPv6Address\"\n                };\n\n                let pyobj = ip.into_pyobject(py).unwrap();\n                let repr = pyobj.repr().unwrap();\n                let repr = repr.to_string_lossy();\n                assert_eq!(repr, format!(\"{py_cls}('{ip}')\"));\n\n                let ip2: IpAddr = pyobj.extract().unwrap();\n                assert_eq!(ip, ip2);\n            }\n            roundtrip(py, \"127.0.0.1\");\n            roundtrip(py, \"::1\");\n            roundtrip(py, \"0.0.0.0\");\n        });\n    }\n\n    #[test]\n    fn test_from_pystring() {\n        Python::attach(|py| {\n            let py_str = PyString::new(py, \"0:0:0:0:0:0:0:1\");\n            let ip: IpAddr = py_str.extract().unwrap();\n            assert_eq!(ip, IpAddr::from_str(\"::1\").unwrap());\n\n            let py_str = PyString::new(py, \"invalid\");\n            assert!(py_str.extract::<IpAddr>().is_err());\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/map.rs",
    "content": "#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_subscript, PyStaticExpr};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::{\n    conversion::{FromPyObjectOwned, IntoPyObject},\n    instance::Bound,\n    types::{any::PyAnyMethods, dict::PyDictMethods, PyDict},\n    Borrowed, FromPyObject, PyAny, PyErr, Python,\n};\nuse std::{cmp, collections, hash};\n\nimpl<'py, K, V, H> IntoPyObject<'py> for collections::HashMap<K, V, H>\nwhere\n    K: IntoPyObject<'py> + cmp::Eq + hash::Hash,\n    V: IntoPyObject<'py>,\n    H: hash::BuildHasher,\n{\n    type Target = PyDict;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyDict::TYPE_HINT, K::OUTPUT_TYPE, V::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let dict = PyDict::new(py);\n        for (k, v) in self {\n            dict.set_item(k, v)?;\n        }\n        Ok(dict)\n    }\n}\n\nimpl<'a, 'py, K, V, H> IntoPyObject<'py> for &'a collections::HashMap<K, V, H>\nwhere\n    &'a K: IntoPyObject<'py> + cmp::Eq + hash::Hash,\n    &'a V: IntoPyObject<'py>,\n    H: hash::BuildHasher,\n{\n    type Target = PyDict;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyDict::TYPE_HINT, <&K>::OUTPUT_TYPE, <&V>::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let dict = PyDict::new(py);\n        for (k, v) in self {\n            dict.set_item(k, v)?;\n        }\n        Ok(dict)\n    }\n}\n\nimpl<'py, K, V> IntoPyObject<'py> for collections::BTreeMap<K, V>\nwhere\n    K: IntoPyObject<'py> + cmp::Eq,\n    V: IntoPyObject<'py>,\n{\n    type Target = PyDict;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyDict::TYPE_HINT, K::OUTPUT_TYPE, V::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let dict = PyDict::new(py);\n        for (k, v) in self {\n            dict.set_item(k, v)?;\n        }\n        Ok(dict)\n    }\n}\n\nimpl<'a, 'py, K, V> IntoPyObject<'py> for &'a collections::BTreeMap<K, V>\nwhere\n    &'a K: IntoPyObject<'py> + cmp::Eq,\n    &'a V: IntoPyObject<'py>,\n    K: 'a,\n    V: 'a,\n{\n    type Target = PyDict;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyDict::TYPE_HINT, <&K>::OUTPUT_TYPE, <&V>::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let dict = PyDict::new(py);\n        for (k, v) in self {\n            dict.set_item(k, v)?;\n        }\n        Ok(dict)\n    }\n}\n\nimpl<'py, K, V, S> FromPyObject<'_, 'py> for collections::HashMap<K, V, S>\nwhere\n    K: FromPyObjectOwned<'py> + cmp::Eq + hash::Hash,\n    V: FromPyObjectOwned<'py>,\n    S: hash::BuildHasher + Default,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(&PyDict::TYPE_HINT, K::INPUT_TYPE, V::INPUT_TYPE);\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        let dict = ob.cast::<PyDict>()?;\n        let mut ret = collections::HashMap::with_capacity_and_hasher(dict.len(), S::default());\n        for (k, v) in dict.iter() {\n            ret.insert(\n                k.extract().map_err(Into::into)?,\n                v.extract().map_err(Into::into)?,\n            );\n        }\n        Ok(ret)\n    }\n}\n\nimpl<'py, K, V> FromPyObject<'_, 'py> for collections::BTreeMap<K, V>\nwhere\n    K: FromPyObjectOwned<'py> + cmp::Ord,\n    V: FromPyObjectOwned<'py>,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr =\n        type_hint_subscript!(PyDict::TYPE_HINT, K::INPUT_TYPE, V::INPUT_TYPE);\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> Result<Self, PyErr> {\n        let dict = ob.cast::<PyDict>()?;\n        let mut ret = collections::BTreeMap::new();\n        for (k, v) in dict.iter() {\n            ret.insert(\n                k.extract().map_err(Into::into)?,\n                v.extract().map_err(Into::into)?,\n            );\n        }\n        Ok(ret)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use std::collections::{BTreeMap, HashMap};\n\n    #[test]\n    fn test_hashmap_to_python() {\n        Python::attach(|py| {\n            let mut map = HashMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let py_map = (&map).into_pyobject(py).unwrap();\n\n            assert_eq!(py_map.len(), 1);\n            assert!(\n                py_map\n                    .get_item(1)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n                    == 1\n            );\n            assert_eq!(map, py_map.extract().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_btreemap_to_python() {\n        Python::attach(|py| {\n            let mut map = BTreeMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let py_map = (&map).into_pyobject(py).unwrap();\n\n            assert_eq!(py_map.len(), 1);\n            assert!(\n                py_map\n                    .get_item(1)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n                    == 1\n            );\n            assert_eq!(map, py_map.extract().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_hashmap_into_python() {\n        Python::attach(|py| {\n            let mut map = HashMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let py_map = map.into_pyobject(py).unwrap();\n\n            assert_eq!(py_map.len(), 1);\n            assert!(\n                py_map\n                    .get_item(1)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n                    == 1\n            );\n        });\n    }\n\n    #[test]\n    fn test_btreemap_into_py() {\n        Python::attach(|py| {\n            let mut map = BTreeMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let py_map = map.into_pyobject(py).unwrap();\n\n            assert_eq!(py_map.len(), 1);\n            assert!(\n                py_map\n                    .get_item(1)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n                    == 1\n            );\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/mod.rs",
    "content": "mod array;\nmod cell;\nmod cstring;\nmod ipaddr;\nmod map;\npub(crate) mod num;\nmod option;\nmod osstr;\nmod path;\nmod set;\nmod slice;\nmod string;\nmod time;\nmod vec;\n"
  },
  {
    "path": "src/conversions/std/num.rs",
    "content": "use crate::conversion::private::Reference;\nuse crate::conversion::{FromPyObjectSequence, IntoPyObject};\nuse crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::py_result_ext::PyResultExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::types::{PyByteArray, PyByteArrayMethods, PyBytes, PyInt};\nuse crate::{exceptions, ffi, Borrowed, Bound, FromPyObject, PyAny, PyErr, PyResult, Python};\nuse std::convert::Infallible;\nuse std::ffi::c_long;\nuse std::mem::MaybeUninit;\nuse std::num::{\n    NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128,\n    NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,\n};\n\nuse super::array::invalid_sequence_length;\n\nmacro_rules! int_fits_larger_int {\n    ($rust_type:ty, $larger_type:ty) => {\n        impl<'py> IntoPyObject<'py> for $rust_type {\n            type Target = PyInt;\n            type Output = Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = <$larger_type>::OUTPUT_TYPE;\n\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                (self as $larger_type).into_pyobject(py)\n            }\n        }\n\n        impl<'py> IntoPyObject<'py> for &$rust_type {\n            type Target = PyInt;\n            type Output = Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = <$larger_type>::OUTPUT_TYPE;\n\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                (*self).into_pyobject(py)\n            }\n        }\n\n        impl FromPyObject<'_, '_> for $rust_type {\n            type Error = PyErr;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const INPUT_TYPE: PyStaticExpr = <$larger_type>::INPUT_TYPE;\n\n            fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n                let val: $larger_type = obj.extract()?;\n                <$rust_type>::try_from(val)\n                    .map_err(|e| exceptions::PyOverflowError::new_err(e.to_string()))\n            }\n        }\n    };\n}\n\nmacro_rules! extract_int {\n    ($obj:ident, $error_val:expr, $pylong_as:expr) => {\n        extract_int!($obj, $error_val, $pylong_as, false)\n    };\n\n    ($obj:ident, $error_val:expr, $pylong_as:expr, $force_index_call: literal) => {\n        // In python 3.8+ `PyLong_AsLong` and friends takes care of calling `PyNumber_Index`,\n        // however 3.8 & 3.9 do lossy conversion of floats, hence we only use the\n        // simplest logic for 3.10+ where that was fixed - python/cpython#82180.\n        // `PyLong_AsUnsignedLongLong` does not call `PyNumber_Index`, hence the `force_index_call` argument\n        // See https://github.com/PyO3/pyo3/pull/3742 for details\n        if cfg!(Py_3_10) && !$force_index_call {\n            err_if_invalid_value($obj.py(), $error_val, unsafe { $pylong_as($obj.as_ptr()) })\n        } else if let Ok(long) = $obj.cast::<crate::types::PyInt>() {\n            // fast path - checking for subclass of `int` just checks a bit in the type $object\n            err_if_invalid_value($obj.py(), $error_val, unsafe { $pylong_as(long.as_ptr()) })\n        } else {\n            unsafe {\n                let num = nb_index(&$obj)?;\n                err_if_invalid_value($obj.py(), $error_val, $pylong_as(num.as_ptr()))\n            }\n        }\n    };\n}\n\nmacro_rules! int_convert_u64_or_i64 {\n    ($rust_type:ty, $pylong_from_ll_or_ull:expr, $pylong_as_ll_or_ull:expr, $force_index_call:literal) => {\n        impl<'py> IntoPyObject<'py> for $rust_type {\n            type Target = PyInt;\n            type Output = Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                unsafe {\n                    Ok($pylong_from_ll_or_ull(self)\n                        .assume_owned(py)\n                        .cast_into_unchecked())\n                }\n            }\n        }\n        impl<'py> IntoPyObject<'py> for &$rust_type {\n            type Target = PyInt;\n            type Output = Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = <$rust_type>::OUTPUT_TYPE;\n\n            #[inline]\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                (*self).into_pyobject(py)\n            }\n        }\n        impl FromPyObject<'_, '_> for $rust_type {\n            type Error = PyErr;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const INPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n            fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<$rust_type, Self::Error> {\n                extract_int!(obj, !0, $pylong_as_ll_or_ull, $force_index_call)\n            }\n        }\n    };\n}\n\nmacro_rules! int_fits_c_long {\n    ($rust_type:ty) => {\n        impl<'py> IntoPyObject<'py> for $rust_type {\n            type Target = PyInt;\n            type Output = Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                unsafe {\n                    Ok(ffi::PyLong_FromLong(self as c_long)\n                        .assume_owned(py)\n                        .cast_into_unchecked())\n                }\n            }\n        }\n\n        impl<'py> IntoPyObject<'py> for &$rust_type {\n            type Target = PyInt;\n            type Output = Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = <$rust_type>::OUTPUT_TYPE;\n\n            #[inline]\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                (*self).into_pyobject(py)\n            }\n        }\n\n        impl<'py> FromPyObject<'_, 'py> for $rust_type {\n            type Error = PyErr;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const INPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n            fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n                let val: c_long = extract_int!(obj, -1, ffi::PyLong_AsLong)?;\n                <$rust_type>::try_from(val)\n                    .map_err(|e| exceptions::PyOverflowError::new_err(e.to_string()))\n            }\n        }\n    };\n}\n\nimpl<'py> IntoPyObject<'py> for u8 {\n    type Target = PyInt;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        unsafe {\n            Ok(ffi::PyLong_FromLong(self as c_long)\n                .assume_owned(py)\n                .cast_into_unchecked())\n        }\n    }\n\n    #[inline]\n    fn owned_sequence_into_pyobject<I>(\n        iter: I,\n        py: Python<'py>,\n        _: crate::conversion::private::Token,\n    ) -> Result<Bound<'py, PyAny>, PyErr>\n    where\n        I: AsRef<[u8]>,\n    {\n        Ok(PyBytes::new(py, iter.as_ref()).into_any())\n    }\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const SEQUENCE_OUTPUT_TYPE: PyStaticExpr = PyBytes::TYPE_HINT;\n}\n\nimpl<'py> IntoPyObject<'py> for &'_ u8 {\n    type Target = PyInt;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = u8::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        u8::into_pyobject(*self, py)\n    }\n\n    #[inline]\n    fn borrowed_sequence_into_pyobject<I>(\n        iter: I,\n        py: Python<'py>,\n        _: crate::conversion::private::Token,\n    ) -> Result<Bound<'py, PyAny>, PyErr>\n    where\n        // I: AsRef<[u8]>, but the compiler needs it expressed via the trait for some reason\n        I: AsRef<[<Self as Reference>::BaseType]>,\n    {\n        Ok(PyBytes::new(py, iter.as_ref()).into_any())\n    }\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const SEQUENCE_OUTPUT_TYPE: PyStaticExpr = PyBytes::TYPE_HINT;\n}\n\nimpl<'py> FromPyObject<'_, 'py> for u8 {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        let val: c_long = extract_int!(obj, -1, ffi::PyLong_AsLong)?;\n        u8::try_from(val).map_err(|e| exceptions::PyOverflowError::new_err(e.to_string()))\n    }\n\n    #[inline]\n    fn sequence_extractor(\n        obj: Borrowed<'_, 'py, PyAny>,\n        _: crate::conversion::private::Token,\n    ) -> Option<impl FromPyObjectSequence<Target = u8>> {\n        if let Ok(bytes) = obj.cast::<PyBytes>() {\n            Some(BytesSequenceExtractor::Bytes(bytes))\n        } else if let Ok(byte_array) = obj.cast::<PyByteArray>() {\n            Some(BytesSequenceExtractor::ByteArray(byte_array))\n        } else {\n            None\n        }\n    }\n}\n\npub(crate) enum BytesSequenceExtractor<'a, 'py> {\n    Bytes(Borrowed<'a, 'py, PyBytes>),\n    ByteArray(Borrowed<'a, 'py, PyByteArray>),\n}\n\nimpl BytesSequenceExtractor<'_, '_> {\n    fn fill_slice(&self, out: &mut [MaybeUninit<u8>]) -> PyResult<()> {\n        let mut copy_slice = |slice: &[u8]| {\n            if slice.len() != out.len() {\n                return Err(invalid_sequence_length(out.len(), slice.len()));\n            }\n            // Safety: `slice` and `out` are guaranteed not to overlap due to `&mut` reference on `out`.\n            unsafe {\n                std::ptr::copy_nonoverlapping(slice.as_ptr(), out.as_mut_ptr().cast(), out.len())\n            };\n            Ok(())\n        };\n\n        match self {\n            BytesSequenceExtractor::Bytes(b) => copy_slice(b.as_bytes()),\n            BytesSequenceExtractor::ByteArray(b) => {\n                crate::sync::critical_section::with_critical_section(b, || {\n                    // Safety: b is protected by a critical section\n                    copy_slice(unsafe { b.as_bytes() })\n                })\n            }\n        }\n    }\n}\n\nimpl FromPyObjectSequence for BytesSequenceExtractor<'_, '_> {\n    type Target = u8;\n\n    fn to_vec(&self) -> Vec<Self::Target> {\n        match self {\n            BytesSequenceExtractor::Bytes(b) => b.as_bytes().to_vec(),\n            BytesSequenceExtractor::ByteArray(b) => b.to_vec(),\n        }\n    }\n\n    fn to_array<const N: usize>(&self) -> PyResult<[u8; N]> {\n        let mut out: MaybeUninit<[u8; N]> = MaybeUninit::uninit();\n\n        // Safety: `[u8; N]` has the same layout as `[MaybeUninit<u8>; N]`\n        let slice = unsafe {\n            std::slice::from_raw_parts_mut(out.as_mut_ptr().cast::<MaybeUninit<u8>>(), N)\n        };\n\n        self.fill_slice(slice)?;\n\n        // Safety: `out` is fully initialized\n        Ok(unsafe { out.assume_init() })\n    }\n}\n\nint_fits_c_long!(i8);\nint_fits_c_long!(i16);\nint_fits_c_long!(u16);\nint_fits_c_long!(i32);\n\n// If c_long is 64-bits, we can use more types with int_fits_c_long!:\n#[cfg(all(target_pointer_width = \"64\", not(target_os = \"windows\")))]\nint_fits_c_long!(u32);\n#[cfg(any(target_pointer_width = \"32\", target_os = \"windows\"))]\nint_fits_larger_int!(u32, u64);\n\n#[cfg(all(target_pointer_width = \"64\", not(target_os = \"windows\")))]\nint_fits_c_long!(i64);\n\n// manual implementation for i64 on systems with 32-bit long\n#[cfg(any(target_pointer_width = \"32\", target_os = \"windows\"))]\nint_convert_u64_or_i64!(i64, ffi::PyLong_FromLongLong, ffi::PyLong_AsLongLong, false);\n\n#[cfg(all(target_pointer_width = \"64\", not(target_os = \"windows\")))]\nint_fits_c_long!(isize);\n#[cfg(any(target_pointer_width = \"32\", target_os = \"windows\"))]\nint_fits_larger_int!(isize, i64);\n\nint_fits_larger_int!(usize, u64);\n\n// u64 has a manual implementation as it never fits into signed long\nint_convert_u64_or_i64!(\n    u64,\n    ffi::PyLong_FromUnsignedLongLong,\n    ffi::PyLong_AsUnsignedLongLong,\n    true\n);\n\n#[cfg(not(Py_LIMITED_API))]\nmod fast_128bit_int_conversion {\n    use super::*;\n\n    // for 128bit Integers\n    macro_rules! int_convert_128 {\n        ($rust_type: ty, $is_signed: literal) => {\n            impl<'py> IntoPyObject<'py> for $rust_type {\n                type Target = PyInt;\n                type Output = Bound<'py, Self::Target>;\n                type Error = Infallible;\n\n                #[cfg(feature = \"experimental-inspect\")]\n                const OUTPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n                fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                    #[cfg(Py_3_13)]\n                    {\n                        let bytes = self.to_ne_bytes();\n                        Ok(int_from_ne_bytes::<{ $is_signed }>(py, &bytes))\n                    }\n                    #[cfg(not(Py_3_13))]\n                    {\n                        let bytes = self.to_le_bytes();\n                        Ok(int_from_le_bytes::<{ $is_signed }>(py, &bytes))\n                    }\n                }\n            }\n\n            impl<'py> IntoPyObject<'py> for &$rust_type {\n                type Target = PyInt;\n                type Output = Bound<'py, Self::Target>;\n                type Error = Infallible;\n\n                #[cfg(feature = \"experimental-inspect\")]\n                const OUTPUT_TYPE: PyStaticExpr = <$rust_type>::OUTPUT_TYPE;\n\n                #[inline]\n                fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                    (*self).into_pyobject(py)\n                }\n            }\n\n            impl FromPyObject<'_, '_> for $rust_type {\n                type Error = PyErr;\n\n                #[cfg(feature = \"experimental-inspect\")]\n                const INPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n                fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<$rust_type, Self::Error> {\n                    let num = nb_index(&ob)?;\n                    let mut buffer = [0u8; std::mem::size_of::<$rust_type>()];\n                    #[cfg(not(Py_3_13))]\n                    {\n                        crate::err::error_on_minusone(ob.py(), unsafe {\n                            ffi::_PyLong_AsByteArray(\n                                num.as_ptr() as *mut ffi::PyLongObject,\n                                buffer.as_mut_ptr(),\n                                buffer.len(),\n                                1,\n                                $is_signed.into(),\n                            )\n                        })?;\n                        Ok(<$rust_type>::from_le_bytes(buffer))\n                    }\n                    #[cfg(Py_3_13)]\n                    {\n                        let mut flags = ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN;\n                        if !$is_signed {\n                            flags |= ffi::Py_ASNATIVEBYTES_UNSIGNED_BUFFER\n                                | ffi::Py_ASNATIVEBYTES_REJECT_NEGATIVE;\n                        }\n                        let actual_size: usize = unsafe {\n                            ffi::PyLong_AsNativeBytes(\n                                num.as_ptr(),\n                                buffer.as_mut_ptr().cast(),\n                                buffer\n                                    .len()\n                                    .try_into()\n                                    .expect(\"length of buffer fits in Py_ssize_t\"),\n                                flags,\n                            )\n                        }\n                        .try_into()\n                        .map_err(|_| PyErr::fetch(ob.py()))?;\n                        if actual_size as usize > buffer.len() {\n                            return Err(crate::exceptions::PyOverflowError::new_err(\n                                \"Python int larger than 128 bits\",\n                            ));\n                        }\n                        Ok(<$rust_type>::from_ne_bytes(buffer))\n                    }\n                }\n            }\n        };\n    }\n\n    int_convert_128!(i128, true);\n    int_convert_128!(u128, false);\n}\n\n#[cfg(all(not(Py_LIMITED_API), not(Py_3_13)))]\npub(crate) fn int_from_le_bytes<'py, const IS_SIGNED: bool>(\n    py: Python<'py>,\n    bytes: &[u8],\n) -> Bound<'py, PyInt> {\n    unsafe {\n        ffi::_PyLong_FromByteArray(bytes.as_ptr().cast(), bytes.len(), 1, IS_SIGNED.into())\n            .assume_owned(py)\n            .cast_into_unchecked()\n    }\n}\n\n#[cfg(all(Py_3_13, not(Py_LIMITED_API)))]\npub(crate) fn int_from_ne_bytes<'py, const IS_SIGNED: bool>(\n    py: Python<'py>,\n    bytes: &[u8],\n) -> Bound<'py, PyInt> {\n    let flags = if IS_SIGNED {\n        ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN\n    } else {\n        ffi::Py_ASNATIVEBYTES_NATIVE_ENDIAN | ffi::Py_ASNATIVEBYTES_UNSIGNED_BUFFER\n    };\n    unsafe {\n        ffi::PyLong_FromNativeBytes(bytes.as_ptr().cast(), bytes.len(), flags)\n            .assume_owned(py)\n            .cast_into_unchecked()\n    }\n}\n\npub(crate) fn nb_index<'py>(obj: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyInt>> {\n    // SAFETY: PyNumber_Index returns a new reference or NULL on error\n    unsafe { ffi::PyNumber_Index(obj.as_ptr()).assume_owned_or_err(obj.py()) }.cast_into()\n}\n\n// For ABI3 we implement the conversion manually.\n#[cfg(Py_LIMITED_API)]\nmod slow_128bit_int_conversion {\n    use super::*;\n    use crate::types::any::PyAnyMethods as _;\n    const SHIFT: usize = 64;\n\n    // for 128bit Integers\n    macro_rules! int_convert_128 {\n        ($rust_type: ty, $half_type: ty) => {\n            impl<'py> IntoPyObject<'py> for $rust_type {\n                type Target = PyInt;\n                type Output = Bound<'py, Self::Target>;\n                type Error = Infallible;\n\n                #[cfg(feature = \"experimental-inspect\")]\n                const OUTPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n                fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                    let lower = (self as u64).into_pyobject(py)?;\n                    let upper = ((self >> SHIFT) as $half_type).into_pyobject(py)?;\n                    let shift = SHIFT.into_pyobject(py)?;\n                    unsafe {\n                        let shifted =\n                            ffi::PyNumber_Lshift(upper.as_ptr(), shift.as_ptr()).assume_owned(py);\n\n                        Ok(ffi::PyNumber_Or(shifted.as_ptr(), lower.as_ptr())\n                            .assume_owned(py)\n                            .cast_into_unchecked())\n                    }\n                }\n            }\n\n            impl<'py> IntoPyObject<'py> for &$rust_type {\n                type Target = PyInt;\n                type Output = Bound<'py, Self::Target>;\n                type Error = Infallible;\n\n                #[cfg(feature = \"experimental-inspect\")]\n                const OUTPUT_TYPE: PyStaticExpr = <$rust_type>::OUTPUT_TYPE;\n\n                #[inline]\n                fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                    (*self).into_pyobject(py)\n                }\n            }\n\n            impl FromPyObject<'_, '_> for $rust_type {\n                type Error = PyErr;\n\n                #[cfg(feature = \"experimental-inspect\")]\n                const INPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n                fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<$rust_type, Self::Error> {\n                    let py = ob.py();\n                    unsafe {\n                        let lower = err_if_invalid_value(\n                            py,\n                            -1 as _,\n                            ffi::PyLong_AsUnsignedLongLongMask(ob.as_ptr()),\n                        )? as $rust_type;\n                        let shift = SHIFT.into_pyobject(py)?;\n                        let shifted = Bound::from_owned_ptr_or_err(\n                            py,\n                            ffi::PyNumber_Rshift(ob.as_ptr(), shift.as_ptr()),\n                        )?;\n                        let upper: $half_type = shifted.extract()?;\n                        Ok((<$rust_type>::from(upper) << SHIFT) | lower)\n                    }\n                }\n            }\n        };\n    }\n\n    int_convert_128!(i128, i64);\n    int_convert_128!(u128, u64);\n}\n\nfn err_if_invalid_value<T: PartialEq>(\n    py: Python<'_>,\n    invalid_value: T,\n    actual_value: T,\n) -> PyResult<T> {\n    if actual_value == invalid_value {\n        if let Some(err) = PyErr::take(py) {\n            return Err(err);\n        }\n    }\n\n    Ok(actual_value)\n}\n\nmacro_rules! nonzero_int_impl {\n    ($nonzero_type:ty, $primitive_type:ty) => {\n        impl<'py> IntoPyObject<'py> for $nonzero_type {\n            type Target = PyInt;\n            type Output = Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = PyInt::TYPE_HINT;\n\n            #[inline]\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                self.get().into_pyobject(py)\n            }\n        }\n\n        impl<'py> IntoPyObject<'py> for &$nonzero_type {\n            type Target = PyInt;\n            type Output = Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = <$nonzero_type>::OUTPUT_TYPE;\n\n            #[inline]\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                (*self).into_pyobject(py)\n            }\n        }\n\n        impl FromPyObject<'_, '_> for $nonzero_type {\n            type Error = PyErr;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const INPUT_TYPE: PyStaticExpr = <$primitive_type>::INPUT_TYPE;\n\n            fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n                let val: $primitive_type = obj.extract()?;\n                <$nonzero_type>::try_from(val)\n                    .map_err(|_| exceptions::PyValueError::new_err(\"invalid zero value\"))\n            }\n        }\n    };\n}\n\nnonzero_int_impl!(NonZeroI8, i8);\nnonzero_int_impl!(NonZeroI16, i16);\nnonzero_int_impl!(NonZeroI32, i32);\nnonzero_int_impl!(NonZeroI64, i64);\nnonzero_int_impl!(NonZeroI128, i128);\nnonzero_int_impl!(NonZeroIsize, isize);\nnonzero_int_impl!(NonZeroU8, u8);\nnonzero_int_impl!(NonZeroU16, u16);\nnonzero_int_impl!(NonZeroU32, u32);\nnonzero_int_impl!(NonZeroU64, u64);\nnonzero_int_impl!(NonZeroU128, u128);\nnonzero_int_impl!(NonZeroUsize, usize);\n\n#[cfg(test)]\nmod test_128bit_integers {\n    use super::*;\n    use crate::types::PyAnyMethods;\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use crate::types::PyDict;\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use crate::types::dict::PyDictMethods;\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use proptest::prelude::*;\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use std::ffi::CString;\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    proptest! {\n        #[test]\n        fn test_i128_roundtrip(x: i128) {\n            Python::attach(|py| {\n                let x_py = x.into_pyobject(py).unwrap();\n                let locals = PyDict::new(py);\n                locals.set_item(\"x_py\", &x_py).unwrap();\n                py.run(&CString::new(format!(\"assert x_py == {x}\")).unwrap(), None, Some(&locals)).unwrap();\n                let roundtripped: i128 = x_py.extract().unwrap();\n                assert_eq!(x, roundtripped);\n            })\n        }\n\n        #[test]\n        fn test_nonzero_i128_roundtrip(\n            x in any::<i128>()\n                .prop_filter(\"Values must not be 0\", |x| x != &0)\n                .prop_map(|x| NonZeroI128::new(x).unwrap())\n        ) {\n            Python::attach(|py| {\n                let x_py = x.into_pyobject(py).unwrap();\n                let locals = PyDict::new(py);\n                locals.set_item(\"x_py\", &x_py).unwrap();\n                py.run(&CString::new(format!(\"assert x_py == {x}\")).unwrap(), None, Some(&locals)).unwrap();\n                let roundtripped: NonZeroI128 = x_py.extract().unwrap();\n                assert_eq!(x, roundtripped);\n            })\n        }\n    }\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    proptest! {\n        #[test]\n        fn test_u128_roundtrip(x: u128) {\n            Python::attach(|py| {\n                let x_py = x.into_pyobject(py).unwrap();\n                let locals = PyDict::new(py);\n                locals.set_item(\"x_py\", &x_py).unwrap();\n                py.run(&CString::new(format!(\"assert x_py == {x}\")).unwrap(), None, Some(&locals)).unwrap();\n                let roundtripped: u128 = x_py.extract().unwrap();\n                assert_eq!(x, roundtripped);\n            })\n        }\n\n        #[test]\n        fn test_nonzero_u128_roundtrip(\n            x in any::<u128>()\n                .prop_filter(\"Values must not be 0\", |x| x != &0)\n                .prop_map(|x| NonZeroU128::new(x).unwrap())\n        ) {\n            Python::attach(|py| {\n                let x_py = x.into_pyobject(py).unwrap();\n                let locals = PyDict::new(py);\n                locals.set_item(\"x_py\", &x_py).unwrap();\n                py.run(&CString::new(format!(\"assert x_py == {x}\")).unwrap(), None, Some(&locals)).unwrap();\n                let roundtripped: NonZeroU128 = x_py.extract().unwrap();\n                assert_eq!(x, roundtripped);\n            })\n        }\n    }\n\n    #[test]\n    fn test_i128_max() {\n        Python::attach(|py| {\n            let v = i128::MAX;\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<i128>().unwrap());\n            assert_eq!(v as u128, obj.extract::<u128>().unwrap());\n            assert!(obj.extract::<u64>().is_err());\n        })\n    }\n\n    #[test]\n    fn test_i128_min() {\n        Python::attach(|py| {\n            let v = i128::MIN;\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<i128>().unwrap());\n            assert!(obj.extract::<i64>().is_err());\n            assert!(obj.extract::<u128>().is_err());\n        })\n    }\n\n    #[test]\n    fn test_u128_max() {\n        Python::attach(|py| {\n            let v = u128::MAX;\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<u128>().unwrap());\n            assert!(obj.extract::<i128>().is_err());\n        })\n    }\n\n    #[test]\n    fn test_i128_overflow() {\n        Python::attach(|py| {\n            let obj = py.eval(c\"(1 << 130) * -1\", None, None).unwrap();\n            let err = obj.extract::<i128>().unwrap_err();\n            assert!(err.is_instance_of::<crate::exceptions::PyOverflowError>(py));\n        })\n    }\n\n    #[test]\n    fn test_u128_overflow() {\n        Python::attach(|py| {\n            let obj = py.eval(c\"1 << 130\", None, None).unwrap();\n            let err = obj.extract::<u128>().unwrap_err();\n            assert!(err.is_instance_of::<crate::exceptions::PyOverflowError>(py));\n        })\n    }\n\n    #[test]\n    fn test_nonzero_i128_max() {\n        Python::attach(|py| {\n            let v = NonZeroI128::new(i128::MAX).unwrap();\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<NonZeroI128>().unwrap());\n            assert_eq!(\n                NonZeroU128::new(v.get() as u128).unwrap(),\n                obj.extract::<NonZeroU128>().unwrap()\n            );\n            assert!(obj.extract::<NonZeroU64>().is_err());\n        })\n    }\n\n    #[test]\n    fn test_nonzero_i128_min() {\n        Python::attach(|py| {\n            let v = NonZeroI128::new(i128::MIN).unwrap();\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<NonZeroI128>().unwrap());\n            assert!(obj.extract::<NonZeroI64>().is_err());\n            assert!(obj.extract::<NonZeroU128>().is_err());\n        })\n    }\n\n    #[test]\n    fn test_nonzero_u128_max() {\n        Python::attach(|py| {\n            let v = NonZeroU128::new(u128::MAX).unwrap();\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<NonZeroU128>().unwrap());\n            assert!(obj.extract::<NonZeroI128>().is_err());\n        })\n    }\n\n    #[test]\n    fn test_nonzero_i128_overflow() {\n        Python::attach(|py| {\n            let obj = py.eval(c\"(1 << 130) * -1\", None, None).unwrap();\n            let err = obj.extract::<NonZeroI128>().unwrap_err();\n            assert!(err.is_instance_of::<crate::exceptions::PyOverflowError>(py));\n        })\n    }\n\n    #[test]\n    fn test_nonzero_u128_overflow() {\n        Python::attach(|py| {\n            let obj = py.eval(c\"1 << 130\", None, None).unwrap();\n            let err = obj.extract::<NonZeroU128>().unwrap_err();\n            assert!(err.is_instance_of::<crate::exceptions::PyOverflowError>(py));\n        })\n    }\n\n    #[test]\n    fn test_nonzero_i128_zero_value() {\n        Python::attach(|py| {\n            let obj = py.eval(c\"0\", None, None).unwrap();\n            let err = obj.extract::<NonZeroI128>().unwrap_err();\n            assert!(err.is_instance_of::<crate::exceptions::PyValueError>(py));\n        })\n    }\n\n    #[test]\n    fn test_nonzero_u128_zero_value() {\n        Python::attach(|py| {\n            let obj = py.eval(c\"0\", None, None).unwrap();\n            let err = obj.extract::<NonZeroU128>().unwrap_err();\n            assert!(err.is_instance_of::<crate::exceptions::PyValueError>(py));\n        })\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::PyAnyMethods;\n    use crate::{IntoPyObject, Python};\n    use std::num::*;\n\n    #[test]\n    fn test_u32_max() {\n        Python::attach(|py| {\n            let v = u32::MAX;\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<u32>().unwrap());\n            assert_eq!(u64::from(v), obj.extract::<u64>().unwrap());\n            assert!(obj.extract::<i32>().is_err());\n        });\n    }\n\n    #[test]\n    fn test_i64_max() {\n        Python::attach(|py| {\n            let v = i64::MAX;\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<i64>().unwrap());\n            assert_eq!(v as u64, obj.extract::<u64>().unwrap());\n            assert!(obj.extract::<u32>().is_err());\n        });\n    }\n\n    #[test]\n    fn test_i64_min() {\n        Python::attach(|py| {\n            let v = i64::MIN;\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<i64>().unwrap());\n            assert!(obj.extract::<i32>().is_err());\n            assert!(obj.extract::<u64>().is_err());\n        });\n    }\n\n    #[test]\n    fn test_u64_max() {\n        Python::attach(|py| {\n            let v = u64::MAX;\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<u64>().unwrap());\n            assert!(obj.extract::<i64>().is_err());\n        });\n    }\n\n    macro_rules! test_common (\n        ($test_mod_name:ident, $t:ty) => (\n            mod $test_mod_name {\n                use crate::exceptions;\n                use crate::conversion::IntoPyObject;\n                use crate::types::PyAnyMethods;\n                use crate::Python;\n\n                #[test]\n                fn from_py_string_type_error() {\n                    Python::attach(|py| {\n                    let obj = (\"123\").into_pyobject(py).unwrap();\n                    let err = obj.extract::<$t>().unwrap_err();\n                    assert!(err.is_instance_of::<exceptions::PyTypeError>(py));\n                    });\n                }\n\n                #[test]\n                fn from_py_float_type_error() {\n                    Python::attach(|py| {\n                    let obj = (12.3f64).into_pyobject(py).unwrap();\n                    let err = obj.extract::<$t>().unwrap_err();\n                    assert!(err.is_instance_of::<exceptions::PyTypeError>(py));});\n                }\n\n                #[test]\n                fn to_py_object_and_back() {\n                    Python::attach(|py| {\n                    let val = 123 as $t;\n                    let obj = val.into_pyobject(py).unwrap();\n                    assert_eq!(obj.extract::<$t>().unwrap(), val as $t);});\n                }\n            }\n        )\n    );\n\n    test_common!(i8, i8);\n    test_common!(u8, u8);\n    test_common!(i16, i16);\n    test_common!(u16, u16);\n    test_common!(i32, i32);\n    test_common!(u32, u32);\n    test_common!(i64, i64);\n    test_common!(u64, u64);\n    test_common!(isize, isize);\n    test_common!(usize, usize);\n    test_common!(i128, i128);\n    test_common!(u128, u128);\n\n    #[test]\n    fn test_nonzero_u32_max() {\n        Python::attach(|py| {\n            let v = NonZeroU32::new(u32::MAX).unwrap();\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<NonZeroU32>().unwrap());\n            assert_eq!(NonZeroU64::from(v), obj.extract::<NonZeroU64>().unwrap());\n            assert!(obj.extract::<NonZeroI32>().is_err());\n        });\n    }\n\n    #[test]\n    fn test_nonzero_i64_max() {\n        Python::attach(|py| {\n            let v = NonZeroI64::new(i64::MAX).unwrap();\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<NonZeroI64>().unwrap());\n            assert_eq!(\n                NonZeroU64::new(v.get() as u64).unwrap(),\n                obj.extract::<NonZeroU64>().unwrap()\n            );\n            assert!(obj.extract::<NonZeroU32>().is_err());\n        });\n    }\n\n    #[test]\n    fn test_nonzero_i64_min() {\n        Python::attach(|py| {\n            let v = NonZeroI64::new(i64::MIN).unwrap();\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<NonZeroI64>().unwrap());\n            assert!(obj.extract::<NonZeroI32>().is_err());\n            assert!(obj.extract::<NonZeroU64>().is_err());\n        });\n    }\n\n    #[test]\n    fn test_nonzero_u64_max() {\n        Python::attach(|py| {\n            let v = NonZeroU64::new(u64::MAX).unwrap();\n            let obj = v.into_pyobject(py).unwrap();\n            assert_eq!(v, obj.extract::<NonZeroU64>().unwrap());\n            assert!(obj.extract::<NonZeroI64>().is_err());\n        });\n    }\n\n    macro_rules! test_nonzero_common (\n        ($test_mod_name:ident, $t:ty) => (\n            mod $test_mod_name {\n                use crate::exceptions;\n                use crate::conversion::IntoPyObject;\n                use crate::types::PyAnyMethods;\n                use crate::Python;\n                use std::num::*;\n\n                #[test]\n                fn from_py_string_type_error() {\n                    Python::attach(|py| {\n                    let obj = (\"123\").into_pyobject(py).unwrap();\n                    let err = obj.extract::<$t>().unwrap_err();\n                    assert!(err.is_instance_of::<exceptions::PyTypeError>(py));\n                    });\n                }\n\n                #[test]\n                fn from_py_float_type_error() {\n                    Python::attach(|py| {\n                    let obj = (12.3f64).into_pyobject(py).unwrap();\n                    let err = obj.extract::<$t>().unwrap_err();\n                    assert!(err.is_instance_of::<exceptions::PyTypeError>(py));});\n                }\n\n                #[test]\n                fn to_py_object_and_back() {\n                    Python::attach(|py| {\n                    let val = <$t>::new(123).unwrap();\n                    let obj = val.into_pyobject(py).unwrap();\n                    assert_eq!(obj.extract::<$t>().unwrap(), val);});\n                }\n            }\n        )\n    );\n\n    test_nonzero_common!(nonzero_i8, NonZeroI8);\n    test_nonzero_common!(nonzero_u8, NonZeroU8);\n    test_nonzero_common!(nonzero_i16, NonZeroI16);\n    test_nonzero_common!(nonzero_u16, NonZeroU16);\n    test_nonzero_common!(nonzero_i32, NonZeroI32);\n    test_nonzero_common!(nonzero_u32, NonZeroU32);\n    test_nonzero_common!(nonzero_i64, NonZeroI64);\n    test_nonzero_common!(nonzero_u64, NonZeroU64);\n    test_nonzero_common!(nonzero_isize, NonZeroIsize);\n    test_nonzero_common!(nonzero_usize, NonZeroUsize);\n    test_nonzero_common!(nonzero_i128, NonZeroI128);\n    test_nonzero_common!(nonzero_u128, NonZeroU128);\n\n    #[test]\n    fn test_i64_bool() {\n        Python::attach(|py| {\n            let obj = true.into_pyobject(py).unwrap();\n            assert_eq!(1, obj.extract::<i64>().unwrap());\n            let obj = false.into_pyobject(py).unwrap();\n            assert_eq!(0, obj.extract::<i64>().unwrap());\n        })\n    }\n\n    #[test]\n    fn test_i64_f64() {\n        Python::attach(|py| {\n            let obj = 12.34f64.into_pyobject(py).unwrap();\n            let err = obj.extract::<i64>().unwrap_err();\n            assert!(err.is_instance_of::<crate::exceptions::PyTypeError>(py));\n            // with no remainder\n            let obj = 12f64.into_pyobject(py).unwrap();\n            let err = obj.extract::<i64>().unwrap_err();\n            assert!(err.is_instance_of::<crate::exceptions::PyTypeError>(py));\n        })\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/option.rs",
    "content": "#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_union, PyStaticExpr};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::types::PyNone;\nuse crate::{\n    conversion::IntoPyObject, types::any::PyAnyMethods, BoundObject, FromPyObject, PyAny, Python,\n};\nuse crate::{Borrowed, Bound};\n\nimpl<'py, T> IntoPyObject<'py> for Option<T>\nwhere\n    T: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = T::Error;\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_union!(&T::OUTPUT_TYPE, PyNone::TYPE_HINT);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.map_or_else(\n            || Ok(py.None().into_bound(py)),\n            |val| {\n                val.into_pyobject(py)\n                    .map(BoundObject::into_any)\n                    .map(BoundObject::into_bound)\n            },\n        )\n    }\n}\n\nimpl<'a, 'py, T> IntoPyObject<'py> for &'a Option<T>\nwhere\n    &'a T: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = <&'a T as IntoPyObject<'py>>::Error;\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <Option<&T>>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.as_ref().into_pyobject(py)\n    }\n}\n\nimpl<'a, 'py, T> FromPyObject<'a, 'py> for Option<T>\nwhere\n    T: FromPyObject<'a, 'py>,\n{\n    type Error = T::Error;\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_union!(T::INPUT_TYPE, PyNone::TYPE_HINT);\n\n    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        if obj.is_none() {\n            Ok(None)\n        } else {\n            obj.extract().map(Some)\n        }\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/osstr.rs",
    "content": "use crate::conversion::IntoPyObject;\n#[cfg(not(target_os = \"wasi\"))]\nuse crate::ffi;\n#[cfg(not(target_os = \"wasi\"))]\nuse crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::instance::Bound;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::types::PyString;\n#[cfg(any(unix, target_os = \"emscripten\"))]\nuse crate::types::{PyBytes, PyBytesMethods};\nuse crate::{Borrowed, FromPyObject, PyAny, PyErr, Python};\nuse std::borrow::Cow;\nuse std::convert::Infallible;\nuse std::ffi::{OsStr, OsString};\n#[cfg(any(unix, target_os = \"emscripten\"))]\nuse std::os::unix::ffi::OsStrExt;\n#[cfg(windows)]\nuse std::os::windows::ffi::OsStrExt;\n\nimpl<'py> IntoPyObject<'py> for &OsStr {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        // If the string is UTF-8, take the quick and easy shortcut\n        #[cfg(not(target_os = \"wasi\"))]\n        if let Some(valid_utf8_path) = self.to_str() {\n            return valid_utf8_path.into_pyobject(py);\n        }\n\n        #[cfg(target_os = \"wasi\")]\n        {\n            self.to_str()\n                .expect(\"wasi strings are UTF8\")\n                .into_pyobject(py)\n        }\n\n        #[cfg(any(unix, target_os = \"emscripten\"))]\n        {\n            let bytes = self.as_bytes();\n            let ptr = bytes.as_ptr().cast();\n            let len = bytes.len() as ffi::Py_ssize_t;\n            unsafe {\n                // DecodeFSDefault automatically chooses an appropriate decoding mechanism to\n                // parse os strings losslessly (i.e. surrogateescape most of the time)\n                Ok(ffi::PyUnicode_DecodeFSDefaultAndSize(ptr, len)\n                    .assume_owned(py)\n                    .cast_into_unchecked())\n            }\n        }\n\n        #[cfg(windows)]\n        {\n            let wstr: Vec<u16> = self.encode_wide().collect();\n            unsafe {\n                // This will not panic because the data from encode_wide is well-formed Windows\n                // string data\n\n                Ok(\n                    ffi::PyUnicode_FromWideChar(wstr.as_ptr(), wstr.len() as ffi::Py_ssize_t)\n                        .assume_owned(py)\n                        .cast_into_unchecked(),\n                )\n            }\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &&OsStr {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&OsStr>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl FromPyObject<'_, '_> for OsString {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let pystring = ob.cast::<PyString>()?;\n\n        #[cfg(target_os = \"wasi\")]\n        {\n            Ok(pystring.to_cow()?.into_owned().into())\n        }\n\n        #[cfg(any(unix, target_os = \"emscripten\"))]\n        {\n            // Decode from Python's lossless bytes string representation back into raw bytes\n            // SAFETY: PyUnicode_EncodeFSDefault returns a new reference or null on error, known to\n            // be a `bytes` object, thread is attached to the interpreter\n            let fs_encoded_bytes = unsafe {\n                ffi::PyUnicode_EncodeFSDefault(pystring.as_ptr())\n                    .assume_owned_or_err(ob.py())?\n                    .cast_into_unchecked::<PyBytes>()\n            };\n\n            // Create an OsStr view into the raw bytes from Python\n            let os_str: &OsStr = OsStrExt::from_bytes(fs_encoded_bytes.as_bytes());\n\n            Ok(os_str.to_os_string())\n        }\n\n        #[cfg(windows)]\n        {\n            // Take the quick and easy shortcut if UTF-8\n            if let Ok(utf8_string) = pystring.to_cow() {\n                return Ok(utf8_string.into_owned().into());\n            }\n\n            // Get an owned allocated wide char buffer from PyString, which we have to deallocate\n            // ourselves\n            let size =\n                unsafe { ffi::PyUnicode_AsWideChar(pystring.as_ptr(), std::ptr::null_mut(), 0) };\n            crate::err::error_on_minusone(ob.py(), size)?;\n\n            debug_assert!(\n                size > 0,\n                \"PyUnicode_AsWideChar should return at least 1 for null terminator\"\n            );\n            let size = size - 1; // exclude null terminator\n\n            let mut buffer = vec![0; size as usize];\n            let bytes_read =\n                unsafe { ffi::PyUnicode_AsWideChar(pystring.as_ptr(), buffer.as_mut_ptr(), size) };\n            assert_eq!(bytes_read, size);\n\n            // Copy wide char buffer into OsString\n            let os_string = std::os::windows::ffi::OsStringExt::from_wide(&buffer);\n\n            Ok(os_string)\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Cow<'_, OsStr> {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&OsStr>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Cow<'_, OsStr> {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&OsStr>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (&**self).into_pyobject(py)\n    }\n}\n\nimpl<'a> FromPyObject<'a, '_> for Cow<'a, OsStr> {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = OsString::INPUT_TYPE;\n\n    fn extract(obj: Borrowed<'a, '_, PyAny>) -> Result<Self, Self::Error> {\n        #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n        if let Ok(s) = obj.extract::<&str>() {\n            return Ok(Cow::Borrowed(s.as_ref()));\n        }\n\n        obj.extract::<OsString>().map(Cow::Owned)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for OsString {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&OsStr>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.as_os_str().into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &OsString {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&OsStr>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.as_os_str().into_pyobject(py)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    #[cfg(target_os = \"wasi\")]\n    use crate::exceptions::PyFileNotFoundError;\n    use crate::types::{PyAnyMethods, PyString, PyStringMethods};\n    use crate::{Bound, BoundObject, IntoPyObject, Python};\n    use std::fmt::Debug;\n    #[cfg(any(unix, target_os = \"emscripten\"))]\n    use std::os::unix::ffi::OsStringExt;\n    #[cfg(windows)]\n    use std::os::windows::ffi::OsStringExt;\n    use std::{\n        borrow::Cow,\n        ffi::{OsStr, OsString},\n    };\n\n    #[test]\n    #[cfg(any(unix, target_os = \"emscripten\"))]\n    fn test_non_utf8_conversion() {\n        Python::attach(|py| {\n            use std::os::unix::ffi::OsStrExt;\n\n            // this is not valid UTF-8\n            let payload = &[250, 251, 252, 253, 254, 255, 0, 255];\n            let os_str = OsStr::from_bytes(payload);\n\n            // do a roundtrip into Pythonland and back and compare\n            let py_str = os_str.into_pyobject(py).unwrap();\n            let os_str_2: OsString = py_str.extract().unwrap();\n            assert_eq!(os_str, os_str_2);\n        });\n    }\n\n    #[test]\n    #[cfg(target_os = \"wasi\")]\n    fn test_extract_non_utf8_wasi_should_error() {\n        Python::attach(|py| {\n            // Non utf-8 strings are not valid wasi paths\n            let open_result = py.run(c\"open('\\\\udcff', 'rb')\", None, None).unwrap_err();\n            assert!(\n                !open_result.is_instance_of::<PyFileNotFoundError>(py),\n                \"Opening invalid utf8 will error with OSError, not FileNotFoundError\"\n            );\n\n            // Create a Python string with not valid UTF-8: &[255]\n            let py_str = py.eval(c\"'\\\\udcff'\", None, None).unwrap();\n            assert!(\n                py_str.extract::<OsString>().is_err(),\n                \"Extracting invalid UTF-8 as OsString should error\"\n            );\n        });\n    }\n\n    #[test]\n    fn test_intopyobject_roundtrip() {\n        Python::attach(|py| {\n            fn test_roundtrip<'py, T>(py: Python<'py>, obj: T)\n            where\n                T: IntoPyObject<'py> + AsRef<OsStr> + Debug + Clone,\n                T::Error: Debug,\n            {\n                let pyobject = obj.clone().into_pyobject(py).unwrap().into_any();\n                let pystring = pyobject.as_borrowed().cast::<PyString>().unwrap();\n                assert_eq!(pystring.to_string_lossy(), obj.as_ref().to_string_lossy());\n                let roundtripped_obj: OsString = pystring.extract().unwrap();\n                assert_eq!(obj.as_ref(), roundtripped_obj.as_os_str());\n            }\n            let os_str = OsStr::new(\"Hello\\0\\n🐍\");\n            test_roundtrip::<&OsStr>(py, os_str);\n            test_roundtrip::<Cow<'_, OsStr>>(py, Cow::Borrowed(os_str));\n            test_roundtrip::<Cow<'_, OsStr>>(py, Cow::Owned(os_str.to_os_string()));\n            test_roundtrip::<OsString>(py, os_str.to_os_string());\n        });\n    }\n\n    #[test]\n    #[cfg(windows)]\n    fn test_windows_non_utf8_osstring_roundtrip() {\n        use std::os::windows::ffi::{OsStrExt, OsStringExt};\n\n        Python::attach(|py| {\n            // Example: Unpaired surrogate (0xD800) is not valid UTF-8, but valid in Windows OsString\n            let wide: &[u16] = &['A' as u16, 0xD800, 'B' as u16]; // 'A', unpaired surrogate, 'B'\n            let os_str = OsString::from_wide(wide);\n\n            assert_eq!(os_str.to_string_lossy(), \"A�B\");\n\n            // This cannot be represented as UTF-8, so .to_str() would return None\n            assert!(os_str.to_str().is_none());\n\n            // Convert to Python and back\n            let py_str = os_str.as_os_str().into_pyobject(py).unwrap();\n            let os_str_2 = py_str.extract::<OsString>().unwrap();\n\n            // The roundtrip should preserve the original wide data\n            assert_eq!(os_str, os_str_2);\n\n            // Show that encode_wide is necessary: direct UTF-8 conversion would lose information\n            let encoded: Vec<u16> = os_str.encode_wide().collect();\n            assert_eq!(encoded, wide);\n        });\n    }\n\n    #[test]\n    fn test_extract_cow() {\n        Python::attach(|py| {\n            fn test_extract<'py, T>(py: Python<'py>, input: &T, is_borrowed: bool)\n            where\n                for<'a> &'a T: IntoPyObject<'py, Output = Bound<'py, PyString>>,\n                for<'a> <&'a T as IntoPyObject<'py>>::Error: Debug,\n                T: AsRef<OsStr> + ?Sized,\n            {\n                let pystring = input.into_pyobject(py).unwrap();\n                let cow: Cow<'_, OsStr> = pystring.extract().unwrap();\n                assert_eq!(cow, input.as_ref());\n                assert_eq!(is_borrowed, matches!(cow, Cow::Borrowed(_)));\n            }\n\n            // On Python 3.10+ or when not using the limited API, we can borrow strings from python\n            let can_borrow_str = cfg!(any(Py_3_10, not(Py_LIMITED_API)));\n            // This can be borrowed because it is valid UTF-8\n            test_extract::<str>(py, \"Hello\\0\\n🐍\", can_borrow_str);\n            test_extract::<str>(py, \"Hello, world!\", can_borrow_str);\n\n            #[cfg(windows)]\n            let os_str = {\n                // 'A', unpaired surrogate, 'B'\n                OsString::from_wide(&['A' as u16, 0xD800, 'B' as u16])\n            };\n\n            #[cfg(any(unix, target_os = \"emscripten\"))]\n            let os_str = { OsString::from_vec(vec![250, 251, 252, 253, 254, 255, 0, 255]) };\n\n            // This cannot be borrowed because it is not valid UTF-8\n            #[cfg(any(windows, unix, target_os = \"emscripten\"))]\n            test_extract::<OsStr>(py, &os_str, false);\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/path.rs",
    "content": "use crate::conversion::IntoPyObject;\nuse crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_identifier, type_hint_subscript, type_hint_union, PyStaticExpr};\nuse crate::sync::PyOnceLock;\nuse crate::types::any::PyAnyMethods;\nuse crate::{ffi, Borrowed, Bound, FromPyObject, Py, PyAny, PyErr, Python};\nuse std::borrow::Cow;\nuse std::ffi::OsString;\nuse std::path::{Path, PathBuf};\n\nimpl FromPyObject<'_, '_> for PathBuf {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_union!(\n        OsString::INPUT_TYPE,\n        type_hint_subscript!(\n            type_hint_identifier!(\"os\", \"PathLike\"),\n            OsString::INPUT_TYPE\n        )\n    );\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        // We use os.fspath to get the underlying path as bytes or str\n        let path = unsafe { ffi::PyOS_FSPath(ob.as_ptr()).assume_owned_or_err(ob.py())? };\n        Ok(path.extract::<OsString>()?.into())\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Path {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"pathlib\", \"Path\");\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        static PY_PATH: PyOnceLock<Py<PyAny>> = PyOnceLock::new();\n        PY_PATH\n            .import(py, \"pathlib\", \"Path\")?\n            .call((self.as_os_str(),), None)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &&Path {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&Path>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Cow<'_, Path> {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&Path>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Cow<'_, Path> {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&Path>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (&**self).into_pyobject(py)\n    }\n}\n\nimpl<'a> FromPyObject<'a, '_> for Cow<'a, Path> {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PathBuf::INPUT_TYPE;\n\n    fn extract(obj: Borrowed<'a, '_, PyAny>) -> Result<Self, Self::Error> {\n        #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n        if let Ok(s) = obj.extract::<&str>() {\n            return Ok(Cow::Borrowed(s.as_ref()));\n        }\n\n        obj.extract::<PathBuf>().map(Cow::Owned)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for PathBuf {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&Path>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (&self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &PathBuf {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&Path>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (&**self).into_pyobject(py)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::{\n        types::{PyAnyMethods, PyString},\n        IntoPyObjectExt,\n    };\n    #[cfg(not(target_os = \"wasi\"))]\n    use std::ffi::OsStr;\n    use std::fmt::Debug;\n    #[cfg(any(unix, target_os = \"emscripten\"))]\n    use std::os::unix::ffi::OsStringExt;\n    #[cfg(windows)]\n    use std::os::windows::ffi::OsStringExt;\n\n    #[test]\n    #[cfg(any(unix, target_os = \"emscripten\"))]\n    fn test_non_utf8_conversion() {\n        Python::attach(|py| {\n            use std::os::unix::ffi::OsStrExt;\n\n            // this is not valid UTF-8\n            let payload = &[250, 251, 252, 253, 254, 255, 0, 255];\n            let path = Path::new(OsStr::from_bytes(payload));\n\n            // do a roundtrip into Pythonland and back and compare\n            let py_str = path.into_pyobject(py).unwrap();\n            let path_2: PathBuf = py_str.extract().unwrap();\n            assert_eq!(path, path_2);\n        });\n    }\n\n    #[test]\n    fn test_intopyobject_roundtrip() {\n        Python::attach(|py| {\n            fn test_roundtrip<'py, T>(py: Python<'py>, obj: T)\n            where\n                T: IntoPyObject<'py> + AsRef<Path> + Debug + Clone,\n                T::Error: Debug,\n            {\n                let pyobject = obj.clone().into_bound_py_any(py).unwrap();\n                let roundtripped_obj: PathBuf = pyobject.extract().unwrap();\n                assert_eq!(obj.as_ref(), roundtripped_obj.as_path());\n            }\n            let path = Path::new(\"Hello\\0\\n🐍\");\n            test_roundtrip::<&Path>(py, path);\n            test_roundtrip::<Cow<'_, Path>>(py, Cow::Borrowed(path));\n            test_roundtrip::<Cow<'_, Path>>(py, Cow::Owned(path.to_path_buf()));\n            test_roundtrip::<PathBuf>(py, path.to_path_buf());\n        });\n    }\n\n    #[test]\n    fn test_from_pystring() {\n        Python::attach(|py| {\n            let path = \"Hello\\0\\n🐍\";\n            let pystring = PyString::new(py, path);\n            let roundtrip: PathBuf = pystring.extract().unwrap();\n            assert_eq!(roundtrip, Path::new(path));\n        });\n    }\n\n    #[test]\n    fn test_extract_cow() {\n        Python::attach(|py| {\n            fn test_extract<'py, T>(py: Python<'py>, path: &T, is_borrowed: bool)\n            where\n                for<'a> &'a T: IntoPyObject<'py, Output = Bound<'py, PyString>>,\n                for<'a> <&'a T as IntoPyObject<'py>>::Error: Debug,\n                T: AsRef<Path> + ?Sized,\n            {\n                let pystring = path.into_pyobject(py).unwrap();\n                let cow: Cow<'_, Path> = pystring.extract().unwrap();\n                assert_eq!(cow, path.as_ref());\n                assert_eq!(is_borrowed, matches!(cow, Cow::Borrowed(_)));\n            }\n\n            // On Python 3.10+ or when not using the limited API, we can borrow strings from python\n            let can_borrow_str = cfg!(any(Py_3_10, not(Py_LIMITED_API)));\n            // This can be borrowed because it is valid UTF-8\n            test_extract::<str>(py, \"Hello\\0\\n🐍\", can_borrow_str);\n            test_extract::<str>(py, \"Hello, world!\", can_borrow_str);\n\n            #[cfg(windows)]\n            let os_str = {\n                // 'A', unpaired surrogate, 'B'\n                OsString::from_wide(&['A' as u16, 0xD800, 'B' as u16])\n            };\n\n            #[cfg(any(unix, target_os = \"emscripten\"))]\n            let os_str = { OsString::from_vec(vec![250, 251, 252, 253, 254, 255, 0, 255]) };\n\n            // This cannot be borrowed because it is not valid UTF-8\n            #[cfg(any(unix, windows, target_os = \"emscripten\"))]\n            test_extract::<OsStr>(py, &os_str, false);\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/set.rs",
    "content": "use std::{cmp, collections, hash};\n\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_subscript, PyStaticExpr};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::{\n    conversion::{FromPyObjectOwned, IntoPyObject},\n    types::{\n        any::PyAnyMethods, frozenset::PyFrozenSetMethods, set::PySetMethods, PyFrozenSet, PySet,\n    },\n    Borrowed, Bound, FromPyObject, PyAny, PyErr, Python,\n};\n\nimpl<'py, K, S> IntoPyObject<'py> for collections::HashSet<K, S>\nwhere\n    K: IntoPyObject<'py> + Eq + hash::Hash,\n    S: hash::BuildHasher + Default,\n{\n    type Target = PySet;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_subscript!(PySet::TYPE_HINT, K::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        PySet::new(py, self)\n    }\n}\n\nimpl<'a, 'py, K, H> IntoPyObject<'py> for &'a collections::HashSet<K, H>\nwhere\n    &'a K: IntoPyObject<'py> + Eq + hash::Hash,\n    H: hash::BuildHasher,\n{\n    type Target = PySet;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_subscript!(PySet::TYPE_HINT, <&K>::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        PySet::new(py, self)\n    }\n}\n\nimpl<'py, K, S> FromPyObject<'_, 'py> for collections::HashSet<K, S>\nwhere\n    K: FromPyObjectOwned<'py> + cmp::Eq + hash::Hash,\n    S: hash::BuildHasher + Default,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_subscript!(PySet::TYPE_HINT, K::INPUT_TYPE);\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        match ob.cast::<PySet>() {\n            Ok(set) => set\n                .iter()\n                .map(|any| any.extract().map_err(Into::into))\n                .collect(),\n            Err(err) => {\n                if let Ok(frozen_set) = ob.cast::<PyFrozenSet>() {\n                    frozen_set\n                        .iter()\n                        .map(|any| any.extract().map_err(Into::into))\n                        .collect()\n                } else {\n                    Err(PyErr::from(err))\n                }\n            }\n        }\n    }\n}\n\nimpl<'py, K> IntoPyObject<'py> for collections::BTreeSet<K>\nwhere\n    K: IntoPyObject<'py> + cmp::Ord,\n{\n    type Target = PySet;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_subscript!(PySet::TYPE_HINT, K::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        PySet::new(py, self)\n    }\n}\n\nimpl<'a, 'py, K> IntoPyObject<'py> for &'a collections::BTreeSet<K>\nwhere\n    &'a K: IntoPyObject<'py> + cmp::Ord,\n    K: 'a,\n{\n    type Target = PySet;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_subscript!(PySet::TYPE_HINT, <&K>::OUTPUT_TYPE);\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        PySet::new(py, self)\n    }\n}\n\nimpl<'py, K> FromPyObject<'_, 'py> for collections::BTreeSet<K>\nwhere\n    K: FromPyObjectOwned<'py> + cmp::Ord,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_subscript!(PySet::TYPE_HINT, K::INPUT_TYPE);\n\n    fn extract(ob: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        match ob.cast::<PySet>() {\n            Ok(set) => set\n                .iter()\n                .map(|any| any.extract().map_err(Into::into))\n                .collect(),\n            Err(err) => {\n                if let Ok(frozen_set) = ob.cast::<PyFrozenSet>() {\n                    frozen_set\n                        .iter()\n                        .map(|any| any.extract().map_err(Into::into))\n                        .collect()\n                } else {\n                    Err(PyErr::from(err))\n                }\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::{any::PyAnyMethods, PyFrozenSet, PySet};\n    use crate::{IntoPyObject, Python};\n    use std::collections::{BTreeSet, HashSet};\n\n    #[test]\n    fn test_extract_hashset() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1, 2, 3, 4, 5]).unwrap();\n            let hash_set: HashSet<usize> = set.extract().unwrap();\n            assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect());\n\n            let set = PyFrozenSet::new(py, [1, 2, 3, 4, 5]).unwrap();\n            let hash_set: HashSet<usize> = set.extract().unwrap();\n            assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect());\n        });\n    }\n\n    #[test]\n    fn test_extract_btreeset() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1, 2, 3, 4, 5]).unwrap();\n            let hash_set: BTreeSet<usize> = set.extract().unwrap();\n            assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect());\n\n            let set = PyFrozenSet::new(py, [1, 2, 3, 4, 5]).unwrap();\n            let hash_set: BTreeSet<usize> = set.extract().unwrap();\n            assert_eq!(hash_set, [1, 2, 3, 4, 5].iter().copied().collect());\n        });\n    }\n\n    #[test]\n    fn test_set_into_pyobject() {\n        Python::attach(|py| {\n            let bt: BTreeSet<u64> = [1, 2, 3, 4, 5].iter().cloned().collect();\n            let hs: HashSet<u64> = [1, 2, 3, 4, 5].iter().cloned().collect();\n\n            let bto = (&bt).into_pyobject(py).unwrap();\n            let hso = (&hs).into_pyobject(py).unwrap();\n\n            assert_eq!(bt, bto.extract().unwrap());\n            assert_eq!(hs, hso.extract().unwrap());\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/slice.rs",
    "content": "use std::borrow::Cow;\n\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::{\n    conversion::IntoPyObject, types::PyBytes, Bound, CastError, PyAny, PyErr, PyResult, Python,\n};\n\nimpl<'a, 'py, T> IntoPyObject<'py> for &'a [T]\nwhere\n    &'a T: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&T>::SEQUENCE_OUTPUT_TYPE;\n\n    /// Turns [`&[u8]`](std::slice) into [`PyBytes`], all other `T`s will be turned into a [`PyList`]\n    ///\n    /// [`PyBytes`]: crate::types::PyBytes\n    /// [`PyList`]: crate::types::PyList\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        <&T>::borrowed_sequence_into_pyobject(self, py, crate::conversion::private::Token)\n    }\n}\n\nimpl<'a, 'py> crate::conversion::FromPyObject<'a, 'py> for &'a [u8] {\n    type Error = CastError<'a, 'py>;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyBytes::TYPE_HINT;\n\n    fn extract(obj: crate::Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        Ok(obj.cast::<PyBytes>()?.as_bytes())\n    }\n}\n\n/// Special-purpose trait impl to efficiently handle both `bytes` and `bytearray`\n///\n/// If the source object is a `bytes` object, the `Cow` will be borrowed and\n/// pointing into the source object, and no copying or heap allocations will happen.\n/// If it is a `bytearray`, its contents will be copied to an owned `Cow`.\nimpl<'a, 'py> crate::conversion::FromPyObject<'a, 'py> for Cow<'a, [u8]> {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = Vec::<u8>::INPUT_TYPE;\n\n    fn extract(ob: crate::Borrowed<'a, 'py, PyAny>) -> PyResult<Self> {\n        Ok(if let Ok(bytes) = ob.cast::<PyBytes>() {\n            Cow::Borrowed(bytes.as_bytes()) // It's immutable, we can take a slice\n        } else {\n            Cow::Owned(Vec::extract(ob)?) // Not possible to take a slice, we have to build a Vec<u8>\n        })\n    }\n}\n\nimpl<'py, T> IntoPyObject<'py> for Cow<'_, [T]>\nwhere\n    T: Clone,\n    for<'a> &'a T: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&T>::SEQUENCE_OUTPUT_TYPE;\n\n    /// Turns `Cow<[u8]>` into [`PyBytes`], all other `T`s will be turned into a [`PyList`]\n    ///\n    /// [`PyBytes`]: crate::types::PyBytes\n    /// [`PyList`]: crate::types::PyList\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        <&T>::borrowed_sequence_into_pyobject(self.as_ref(), py, crate::conversion::private::Token)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::borrow::Cow;\n\n    use crate::{\n        conversion::IntoPyObject,\n        types::{any::PyAnyMethods, PyBytes, PyBytesMethods, PyList},\n        Python,\n    };\n\n    #[test]\n    fn test_extract_bytes() {\n        Python::attach(|py| {\n            let py_bytes = py.eval(c\"b'Hello Python'\", None, None).unwrap();\n            let bytes: &[u8] = py_bytes.extract().unwrap();\n            assert_eq!(bytes, b\"Hello Python\");\n        });\n    }\n\n    #[test]\n    fn test_cow_impl() {\n        Python::attach(|py| {\n            let bytes = py.eval(cr#\"b\"foobar\"\"#, None, None).unwrap();\n            let cow = bytes.extract::<Cow<'_, [u8]>>().unwrap();\n            assert_eq!(cow, Cow::<[u8]>::Borrowed(b\"foobar\"));\n\n            let byte_array = py.eval(cr#\"bytearray(b\"foobar\")\"#, None, None).unwrap();\n            let cow = byte_array.extract::<Cow<'_, [u8]>>().unwrap();\n            assert_eq!(cow, Cow::<[u8]>::Owned(b\"foobar\".to_vec()));\n\n            let something_else_entirely = py.eval(c\"42\", None, None).unwrap();\n            something_else_entirely\n                .extract::<Cow<'_, [u8]>>()\n                .unwrap_err();\n\n            let cow = Cow::<[u8]>::Borrowed(b\"foobar\").into_pyobject(py).unwrap();\n            assert!(cow.is_instance_of::<PyBytes>());\n\n            let cow = Cow::<[u8]>::Owned(b\"foobar\".to_vec())\n                .into_pyobject(py)\n                .unwrap();\n            assert!(cow.is_instance_of::<PyBytes>());\n        });\n    }\n\n    #[test]\n    fn test_slice_intopyobject_impl() {\n        Python::attach(|py| {\n            let bytes: &[u8] = b\"foobar\";\n            let obj = bytes.into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyBytes>());\n            let obj = obj.cast_into::<PyBytes>().unwrap();\n            assert_eq!(obj.as_bytes(), bytes);\n\n            let nums: &[u16] = &[0, 1, 2, 3];\n            let obj = nums.into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyList>());\n        });\n    }\n\n    #[test]\n    fn test_cow_intopyobject_impl() {\n        Python::attach(|py| {\n            let borrowed_bytes = Cow::<[u8]>::Borrowed(b\"foobar\");\n            let obj = borrowed_bytes.clone().into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyBytes>());\n            let obj = obj.cast_into::<PyBytes>().unwrap();\n            assert_eq!(obj.as_bytes(), &*borrowed_bytes);\n\n            let owned_bytes = Cow::<[u8]>::Owned(b\"foobar\".to_vec());\n            let obj = owned_bytes.clone().into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyBytes>());\n            let obj = obj.cast_into::<PyBytes>().unwrap();\n            assert_eq!(obj.as_bytes(), &*owned_bytes);\n\n            let borrowed_nums = Cow::<[u16]>::Borrowed(&[0, 1, 2, 3]);\n            let obj = borrowed_nums.into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyList>());\n\n            let owned_nums = Cow::<[u16]>::Owned(vec![0, 1, 2, 3]);\n            let obj = owned_nums.into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyList>());\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/string.rs",
    "content": "#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::{\n    conversion::IntoPyObject, instance::Bound, types::PyString, Borrowed, FromPyObject, PyAny,\n    PyErr, Python,\n};\nuse std::{borrow::Cow, convert::Infallible};\n\nimpl<'py> IntoPyObject<'py> for &str {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = String::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PyString::new(py, self))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &&str {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = String::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Cow<'_, str> {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = String::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Cow<'_, str> {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = String::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (&**self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for char {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = String::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let mut bytes = [0u8; 4];\n        Ok(PyString::new(py, self.encode_utf8(&mut bytes)))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &char {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = String::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for String {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PyString::new(py, &self))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &String {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = String::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PyString::new(py, self))\n    }\n}\n\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\nimpl<'a> FromPyObject<'a, '_> for &'a str {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'a, '_, PyAny>) -> Result<Self, Self::Error> {\n        ob.cast::<PyString>()?.to_str()\n    }\n}\n\nimpl<'a> FromPyObject<'a, '_> for Cow<'a, str> {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'a, '_, PyAny>) -> Result<Self, Self::Error> {\n        ob.cast::<PyString>()?.to_cow()\n    }\n}\n\n/// Allows extracting strings from Python objects.\n/// Accepts Python `str` and `unicode` objects.\nimpl FromPyObject<'_, '_> for String {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        obj.cast::<PyString>()?.to_cow().map(Cow::into_owned)\n    }\n}\n\nimpl FromPyObject<'_, '_> for char {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let s = obj.cast::<PyString>()?.to_cow()?;\n        let mut iter = s.chars();\n        if let (Some(ch), None) = (iter.next(), iter.next()) {\n            Ok(ch)\n        } else {\n            Err(crate::exceptions::PyValueError::new_err(\n                \"expected a string of length 1\",\n            ))\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::any::PyAnyMethods;\n    use crate::{IntoPyObject, Python};\n    use std::borrow::Cow;\n\n    #[test]\n    fn test_cow_into_pyobject() {\n        Python::attach(|py| {\n            let s = \"Hello Python\";\n            let py_string = Cow::Borrowed(s).into_pyobject(py).unwrap();\n            assert_eq!(s, py_string.extract::<Cow<'_, str>>().unwrap());\n            let py_string = Cow::<str>::Owned(s.into()).into_pyobject(py).unwrap();\n            assert_eq!(s, py_string.extract::<Cow<'_, str>>().unwrap());\n        })\n    }\n\n    #[test]\n    fn test_non_bmp() {\n        Python::attach(|py| {\n            let s = \"\\u{1F30F}\";\n            let py_string = s.into_pyobject(py).unwrap();\n            assert_eq!(s, py_string.extract::<String>().unwrap());\n        })\n    }\n\n    #[test]\n    fn test_extract_str() {\n        Python::attach(|py| {\n            let s = \"Hello Python\";\n            let py_string = s.into_pyobject(py).unwrap();\n\n            let s2: Cow<'_, str> = py_string.extract().unwrap();\n            assert_eq!(s, s2);\n        })\n    }\n\n    #[test]\n    fn test_extract_char() {\n        Python::attach(|py| {\n            let ch = '😃';\n            let py_string = ch.into_pyobject(py).unwrap();\n            let ch2: char = py_string.extract().unwrap();\n            assert_eq!(ch, ch2);\n        })\n    }\n\n    #[test]\n    fn test_extract_char_err() {\n        Python::attach(|py| {\n            let s = \"Hello Python\";\n            let py_string = s.into_pyobject(py).unwrap();\n            let err: crate::PyResult<char> = py_string.extract();\n            assert!(err\n                .unwrap_err()\n                .to_string()\n                .contains(\"expected a string of length 1\"));\n        })\n    }\n\n    #[test]\n    fn test_string_into_pyobject() {\n        Python::attach(|py| {\n            let s = \"Hello Python\";\n            let s2 = s.to_owned();\n            let s3 = &s2;\n            assert_eq!(\n                s,\n                s3.into_pyobject(py)\n                    .unwrap()\n                    .extract::<Cow<'_, str>>()\n                    .unwrap()\n            );\n            assert_eq!(\n                s,\n                s2.into_pyobject(py)\n                    .unwrap()\n                    .extract::<Cow<'_, str>>()\n                    .unwrap()\n            );\n            assert_eq!(\n                s,\n                s.into_pyobject(py)\n                    .unwrap()\n                    .extract::<Cow<'_, str>>()\n                    .unwrap()\n            );\n        })\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/time.rs",
    "content": "use crate::conversion::IntoPyObject;\nuse crate::exceptions::{PyOverflowError, PyValueError};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(Py_LIMITED_API)]\nuse crate::intern;\nuse crate::sync::PyOnceLock;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::types::any::PyAnyMethods;\n#[cfg(not(Py_LIMITED_API))]\nuse crate::types::PyDeltaAccess;\nuse crate::types::{PyDateTime, PyDelta, PyTzInfo};\nuse crate::{Borrowed, Bound, FromPyObject, Py, PyAny, PyErr, PyResult, Python};\nuse std::time::{Duration, SystemTime, UNIX_EPOCH};\n\nconst SECONDS_PER_DAY: u64 = 24 * 60 * 60;\n\nimpl FromPyObject<'_, '_> for Duration {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDelta::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let delta = obj.cast::<PyDelta>()?;\n        #[cfg(not(Py_LIMITED_API))]\n        let (days, seconds, microseconds) = {\n            (\n                delta.get_days(),\n                delta.get_seconds(),\n                delta.get_microseconds(),\n            )\n        };\n        #[cfg(Py_LIMITED_API)]\n        let (days, seconds, microseconds): (i32, i32, i32) = {\n            let py = delta.py();\n            (\n                delta.getattr(intern!(py, \"days\"))?.extract()?,\n                delta.getattr(intern!(py, \"seconds\"))?.extract()?,\n                delta.getattr(intern!(py, \"microseconds\"))?.extract()?,\n            )\n        };\n\n        // We cast\n        let days = u64::try_from(days).map_err(|_| {\n            PyValueError::new_err(\n                \"It is not possible to convert a negative timedelta to a Rust Duration\",\n            )\n        })?;\n        let seconds = u64::try_from(seconds).unwrap(); // 0 <= seconds < 3600*24\n        let microseconds = u32::try_from(microseconds).unwrap(); // 0 <= microseconds < 1000000\n\n        // We convert\n        let total_seconds = days * SECONDS_PER_DAY + seconds; // We casted from i32, this can't overflow\n        let nanoseconds = microseconds.checked_mul(1_000).unwrap(); // 0 <= microseconds < 1000000\n\n        Ok(Duration::new(total_seconds, nanoseconds))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Duration {\n    type Target = PyDelta;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDelta::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let days = self.as_secs() / SECONDS_PER_DAY;\n        let seconds = self.as_secs() % SECONDS_PER_DAY;\n        let microseconds = self.subsec_micros();\n\n        PyDelta::new(\n            py,\n            days.try_into()?,\n            seconds.try_into()?,\n            microseconds.try_into()?,\n            false,\n        )\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Duration {\n    type Target = PyDelta;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Duration::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\n// Conversions between SystemTime and datetime do not rely on the floating point timestamp of the\n// timestamp/fromtimestamp APIs to avoid possible precision loss but goes through the\n// timedelta/std::time::Duration types by taking for reference point the UNIX epoch.\n//\n// TODO: it might be nice to investigate using timestamps anyway, at least when the datetime is a safe range.\n\nimpl FromPyObject<'_, '_> for SystemTime {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let duration_since_unix_epoch: Duration = obj.sub(unix_epoch_py(obj.py())?)?.extract()?;\n        UNIX_EPOCH\n            .checked_add(duration_since_unix_epoch)\n            .ok_or_else(|| {\n                PyOverflowError::new_err(\"Overflow error when converting the time to Rust\")\n            })\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for SystemTime {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let duration_since_unix_epoch =\n            self.duration_since(UNIX_EPOCH).unwrap().into_pyobject(py)?;\n        unix_epoch_py(py)?\n            .add(duration_since_unix_epoch)?\n            .cast_into()\n            .map_err(Into::into)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &SystemTime {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = SystemTime::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nfn unix_epoch_py(py: Python<'_>) -> PyResult<Borrowed<'_, '_, PyDateTime>> {\n    static UNIX_EPOCH: PyOnceLock<Py<PyDateTime>> = PyOnceLock::new();\n    Ok(UNIX_EPOCH\n        .get_or_try_init(py, || {\n            let utc = PyTzInfo::utc(py)?;\n            Ok::<_, PyErr>(PyDateTime::new(py, 1970, 1, 1, 0, 0, 0, 0, Some(&utc))?.into())\n        })?\n        .bind_borrowed(py))\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::PyDict;\n\n    #[test]\n    fn test_duration_frompyobject() {\n        Python::attach(|py| {\n            assert_eq!(\n                new_timedelta(py, 0, 0, 0).extract::<Duration>().unwrap(),\n                Duration::new(0, 0)\n            );\n            assert_eq!(\n                new_timedelta(py, 1, 0, 0).extract::<Duration>().unwrap(),\n                Duration::new(86400, 0)\n            );\n            assert_eq!(\n                new_timedelta(py, 0, 1, 0).extract::<Duration>().unwrap(),\n                Duration::new(1, 0)\n            );\n            assert_eq!(\n                new_timedelta(py, 0, 0, 1).extract::<Duration>().unwrap(),\n                Duration::new(0, 1_000)\n            );\n            assert_eq!(\n                new_timedelta(py, 1, 1, 1).extract::<Duration>().unwrap(),\n                Duration::new(86401, 1_000)\n            );\n            assert_eq!(\n                timedelta_class(py)\n                    .getattr(\"max\")\n                    .unwrap()\n                    .extract::<Duration>()\n                    .unwrap(),\n                Duration::new(86399999999999, 999999000)\n            );\n        });\n    }\n\n    #[test]\n    fn test_duration_frompyobject_negative() {\n        Python::attach(|py| {\n            assert_eq!(\n                new_timedelta(py, 0, -1, 0)\n                    .extract::<Duration>()\n                    .unwrap_err()\n                    .to_string(),\n                \"ValueError: It is not possible to convert a negative timedelta to a Rust Duration\"\n            );\n        })\n    }\n\n    #[test]\n    fn test_duration_into_pyobject() {\n        Python::attach(|py| {\n            let assert_eq = |l: Bound<'_, PyAny>, r: Bound<'_, PyAny>| {\n                assert!(l.eq(r).unwrap());\n            };\n\n            assert_eq(\n                Duration::new(0, 0).into_pyobject(py).unwrap().into_any(),\n                new_timedelta(py, 0, 0, 0),\n            );\n            assert_eq(\n                Duration::new(86400, 0)\n                    .into_pyobject(py)\n                    .unwrap()\n                    .into_any(),\n                new_timedelta(py, 1, 0, 0),\n            );\n            assert_eq(\n                Duration::new(1, 0).into_pyobject(py).unwrap().into_any(),\n                new_timedelta(py, 0, 1, 0),\n            );\n            assert_eq(\n                Duration::new(0, 1_000)\n                    .into_pyobject(py)\n                    .unwrap()\n                    .into_any(),\n                new_timedelta(py, 0, 0, 1),\n            );\n            assert_eq(\n                Duration::new(0, 1).into_pyobject(py).unwrap().into_any(),\n                new_timedelta(py, 0, 0, 0),\n            );\n            assert_eq(\n                Duration::new(86401, 1_000)\n                    .into_pyobject(py)\n                    .unwrap()\n                    .into_any(),\n                new_timedelta(py, 1, 1, 1),\n            );\n            assert_eq(\n                Duration::new(86399999999999, 999999000)\n                    .into_pyobject(py)\n                    .unwrap()\n                    .into_any(),\n                timedelta_class(py).getattr(\"max\").unwrap(),\n            );\n        });\n    }\n\n    #[test]\n    fn test_duration_into_pyobject_overflow() {\n        Python::attach(|py| {\n            assert!(Duration::MAX.into_pyobject(py).is_err());\n        })\n    }\n\n    #[test]\n    fn test_time_frompyobject() {\n        Python::attach(|py| {\n            assert_eq!(\n                new_datetime(py, 1970, 1, 1, 0, 0, 0, 0)\n                    .extract::<SystemTime>()\n                    .unwrap(),\n                UNIX_EPOCH\n            );\n            assert_eq!(\n                new_datetime(py, 2020, 2, 3, 4, 5, 6, 7)\n                    .extract::<SystemTime>()\n                    .unwrap(),\n                UNIX_EPOCH\n                    .checked_add(Duration::new(1580702706, 7000))\n                    .unwrap()\n            );\n            assert_eq!(\n                max_datetime(py).extract::<SystemTime>().unwrap(),\n                UNIX_EPOCH\n                    .checked_add(Duration::new(253402300799, 999999000))\n                    .unwrap()\n            );\n        });\n    }\n\n    #[test]\n    fn test_time_frompyobject_before_epoch() {\n        Python::attach(|py| {\n            assert_eq!(\n                new_datetime(py, 1950, 1, 1, 0, 0, 0, 0)\n                    .extract::<SystemTime>()\n                    .unwrap_err()\n                    .to_string(),\n                \"ValueError: It is not possible to convert a negative timedelta to a Rust Duration\"\n            );\n        })\n    }\n\n    #[test]\n    fn test_time_intopyobject() {\n        Python::attach(|py| {\n            let assert_eq = |l: Bound<'_, PyDateTime>, r: Bound<'_, PyDateTime>| {\n                assert!(l.eq(r).unwrap());\n            };\n\n            assert_eq(\n                UNIX_EPOCH\n                    .checked_add(Duration::new(1580702706, 7123))\n                    .unwrap()\n                    .into_pyobject(py)\n                    .unwrap(),\n                new_datetime(py, 2020, 2, 3, 4, 5, 6, 7),\n            );\n            assert_eq(\n                UNIX_EPOCH\n                    .checked_add(Duration::new(253402300799, 999999000))\n                    .unwrap()\n                    .into_pyobject(py)\n                    .unwrap(),\n                max_datetime(py),\n            );\n        });\n    }\n\n    #[expect(clippy::too_many_arguments)]\n    fn new_datetime(\n        py: Python<'_>,\n        year: i32,\n        month: u8,\n        day: u8,\n        hour: u8,\n        minute: u8,\n        second: u8,\n        microsecond: u32,\n    ) -> Bound<'_, PyDateTime> {\n        let utc = PyTzInfo::utc(py).unwrap();\n        PyDateTime::new(\n            py,\n            year,\n            month,\n            day,\n            hour,\n            minute,\n            second,\n            microsecond,\n            Some(&utc),\n        )\n        .unwrap()\n    }\n\n    fn max_datetime(py: Python<'_>) -> Bound<'_, PyDateTime> {\n        let naive_max = datetime_class(py).getattr(\"max\").unwrap();\n        let kargs = PyDict::new(py);\n        kargs\n            .set_item(\"tzinfo\", PyTzInfo::utc(py).unwrap())\n            .unwrap();\n        naive_max\n            .call_method(\"replace\", (), Some(&kargs))\n            .unwrap()\n            .cast_into()\n            .unwrap()\n    }\n\n    #[test]\n    fn test_time_intopyobject_overflow() {\n        let big_system_time = UNIX_EPOCH\n            .checked_add(Duration::new(300000000000, 0))\n            .unwrap();\n        Python::attach(|py| {\n            assert!(big_system_time.into_pyobject(py).is_err());\n        })\n    }\n\n    fn new_timedelta(\n        py: Python<'_>,\n        days: i32,\n        seconds: i32,\n        microseconds: i32,\n    ) -> Bound<'_, PyAny> {\n        timedelta_class(py)\n            .call1((days, seconds, microseconds))\n            .unwrap()\n    }\n\n    fn datetime_class(py: Python<'_>) -> Bound<'_, PyAny> {\n        py.import(\"datetime\").unwrap().getattr(\"datetime\").unwrap()\n    }\n\n    fn timedelta_class(py: Python<'_>) -> Bound<'_, PyAny> {\n        py.import(\"datetime\").unwrap().getattr(\"timedelta\").unwrap()\n    }\n}\n"
  },
  {
    "path": "src/conversions/std/vec.rs",
    "content": "#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_subscript, PyStaticExpr};\nuse crate::{\n    conversion::{FromPyObject, FromPyObjectOwned, FromPyObjectSequence, IntoPyObject},\n    exceptions::PyTypeError,\n    ffi,\n    types::{PyAnyMethods, PySequence, PyString},\n    Borrowed, CastError, PyResult, PyTypeInfo,\n};\nuse crate::{Bound, PyAny, PyErr, Python};\n\nimpl<'py, T> IntoPyObject<'py> for Vec<T>\nwhere\n    T: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::SEQUENCE_OUTPUT_TYPE;\n\n    /// Turns [`Vec<u8>`] into [`PyBytes`], all other `T`s will be turned into a [`PyList`]\n    ///\n    /// [`PyBytes`]: crate::types::PyBytes\n    /// [`PyList`]: crate::types::PyList\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        T::owned_sequence_into_pyobject(self, py, crate::conversion::private::Token)\n    }\n}\n\nimpl<'a, 'py, T> IntoPyObject<'py> for &'a Vec<T>\nwhere\n    &'a T: IntoPyObject<'py>,\n{\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = <&[T]>::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        // NB: we could actually not cast to `PyAny`, which would be nice for\n        // `&Vec<u8>`, but that'd be inconsistent with the `IntoPyObject` impl\n        // above which always returns a `PyAny` for `Vec<T>`.\n        self.as_slice().into_pyobject(py).map(Bound::into_any)\n    }\n}\n\nimpl<'py, T> FromPyObject<'_, 'py> for Vec<T>\nwhere\n    T: FromPyObjectOwned<'py>,\n{\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_subscript!(PySequence::TYPE_HINT, T::INPUT_TYPE);\n\n    fn extract(obj: Borrowed<'_, 'py, PyAny>) -> PyResult<Self> {\n        if let Some(extractor) = T::sequence_extractor(obj, crate::conversion::private::Token) {\n            return Ok(extractor.to_vec());\n        }\n\n        if obj.is_instance_of::<PyString>() {\n            return Err(PyTypeError::new_err(\"Can't extract `str` to `Vec`\"));\n        }\n\n        extract_sequence(obj)\n    }\n}\n\nfn extract_sequence<'py, T>(obj: Borrowed<'_, 'py, PyAny>) -> PyResult<Vec<T>>\nwhere\n    T: FromPyObjectOwned<'py>,\n{\n    // Types that pass `PySequence_Check` usually implement enough of the sequence protocol\n    // to support this function and if not, we will only fail extraction safely.\n    if unsafe { ffi::PySequence_Check(obj.as_ptr()) } == 0 {\n        return Err(CastError::new(obj, PySequence::type_object(obj.py()).into_any()).into());\n    }\n\n    let mut v = Vec::with_capacity(obj.len().unwrap_or(0));\n    for item in obj.try_iter()? {\n        v.push(item?.extract::<T>().map_err(Into::into)?);\n    }\n    Ok(v)\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::conversion::IntoPyObject;\n    use crate::types::{PyAnyMethods, PyBytes, PyBytesMethods, PyList};\n    use crate::Python;\n\n    #[test]\n    fn test_vec_intopyobject_impl() {\n        Python::attach(|py| {\n            let bytes: Vec<u8> = b\"foobar\".to_vec();\n            let obj = bytes.clone().into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyBytes>());\n            let obj = obj.cast_into::<PyBytes>().unwrap();\n            assert_eq!(obj.as_bytes(), &bytes);\n\n            let nums: Vec<u16> = vec![0, 1, 2, 3];\n            let obj = nums.into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyList>());\n        });\n    }\n\n    #[test]\n    fn test_vec_reference_intopyobject_impl() {\n        Python::attach(|py| {\n            let bytes: Vec<u8> = b\"foobar\".to_vec();\n            let obj = (&bytes).into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyBytes>());\n            let obj = obj.cast_into::<PyBytes>().unwrap();\n            assert_eq!(obj.as_bytes(), &bytes);\n\n            let nums: Vec<u16> = vec![0, 1, 2, 3];\n            let obj = (&nums).into_pyobject(py).unwrap();\n            assert!(obj.is_instance_of::<PyList>());\n        });\n    }\n\n    #[test]\n    fn test_strings_cannot_be_extracted_to_vec() {\n        Python::attach(|py| {\n            let v = \"London Calling\";\n            let ob = v.into_pyobject(py).unwrap();\n\n            assert!(ob.extract::<Vec<String>>().is_err());\n            assert!(ob.extract::<Vec<char>>().is_err());\n        });\n    }\n\n    #[test]\n    fn test_extract_bytes_to_vec() {\n        Python::attach(|py| {\n            let v: Vec<u8> = PyBytes::new(py, b\"abc\").extract().unwrap();\n            assert_eq!(v, b\"abc\");\n        });\n    }\n\n    #[test]\n    fn test_extract_tuple_to_vec() {\n        Python::attach(|py| {\n            let v: Vec<i32> = py.eval(c\"(1, 2)\", None, None).unwrap().extract().unwrap();\n            assert_eq!(v, [1, 2]);\n        });\n    }\n\n    #[test]\n    fn test_extract_range_to_vec() {\n        Python::attach(|py| {\n            let v: Vec<i32> = py\n                .eval(c\"range(1, 5)\", None, None)\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(v, [1, 2, 3, 4]);\n        });\n    }\n\n    #[test]\n    fn test_extract_bytearray_to_vec() {\n        Python::attach(|py| {\n            let v: Vec<u8> = py\n                .eval(c\"bytearray(b'abc')\", None, None)\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(v, b\"abc\");\n        });\n    }\n}\n"
  },
  {
    "path": "src/conversions/time.rs",
    "content": "#![cfg(feature = \"time\")]\n\n//! Conversions to and from [time](https://docs.rs/time/)’s `Date`,\n//! `Duration`, `OffsetDateTime`, `PrimitiveDateTime`, `Time`, `UtcDateTime` and `UtcOffset`.\n//!\n//! # Setup\n//!\n//! To use this feature, add this to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n//! time = \"0.3\"\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"time\\\"] }\")]\n//! ```\n//!\n//! Note that you must use compatible versions of time and PyO3.\n//! The required time version may vary based on the version of PyO3.\n//!\n//! ```rust\n//! use time::{Duration, OffsetDateTime, PrimitiveDateTime, Date, Time, Month};\n//! use pyo3::{Python, PyResult, IntoPyObject, types::PyAnyMethods};\n//!\n//! fn main() -> PyResult<()> {\n//!     Python::initialize();\n//!     Python::attach(|py| {\n//!         // Create a fixed date and time (2022-01-01 12:00:00 UTC)\n//!         let date = Date::from_calendar_date(2022, Month::January, 1).unwrap();\n//!         let time = Time::from_hms(12, 0, 0).unwrap();\n//!         let primitive_dt = PrimitiveDateTime::new(date, time);\n//!\n//!         // Convert to OffsetDateTime with UTC offset\n//!         let datetime = primitive_dt.assume_utc();\n//!\n//!         // Create a duration of 1 hour\n//!         let duration = Duration::hours(1);\n//!\n//!         // Convert to Python objects\n//!         let py_datetime = datetime.into_pyobject(py)?;\n//!         let py_timedelta = duration.into_pyobject(py)?;\n//!\n//!         // Add the duration to the datetime in Python\n//!         let py_result = py_datetime.add(py_timedelta)?;\n//!\n//!         // Convert the result back to Rust\n//!         let result: OffsetDateTime = py_result.extract()?;\n//!         assert_eq!(result.hour(), 13);\n//!\n//!         Ok(())\n//!     })\n//! }\n//! ```\n\nuse crate::exceptions::{PyTypeError, PyValueError};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(Py_LIMITED_API)]\nuse crate::intern;\n#[cfg(not(Py_LIMITED_API))]\nuse crate::types::datetime::{PyDateAccess, PyDeltaAccess};\nuse crate::types::{PyAnyMethods, PyDate, PyDateTime, PyDelta, PyNone, PyTime, PyTzInfo};\n#[cfg(not(Py_LIMITED_API))]\nuse crate::types::{PyTimeAccess, PyTzInfoAccess};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::{type_hint_identifier, PyTypeInfo};\nuse crate::{Borrowed, Bound, FromPyObject, IntoPyObject, PyAny, PyErr, PyResult, Python};\nuse time::{\n    Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcDateTime, UtcOffset,\n};\n\nconst SECONDS_PER_DAY: i64 = 86_400;\n\n// Macro for reference implementation\nmacro_rules! impl_into_py_for_ref {\n    ($type:ty, $target:ty) => {\n        impl<'py> IntoPyObject<'py> for &$type {\n            type Target = $target;\n            type Output = Bound<'py, Self::Target>;\n            type Error = PyErr;\n\n            #[cfg(feature = \"experimental-inspect\")]\n            const OUTPUT_TYPE: PyStaticExpr = <$type>::OUTPUT_TYPE;\n\n            #[inline]\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                (*self).into_pyobject(py)\n            }\n        }\n    };\n}\n\n// Macro for month conversion\nmacro_rules! month_from_number {\n    ($month:expr) => {\n        match $month {\n            1 => Month::January,\n            2 => Month::February,\n            3 => Month::March,\n            4 => Month::April,\n            5 => Month::May,\n            6 => Month::June,\n            7 => Month::July,\n            8 => Month::August,\n            9 => Month::September,\n            10 => Month::October,\n            11 => Month::November,\n            12 => Month::December,\n            _ => return Err(PyValueError::new_err(\"invalid month value\")),\n        }\n    };\n}\n\nfn extract_date_time(dt: &Bound<'_, PyAny>) -> PyResult<(Date, Time)> {\n    #[cfg(not(Py_LIMITED_API))]\n    {\n        let dt = dt.cast::<PyDateTime>()?;\n        let date = Date::from_calendar_date(\n            dt.get_year(),\n            month_from_number!(dt.get_month()),\n            dt.get_day(),\n        )\n        .map_err(|_| PyValueError::new_err(\"invalid or out-of-range date\"))?;\n\n        let time = Time::from_hms_micro(\n            dt.get_hour(),\n            dt.get_minute(),\n            dt.get_second(),\n            dt.get_microsecond(),\n        )\n        .map_err(|_| PyValueError::new_err(\"invalid or out-of-range time\"))?;\n        Ok((date, time))\n    }\n\n    #[cfg(Py_LIMITED_API)]\n    {\n        let date = Date::from_calendar_date(\n            dt.getattr(intern!(dt.py(), \"year\"))?.extract()?,\n            month_from_number!(dt.getattr(intern!(dt.py(), \"month\"))?.extract::<u8>()?),\n            dt.getattr(intern!(dt.py(), \"day\"))?.extract()?,\n        )\n        .map_err(|_| PyValueError::new_err(\"invalid or out-of-range date\"))?;\n\n        let time = Time::from_hms_micro(\n            dt.getattr(intern!(dt.py(), \"hour\"))?.extract()?,\n            dt.getattr(intern!(dt.py(), \"minute\"))?.extract()?,\n            dt.getattr(intern!(dt.py(), \"second\"))?.extract()?,\n            dt.getattr(intern!(dt.py(), \"microsecond\"))?.extract()?,\n        )\n        .map_err(|_| PyValueError::new_err(\"invalid or out-of-range time\"))?;\n\n        Ok((date, time))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Duration {\n    type Target = PyDelta;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDelta::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let total_seconds = self.whole_seconds();\n        let micro_seconds = self.subsec_microseconds();\n\n        // For negative durations, Python expects days to be negative and\n        // seconds/microseconds to be positive or zero\n        let (days, seconds) = if total_seconds < 0 && total_seconds % SECONDS_PER_DAY != 0 {\n            // For negative values, we need to round down (toward more negative)\n            // e.g., -10 seconds should be -1 days + 86390 seconds\n            let days = total_seconds.div_euclid(SECONDS_PER_DAY);\n            let seconds = total_seconds.rem_euclid(SECONDS_PER_DAY);\n            (days, seconds)\n        } else {\n            // For positive or exact negative days, use normal division\n            (\n                total_seconds / SECONDS_PER_DAY,\n                total_seconds % SECONDS_PER_DAY,\n            )\n        };\n        // Create the timedelta with days, seconds, microseconds\n        // Safe to unwrap as we've verified the values are within bounds\n        PyDelta::new(\n            py,\n            days.try_into().expect(\"days overflow\"),\n            seconds.try_into().expect(\"seconds overflow\"),\n            micro_seconds,\n            true,\n        )\n    }\n}\n\nimpl FromPyObject<'_, '_> for Duration {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDelta::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        #[cfg(not(Py_LIMITED_API))]\n        let (days, seconds, microseconds) = {\n            let delta = ob.cast::<PyDelta>()?;\n            (\n                delta.get_days().into(),\n                delta.get_seconds().into(),\n                delta.get_microseconds().into(),\n            )\n        };\n\n        #[cfg(Py_LIMITED_API)]\n        let (days, seconds, microseconds) = {\n            (\n                ob.getattr(intern!(ob.py(), \"days\"))?.extract()?,\n                ob.getattr(intern!(ob.py(), \"seconds\"))?.extract()?,\n                ob.getattr(intern!(ob.py(), \"microseconds\"))?.extract()?,\n            )\n        };\n\n        Ok(\n            Duration::days(days)\n                + Duration::seconds(seconds)\n                + Duration::microseconds(microseconds),\n        )\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Date {\n    type Target = PyDate;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDate::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let year = self.year();\n        let month = self.month() as u8;\n        let day = self.day();\n\n        PyDate::new(py, year, month, day)\n    }\n}\n\nimpl FromPyObject<'_, '_> for Date {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDate::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let (year, month, day) = {\n            #[cfg(not(Py_LIMITED_API))]\n            {\n                let date = ob.cast::<PyDate>()?;\n                (date.get_year(), date.get_month(), date.get_day())\n            }\n\n            #[cfg(Py_LIMITED_API)]\n            {\n                let year = ob.getattr(intern!(ob.py(), \"year\"))?.extract()?;\n                let month: u8 = ob.getattr(intern!(ob.py(), \"month\"))?.extract()?;\n                let day = ob.getattr(intern!(ob.py(), \"day\"))?.extract()?;\n                (year, month, day)\n            }\n        };\n\n        // Convert the month number to time::Month enum\n        let month = month_from_number!(month);\n\n        Date::from_calendar_date(year, month, day)\n            .map_err(|_| PyValueError::new_err(\"invalid or out-of-range date\"))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Time {\n    type Target = PyTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyTime::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let hour = self.hour();\n        let minute = self.minute();\n        let second = self.second();\n        let microsecond = self.microsecond();\n\n        PyTime::new(py, hour, minute, second, microsecond, None)\n    }\n}\n\nimpl FromPyObject<'_, '_> for Time {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyTime::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let (hour, minute, second, microsecond) = {\n            #[cfg(not(Py_LIMITED_API))]\n            {\n                let time = ob.cast::<PyTime>()?;\n                let hour: u8 = time.get_hour();\n                let minute: u8 = time.get_minute();\n                let second: u8 = time.get_second();\n                let microsecond = time.get_microsecond();\n                (hour, minute, second, microsecond)\n            }\n\n            #[cfg(Py_LIMITED_API)]\n            {\n                let hour: u8 = ob.getattr(intern!(ob.py(), \"hour\"))?.extract()?;\n                let minute: u8 = ob.getattr(intern!(ob.py(), \"minute\"))?.extract()?;\n                let second: u8 = ob.getattr(intern!(ob.py(), \"second\"))?.extract()?;\n                let microsecond = ob.getattr(intern!(ob.py(), \"microsecond\"))?.extract()?;\n                (hour, minute, second, microsecond)\n            }\n        };\n\n        Time::from_hms_micro(hour, minute, second, microsecond)\n            .map_err(|_| PyValueError::new_err(\"invalid or out-of-range time\"))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for PrimitiveDateTime {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let date = self.date();\n        let time = self.time();\n\n        let year = date.year();\n        let month = date.month() as u8;\n        let day = date.day();\n        let hour = time.hour();\n        let minute = time.minute();\n        let second = time.second();\n        let microsecond = time.microsecond();\n\n        PyDateTime::new(\n            py,\n            year,\n            month,\n            day,\n            hour,\n            minute,\n            second,\n            microsecond,\n            None,\n        )\n    }\n}\n\nimpl FromPyObject<'_, '_> for PrimitiveDateTime {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn extract(dt: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let has_tzinfo = {\n            #[cfg(not(Py_LIMITED_API))]\n            {\n                let dt = dt.cast::<PyDateTime>()?;\n                dt.get_tzinfo().is_some()\n            }\n            #[cfg(Py_LIMITED_API)]\n            {\n                !dt.getattr(intern!(dt.py(), \"tzinfo\"))?.is_none()\n            }\n        };\n\n        if has_tzinfo {\n            return Err(PyTypeError::new_err(\"expected a datetime without tzinfo\"));\n        }\n\n        let (date, time) = extract_date_time(&dt)?;\n\n        Ok(PrimitiveDateTime::new(date, time))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for UtcOffset {\n    type Target = PyTzInfo;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"datetime\", \"timezone\");\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        // Get offset in seconds\n        let seconds_offset = self.whole_seconds();\n        let td = PyDelta::new(py, 0, seconds_offset, 0, true)?;\n        PyTzInfo::fixed_offset(py, td)\n    }\n}\n\nimpl FromPyObject<'_, '_> for UtcOffset {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyTzInfo::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        #[cfg(not(Py_LIMITED_API))]\n        let ob = ob.cast::<PyTzInfo>()?;\n\n        // Get the offset in seconds from the Python tzinfo\n        let py_timedelta = ob.call_method1(\"utcoffset\", (PyNone::get(ob.py()),))?;\n        if py_timedelta.is_none() {\n            return Err(PyTypeError::new_err(format!(\n                \"{ob:?} is not a fixed offset timezone\"\n            )));\n        }\n\n        let total_seconds: Duration = py_timedelta.extract()?;\n        let seconds = total_seconds.whole_seconds();\n\n        // Create the UtcOffset from the seconds\n        UtcOffset::from_whole_seconds(seconds as i32)\n            .map_err(|_| PyValueError::new_err(\"UTC offset out of bounds\"))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for OffsetDateTime {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let date = self.date();\n        let time = self.time();\n        let offset = self.offset();\n\n        // Convert the offset to a Python tzinfo\n        let py_tzinfo = offset.into_pyobject(py)?;\n\n        let year = date.year();\n        let month = date.month() as u8;\n        let day = date.day();\n        let hour = time.hour();\n        let minute = time.minute();\n        let second = time.second();\n        let microsecond = time.microsecond();\n\n        PyDateTime::new(\n            py,\n            year,\n            month,\n            day,\n            hour,\n            minute,\n            second,\n            microsecond,\n            Some(py_tzinfo.cast()?),\n        )\n    }\n}\n\nimpl FromPyObject<'_, '_> for OffsetDateTime {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let offset: UtcOffset = {\n            #[cfg(not(Py_LIMITED_API))]\n            {\n                let dt = ob.cast::<PyDateTime>()?;\n                let tzinfo = dt.get_tzinfo().ok_or_else(|| {\n                    PyTypeError::new_err(\"expected a datetime with non-None tzinfo\")\n                })?;\n                tzinfo.extract()?\n            }\n            #[cfg(Py_LIMITED_API)]\n            {\n                let tzinfo = ob.getattr(intern!(ob.py(), \"tzinfo\"))?;\n                if tzinfo.is_none() {\n                    return Err(PyTypeError::new_err(\n                        \"expected a datetime with non-None tzinfo\",\n                    ));\n                }\n                tzinfo.extract()?\n            }\n        };\n\n        let (date, time) = extract_date_time(&ob)?;\n\n        let primitive_dt = PrimitiveDateTime::new(date, time);\n        Ok(primitive_dt.assume_offset(offset))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for UtcDateTime {\n    type Target = PyDateTime;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let date = self.date();\n        let time = self.time();\n\n        let py_tzinfo = PyTzInfo::utc(py)?;\n\n        let year = date.year();\n        let month = date.month() as u8;\n        let day = date.day();\n        let hour = time.hour();\n        let minute = time.minute();\n        let second = time.second();\n        let microsecond = time.microsecond();\n\n        PyDateTime::new(\n            py,\n            year,\n            month,\n            day,\n            hour,\n            minute,\n            second,\n            microsecond,\n            Some(&py_tzinfo),\n        )\n    }\n}\n\nimpl FromPyObject<'_, '_> for UtcDateTime {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyDateTime::TYPE_HINT;\n\n    fn extract(ob: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let tzinfo = {\n            #[cfg(not(Py_LIMITED_API))]\n            {\n                let dt = ob.cast::<PyDateTime>()?;\n                dt.get_tzinfo().ok_or_else(|| {\n                    PyTypeError::new_err(\"expected a datetime with non-None tzinfo\")\n                })?\n            }\n\n            #[cfg(Py_LIMITED_API)]\n            {\n                let tzinfo = ob.getattr(intern!(ob.py(), \"tzinfo\"))?;\n                if tzinfo.is_none() {\n                    return Err(PyTypeError::new_err(\n                        \"expected a datetime with non-None tzinfo\",\n                    ));\n                }\n                tzinfo\n            }\n        };\n\n        // Verify that the tzinfo is UTC\n        let is_utc = tzinfo.eq(PyTzInfo::utc(ob.py())?)?;\n\n        if !is_utc {\n            return Err(PyValueError::new_err(\n                \"expected a datetime with UTC timezone\",\n            ));\n        }\n\n        let (date, time) = extract_date_time(&ob)?;\n        let primitive_dt = PrimitiveDateTime::new(date, time);\n        Ok(primitive_dt.assume_utc().into())\n    }\n}\n\nimpl_into_py_for_ref!(Duration, PyDelta);\nimpl_into_py_for_ref!(Date, PyDate);\nimpl_into_py_for_ref!(Time, PyTime);\nimpl_into_py_for_ref!(PrimitiveDateTime, PyDateTime);\nimpl_into_py_for_ref!(UtcOffset, PyTzInfo);\nimpl_into_py_for_ref!(OffsetDateTime, PyDateTime);\nimpl_into_py_for_ref!(UtcDateTime, PyDateTime);\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::intern;\n    use crate::types::any::PyAnyMethods;\n    use crate::types::PyTypeMethods;\n\n    mod utils {\n        use super::*;\n\n        pub(crate) fn extract_py_delta_from_duration(\n            duration: Duration,\n            py: Python<'_>,\n        ) -> (i64, i64, i64) {\n            let py_delta = duration.into_pyobject(py).unwrap();\n            let days = py_delta\n                .getattr(intern!(py, \"days\"))\n                .unwrap()\n                .extract::<i64>()\n                .unwrap();\n            let seconds = py_delta\n                .getattr(intern!(py, \"seconds\"))\n                .unwrap()\n                .extract::<i64>()\n                .unwrap();\n            let microseconds = py_delta\n                .getattr(intern!(py, \"microseconds\"))\n                .unwrap()\n                .extract::<i64>()\n                .unwrap();\n            (days, seconds, microseconds)\n        }\n\n        pub(crate) fn extract_py_date_from_date(date: Date, py: Python<'_>) -> (i32, u8, u8) {\n            let py_date = date.into_pyobject(py).unwrap();\n\n            // Check the Python object is correct\n            let year = py_date\n                .getattr(intern!(py, \"year\"))\n                .unwrap()\n                .extract::<i32>()\n                .unwrap();\n            let month = py_date\n                .getattr(intern!(py, \"month\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let day = py_date\n                .getattr(intern!(py, \"day\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            (year, month, day)\n        }\n\n        pub(crate) fn create_date_from_py_date(\n            py: Python<'_>,\n            year: i32,\n            month: u8,\n            day: u8,\n        ) -> PyResult<Date> {\n            let datetime = py.import(\"datetime\").unwrap();\n            let date_type = datetime.getattr(intern!(py, \"date\")).unwrap();\n            let py_date = date_type.call1((year, month, day));\n            match py_date {\n                Ok(py_date) => py_date.extract(),\n                Err(err) => Err(err),\n            }\n        }\n\n        pub(crate) fn create_time_from_py_time(\n            py: Python<'_>,\n            hour: u8,\n            minute: u8,\n            second: u8,\n            microseocnd: u32,\n        ) -> PyResult<Time> {\n            let datetime = py.import(\"datetime\").unwrap();\n            let time_type = datetime.getattr(intern!(py, \"time\")).unwrap();\n            let py_time = time_type.call1((hour, minute, second, microseocnd));\n            match py_time {\n                Ok(py_time) => py_time.extract(),\n                Err(err) => Err(err),\n            }\n        }\n\n        pub(crate) fn extract_py_time_from_time(time: Time, py: Python<'_>) -> (u8, u8, u8, u32) {\n            let py_time = time.into_pyobject(py).unwrap();\n            let hour = py_time\n                .getattr(intern!(py, \"hour\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let minute = py_time\n                .getattr(intern!(py, \"minute\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let second = py_time\n                .getattr(intern!(py, \"second\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let microsecond = py_time\n                .getattr(intern!(py, \"microsecond\"))\n                .unwrap()\n                .extract::<u32>()\n                .unwrap();\n            (hour, minute, second, microsecond)\n        }\n\n        pub(crate) fn extract_date_time_from_primitive_date_time(\n            dt: PrimitiveDateTime,\n            py: Python<'_>,\n        ) -> (u32, u8, u8, u8, u8, u8, u32) {\n            let py_dt = dt.into_pyobject(py).unwrap();\n            let year = py_dt\n                .getattr(intern!(py, \"year\"))\n                .unwrap()\n                .extract::<u32>()\n                .unwrap();\n            let month = py_dt\n                .getattr(intern!(py, \"month\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let day = py_dt\n                .getattr(intern!(py, \"day\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let hour = py_dt\n                .getattr(intern!(py, \"hour\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let minute = py_dt\n                .getattr(intern!(py, \"minute\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let second = py_dt\n                .getattr(intern!(py, \"second\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let microsecond = py_dt\n                .getattr(intern!(py, \"microsecond\"))\n                .unwrap()\n                .extract::<u32>()\n                .unwrap();\n            (year, month, day, hour, minute, second, microsecond)\n        }\n\n        #[expect(clippy::too_many_arguments)]\n        pub(crate) fn create_primitive_date_time_from_py(\n            py: Python<'_>,\n            year: u32,\n            month: u8,\n            day: u8,\n            hour: u8,\n            minute: u8,\n            second: u8,\n            microsecond: u32,\n        ) -> PyResult<PrimitiveDateTime> {\n            let datetime = py.import(\"datetime\").unwrap();\n            let datetime_type = datetime.getattr(intern!(py, \"datetime\")).unwrap();\n            let py_dt = datetime_type.call1((year, month, day, hour, minute, second, microsecond));\n            match py_dt {\n                Ok(py_dt) => py_dt.extract(),\n                Err(err) => Err(err),\n            }\n        }\n\n        pub(crate) fn extract_total_seconds_from_utcoffset(\n            offset: UtcOffset,\n            py: Python<'_>,\n        ) -> f64 {\n            let py_tz = offset.into_pyobject(py).unwrap();\n            let utc_offset = py_tz.call_method1(\"utcoffset\", (py.None(),)).unwrap();\n            let total_seconds = utc_offset\n                .getattr(intern!(py, \"total_seconds\"))\n                .unwrap()\n                .call0()\n                .unwrap()\n                .extract::<f64>()\n                .unwrap();\n            total_seconds\n        }\n\n        pub(crate) fn extract_from_utc_date_time(\n            dt: UtcDateTime,\n            py: Python<'_>,\n        ) -> (u32, u8, u8, u8, u8, u8, u32) {\n            let py_dt = dt.into_pyobject(py).unwrap();\n            let year = py_dt\n                .getattr(intern!(py, \"year\"))\n                .unwrap()\n                .extract::<u32>()\n                .unwrap();\n            let month = py_dt\n                .getattr(intern!(py, \"month\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let day = py_dt\n                .getattr(intern!(py, \"day\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let hour = py_dt\n                .getattr(intern!(py, \"hour\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let minute = py_dt\n                .getattr(intern!(py, \"minute\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let second = py_dt\n                .getattr(intern!(py, \"second\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let microsecond = py_dt\n                .getattr(intern!(py, \"microsecond\"))\n                .unwrap()\n                .extract::<u32>()\n                .unwrap();\n            (year, month, day, hour, minute, second, microsecond)\n        }\n    }\n    #[test]\n    fn test_time_duration_conversion() {\n        Python::attach(|py| {\n            // Regular duration\n            let duration = Duration::new(1, 500_000_000); // 1.5 seconds\n            let (_, seconds, microseconds) = utils::extract_py_delta_from_duration(duration, py);\n            assert_eq!(seconds, 1);\n            assert_eq!(microseconds, 500_000);\n\n            // Check negative durations\n            let neg_duration = Duration::new(-10, 0); // -10 seconds\n            let (days, seconds, _) = utils::extract_py_delta_from_duration(neg_duration, py);\n            assert_eq!(days, -1);\n            assert_eq!(seconds, 86390); // 86400 - 10 seconds\n\n            // Test case for exact negative days (should use normal division path)\n            let exact_day = Duration::seconds(-86_400); // Exactly -1 day\n            let (days, seconds, microseconds) =\n                utils::extract_py_delta_from_duration(exact_day, py);\n            assert_eq!(days, -1);\n            assert_eq!(seconds, 0);\n            assert_eq!(microseconds, 0);\n        });\n    }\n\n    #[test]\n    fn test_time_duration_conversion_large_values() {\n        Python::attach(|py| {\n            // Large duration (close to max)\n            let large_duration = Duration::seconds(86_399_999_000_000); // Almost max\n            let (days, _, _) = utils::extract_py_delta_from_duration(large_duration, py);\n            assert!(days > 999_000_000);\n\n            // Test over limit (should yield Overflow error in python)\n            let too_large = Duration::seconds(86_400_000_000_000); // Over max\n            let result = too_large.into_pyobject(py);\n            assert!(result.is_err());\n            let err_type = result.unwrap_err().get_type(py).name().unwrap();\n            assert_eq!(err_type, \"OverflowError\");\n        });\n    }\n\n    #[test]\n    fn test_time_duration_nanosecond_resolution() {\n        Python::attach(|py| {\n            // Test nanosecond conversion to microseconds\n            let duration = Duration::new(0, 1_234_567);\n            let (_, _, microseconds) = utils::extract_py_delta_from_duration(duration, py);\n            // Python timedelta only has microsecond resolution, so we should get 1234 microseconds\n            assert_eq!(microseconds, 1234);\n        });\n    }\n\n    #[test]\n    fn test_time_duration_from_python() {\n        Python::attach(|py| {\n            // Create Python timedeltas with various values\n            let datetime = py.import(\"datetime\").unwrap();\n            let timedelta = datetime.getattr(intern!(py, \"timedelta\")).unwrap();\n\n            // Test positive values\n            let py_delta1 = timedelta.call1((3, 7200, 500000)).unwrap();\n            let duration1: Duration = py_delta1.extract().unwrap();\n            assert_eq!(duration1.whole_days(), 3);\n            assert_eq!(duration1.whole_seconds() % 86400, 7200);\n            assert_eq!(duration1.subsec_nanoseconds(), 500000000);\n\n            // Test negative days\n            let py_delta2 = timedelta.call1((-2, 43200)).unwrap();\n            let duration2: Duration = py_delta2.extract().unwrap();\n            assert_eq!(duration2.whole_days(), -1);\n            assert_eq!(duration2.whole_seconds(), -129600);\n        });\n    }\n\n    #[test]\n    fn test_time_date_conversion() {\n        Python::attach(|py| {\n            // Regular date\n            let date = Date::from_calendar_date(2023, Month::April, 15).unwrap();\n            let (year, month, day) = utils::extract_py_date_from_date(date, py);\n            assert_eq!(year, 2023);\n            assert_eq!(month, 4);\n            assert_eq!(day, 15);\n\n            // Test edge cases\n            let min_date = Date::from_calendar_date(1, Month::January, 1).unwrap();\n            let (min_year, min_month, min_day) = utils::extract_py_date_from_date(min_date, py);\n            assert_eq!(min_year, 1);\n            assert_eq!(min_month, 1);\n            assert_eq!(min_day, 1);\n\n            let max_date = Date::from_calendar_date(9999, Month::December, 31).unwrap();\n            let (max_year, max_month, max_day) = utils::extract_py_date_from_date(max_date, py);\n            assert_eq!(max_year, 9999);\n            assert_eq!(max_month, 12);\n            assert_eq!(max_day, 31);\n        });\n    }\n\n    #[test]\n    fn test_time_date_from_python() {\n        Python::attach(|py| {\n            let date1 = utils::create_date_from_py_date(py, 2023, 4, 15).unwrap();\n            assert_eq!(date1.year(), 2023);\n            assert_eq!(date1.month(), Month::April);\n            assert_eq!(date1.day(), 15);\n\n            // Test min date\n            let date2 = utils::create_date_from_py_date(py, 1, 1, 1).unwrap();\n            assert_eq!(date2.year(), 1);\n            assert_eq!(date2.month(), Month::January);\n            assert_eq!(date2.day(), 1);\n\n            // Test max date\n            let date3 = utils::create_date_from_py_date(py, 9999, 12, 31).unwrap();\n            assert_eq!(date3.year(), 9999);\n            assert_eq!(date3.month(), Month::December);\n            assert_eq!(date3.day(), 31);\n\n            // Test leap year date\n            let date4 = utils::create_date_from_py_date(py, 2024, 2, 29).unwrap();\n            assert_eq!(date4.year(), 2024);\n            assert_eq!(date4.month(), Month::February);\n            assert_eq!(date4.day(), 29);\n        });\n    }\n\n    #[test]\n    fn test_time_date_invalid_values() {\n        Python::attach(|py| {\n            let invalid_date = utils::create_date_from_py_date(py, 2023, 2, 30);\n            assert!(invalid_date.is_err());\n\n            // Test extraction of invalid month\n            let another_invalid_date = utils::create_date_from_py_date(py, 2023, 13, 1);\n            assert!(another_invalid_date.is_err());\n        });\n    }\n\n    #[test]\n    fn test_time_time_conversion() {\n        Python::attach(|py| {\n            // Regular time\n            let time = Time::from_hms_micro(14, 30, 45, 123456).unwrap();\n            let (hour, minute, second, microsecond) = utils::extract_py_time_from_time(time, py);\n            assert_eq!(hour, 14);\n            assert_eq!(minute, 30);\n            assert_eq!(second, 45);\n            assert_eq!(microsecond, 123456);\n\n            // Test edge cases\n            let min_time = Time::from_hms_micro(0, 0, 0, 0).unwrap();\n            let (min_hour, min_minute, min_second, min_microsecond) =\n                utils::extract_py_time_from_time(min_time, py);\n            assert_eq!(min_hour, 0);\n            assert_eq!(min_minute, 0);\n            assert_eq!(min_second, 0);\n            assert_eq!(min_microsecond, 0);\n\n            let max_time = Time::from_hms_micro(23, 59, 59, 999999).unwrap();\n            let (max_hour, max_minute, max_second, max_microsecond) =\n                utils::extract_py_time_from_time(max_time, py);\n            assert_eq!(max_hour, 23);\n            assert_eq!(max_minute, 59);\n            assert_eq!(max_second, 59);\n            assert_eq!(max_microsecond, 999999);\n        });\n    }\n\n    #[test]\n    fn test_time_time_from_python() {\n        Python::attach(|py| {\n            let time1 = utils::create_time_from_py_time(py, 14, 30, 45, 123456).unwrap();\n            assert_eq!(time1.hour(), 14);\n            assert_eq!(time1.minute(), 30);\n            assert_eq!(time1.second(), 45);\n            assert_eq!(time1.microsecond(), 123456);\n\n            // Test min time\n            let time2 = utils::create_time_from_py_time(py, 0, 0, 0, 0).unwrap();\n            assert_eq!(time2.hour(), 0);\n            assert_eq!(time2.minute(), 0);\n            assert_eq!(time2.second(), 0);\n            assert_eq!(time2.microsecond(), 0);\n\n            // Test max time\n            let time3 = utils::create_time_from_py_time(py, 23, 59, 59, 999999).unwrap();\n            assert_eq!(time3.hour(), 23);\n            assert_eq!(time3.minute(), 59);\n            assert_eq!(time3.second(), 59);\n            assert_eq!(time3.microsecond(), 999999);\n        });\n    }\n\n    #[test]\n    fn test_time_time_invalid_values() {\n        Python::attach(|py| {\n            let result = utils::create_time_from_py_time(py, 24, 0, 0, 0);\n            assert!(result.is_err());\n            let result = utils::create_time_from_py_time(py, 12, 60, 0, 0);\n            assert!(result.is_err());\n            let result = utils::create_time_from_py_time(py, 12, 30, 60, 0);\n            assert!(result.is_err());\n            let result = utils::create_time_from_py_time(py, 12, 30, 30, 1000000);\n            assert!(result.is_err());\n        });\n    }\n\n    #[test]\n    fn test_time_time_with_timezone() {\n        Python::attach(|py| {\n            // Create Python time with timezone (just to ensure we can handle it properly)\n            let datetime = py.import(\"datetime\").unwrap();\n            let time_type = datetime.getattr(intern!(py, \"time\")).unwrap();\n            let tz_utc = PyTzInfo::utc(py).unwrap();\n\n            // Create time with timezone\n            let py_time_with_tz = time_type.call1((12, 30, 45, 0, tz_utc)).unwrap();\n            let time: Time = py_time_with_tz.extract().unwrap();\n\n            assert_eq!(time.hour(), 12);\n            assert_eq!(time.minute(), 30);\n            assert_eq!(time.second(), 45);\n        });\n    }\n\n    #[test]\n    fn test_time_primitive_datetime_conversion() {\n        Python::attach(|py| {\n            // Regular datetime\n            let date = Date::from_calendar_date(2023, Month::April, 15).unwrap();\n            let time = Time::from_hms_micro(14, 30, 45, 123456).unwrap();\n            let dt = PrimitiveDateTime::new(date, time);\n            let (year, month, day, hour, minute, second, microsecond) =\n                utils::extract_date_time_from_primitive_date_time(dt, py);\n\n            assert_eq!(year, 2023);\n            assert_eq!(month, 4);\n            assert_eq!(day, 15);\n            assert_eq!(hour, 14);\n            assert_eq!(minute, 30);\n            assert_eq!(second, 45);\n            assert_eq!(microsecond, 123456);\n\n            // Test min datetime\n            let min_date = Date::from_calendar_date(1, Month::January, 1).unwrap();\n            let min_time = Time::from_hms_micro(0, 0, 0, 0).unwrap();\n            let min_dt = PrimitiveDateTime::new(min_date, min_time);\n            let (year, month, day, hour, minute, second, microsecond) =\n                utils::extract_date_time_from_primitive_date_time(min_dt, py);\n            assert_eq!(year, 1);\n            assert_eq!(month, 1);\n            assert_eq!(day, 1);\n            assert_eq!(hour, 0);\n            assert_eq!(minute, 0);\n            assert_eq!(second, 0);\n            assert_eq!(microsecond, 0);\n        });\n    }\n\n    #[test]\n    fn test_time_primitive_datetime_from_python() {\n        Python::attach(|py| {\n            let dt1 =\n                utils::create_primitive_date_time_from_py(py, 2023, 4, 15, 14, 30, 45, 123456)\n                    .unwrap();\n            assert_eq!(dt1.year(), 2023);\n            assert_eq!(dt1.month(), Month::April);\n            assert_eq!(dt1.day(), 15);\n            assert_eq!(dt1.hour(), 14);\n            assert_eq!(dt1.minute(), 30);\n            assert_eq!(dt1.second(), 45);\n            assert_eq!(dt1.microsecond(), 123456);\n\n            let dt2 = utils::create_primitive_date_time_from_py(py, 1, 1, 1, 0, 0, 0, 0).unwrap();\n            assert_eq!(dt2.year(), 1);\n            assert_eq!(dt2.month(), Month::January);\n            assert_eq!(dt2.day(), 1);\n            assert_eq!(dt2.hour(), 0);\n            assert_eq!(dt2.minute(), 0);\n        });\n    }\n\n    #[test]\n    fn test_time_utc_offset_conversion() {\n        Python::attach(|py| {\n            // Test positive offset\n            let offset = UtcOffset::from_hms(5, 30, 0).unwrap();\n            let total_seconds = utils::extract_total_seconds_from_utcoffset(offset, py);\n            assert_eq!(total_seconds, 5.0 * 3600.0 + 30.0 * 60.0);\n\n            // Test negative offset\n            let neg_offset = UtcOffset::from_hms(-8, -15, 0).unwrap();\n            let neg_total_seconds = utils::extract_total_seconds_from_utcoffset(neg_offset, py);\n            assert_eq!(neg_total_seconds, -8.0 * 3600.0 - 15.0 * 60.0);\n        });\n    }\n\n    #[test]\n    fn test_time_utc_offset_from_python() {\n        Python::attach(|py| {\n            // Create timezone objects\n            let datetime = py.import(\"datetime\").unwrap();\n            let timezone = datetime.getattr(intern!(py, \"timezone\")).unwrap();\n            let timedelta = datetime.getattr(intern!(py, \"timedelta\")).unwrap();\n\n            // Test UTC\n            let tz_utc = PyTzInfo::utc(py).unwrap();\n            let utc_offset: UtcOffset = tz_utc.extract().unwrap();\n            assert_eq!(utc_offset.whole_hours(), 0);\n            assert_eq!(utc_offset.minutes_past_hour(), 0);\n            assert_eq!(utc_offset.seconds_past_minute(), 0);\n\n            // Test positive offset\n            let td_pos = timedelta.call1((0, 19800, 0)).unwrap(); // 5 hours 30 minutes\n            let tz_pos = timezone.call1((td_pos,)).unwrap();\n            let offset_pos: UtcOffset = tz_pos.extract().unwrap();\n            assert_eq!(offset_pos.whole_hours(), 5);\n            assert_eq!(offset_pos.minutes_past_hour(), 30);\n\n            // Test negative offset\n            let td_neg = timedelta.call1((0, -30900, 0)).unwrap(); // -8 hours -35 minutes\n            let tz_neg = timezone.call1((td_neg,)).unwrap();\n            let offset_neg: UtcOffset = tz_neg.extract().unwrap();\n            assert_eq!(offset_neg.whole_hours(), -8);\n            assert_eq!(offset_neg.minutes_past_hour(), -35);\n        });\n    }\n\n    #[test]\n    fn test_time_offset_datetime_conversion() {\n        Python::attach(|py| {\n            // Create an OffsetDateTime with +5:30 offset\n            let date = Date::from_calendar_date(2023, Month::April, 15).unwrap();\n            let time = Time::from_hms_micro(14, 30, 45, 123456).unwrap();\n            let offset = UtcOffset::from_hms(5, 30, 0).unwrap();\n            let dt = PrimitiveDateTime::new(date, time).assume_offset(offset);\n\n            // Convert to Python\n            let py_dt = dt.into_pyobject(py).unwrap();\n\n            // Check components\n            let year = py_dt\n                .getattr(intern!(py, \"year\"))\n                .unwrap()\n                .extract::<i32>()\n                .unwrap();\n            let month = py_dt\n                .getattr(intern!(py, \"month\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let day = py_dt\n                .getattr(intern!(py, \"day\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let hour = py_dt\n                .getattr(intern!(py, \"hour\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let minute = py_dt\n                .getattr(intern!(py, \"minute\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let second = py_dt\n                .getattr(intern!(py, \"second\"))\n                .unwrap()\n                .extract::<u8>()\n                .unwrap();\n            let microsecond = py_dt\n                .getattr(intern!(py, \"microsecond\"))\n                .unwrap()\n                .extract::<u32>()\n                .unwrap();\n\n            assert_eq!(year, 2023);\n            assert_eq!(month, 4);\n            assert_eq!(day, 15);\n            assert_eq!(hour, 14);\n            assert_eq!(minute, 30);\n            assert_eq!(second, 45);\n            assert_eq!(microsecond, 123456);\n\n            // Check timezone offset\n            let tzinfo = py_dt.getattr(intern!(py, \"tzinfo\")).unwrap();\n            let utcoffset = tzinfo.call_method1(\"utcoffset\", (py_dt,)).unwrap();\n            let seconds = utcoffset\n                .call_method0(\"total_seconds\")\n                .unwrap()\n                .extract::<f64>()\n                .unwrap();\n            assert_eq!(seconds, 5.0 * 3600.0 + 30.0 * 60.0);\n        });\n    }\n\n    #[test]\n    fn test_time_offset_datetime_from_python() {\n        Python::attach(|py| {\n            // Create Python datetime with timezone\n            let datetime = py.import(\"datetime\").unwrap();\n            let datetime_type = datetime.getattr(intern!(py, \"datetime\")).unwrap();\n            let timezone = datetime.getattr(intern!(py, \"timezone\")).unwrap();\n            let timedelta = datetime.getattr(intern!(py, \"timedelta\")).unwrap();\n\n            // Create a timezone (+5:30)\n            let td = timedelta.call1((0, 19800, 0)).unwrap(); // 5:30:00\n            let tz = timezone.call1((td,)).unwrap();\n\n            // Create datetime with this timezone\n            let py_dt = datetime_type\n                .call1((2023, 4, 15, 14, 30, 45, 123456, tz))\n                .unwrap();\n\n            // Extract to Rust\n            let dt: OffsetDateTime = py_dt.extract().unwrap();\n\n            // Verify components\n            assert_eq!(dt.year(), 2023);\n            assert_eq!(dt.month(), Month::April);\n            assert_eq!(dt.day(), 15);\n            assert_eq!(dt.hour(), 14);\n            assert_eq!(dt.minute(), 30);\n            assert_eq!(dt.second(), 45);\n            assert_eq!(dt.microsecond(), 123456);\n            assert_eq!(dt.offset().whole_hours(), 5);\n            assert_eq!(dt.offset().minutes_past_hour(), 30);\n        });\n    }\n\n    #[test]\n    fn test_time_utc_datetime_conversion() {\n        Python::attach(|py| {\n            let date = Date::from_calendar_date(2023, Month::April, 15).unwrap();\n            let time = Time::from_hms_micro(14, 30, 45, 123456).unwrap();\n            let primitive_dt = PrimitiveDateTime::new(date, time);\n            let dt: UtcDateTime = primitive_dt.assume_utc().into();\n            let (year, month, day, hour, minute, second, microsecond) =\n                utils::extract_from_utc_date_time(dt, py);\n\n            assert_eq!(year, 2023);\n            assert_eq!(month, 4);\n            assert_eq!(day, 15);\n            assert_eq!(hour, 14);\n            assert_eq!(minute, 30);\n            assert_eq!(second, 45);\n            assert_eq!(microsecond, 123456);\n        });\n    }\n\n    #[test]\n    fn test_time_utc_datetime_from_python() {\n        Python::attach(|py| {\n            // Create Python UTC datetime\n            let datetime = py.import(\"datetime\").unwrap();\n            let datetime_type = datetime.getattr(intern!(py, \"datetime\")).unwrap();\n            let tz_utc = PyTzInfo::utc(py).unwrap();\n\n            // Create datetime with UTC timezone\n            let py_dt = datetime_type\n                .call1((2023, 4, 15, 14, 30, 45, 123456, tz_utc))\n                .unwrap();\n\n            // Convert to Rust\n            let dt: UtcDateTime = py_dt.extract().unwrap();\n\n            // Verify components\n            assert_eq!(dt.year(), 2023);\n            assert_eq!(dt.month(), Month::April);\n            assert_eq!(dt.day(), 15);\n            assert_eq!(dt.hour(), 14);\n            assert_eq!(dt.minute(), 30);\n            assert_eq!(dt.second(), 45);\n            assert_eq!(dt.microsecond(), 123456);\n        });\n    }\n\n    #[test]\n    fn test_time_utc_datetime_non_utc_timezone() {\n        Python::attach(|py| {\n            // Create Python datetime with non-UTC timezone\n            let datetime = py.import(\"datetime\").unwrap();\n            let datetime_type = datetime.getattr(intern!(py, \"datetime\")).unwrap();\n            let timezone = datetime.getattr(intern!(py, \"timezone\")).unwrap();\n            let timedelta = datetime.getattr(intern!(py, \"timedelta\")).unwrap();\n\n            // Create a non-UTC timezone (EST = UTC-5)\n            let td = timedelta.call1((0, -18000, 0)).unwrap(); // -5 hours\n            let tz_est = timezone.call1((td,)).unwrap();\n\n            // Create datetime with EST timezone\n            let py_dt = datetime_type\n                .call1((2023, 4, 15, 14, 30, 45, 123456, tz_est))\n                .unwrap();\n\n            // Try to convert to UtcDateTime - should fail\n            let result: Result<UtcDateTime, _> = py_dt.extract();\n            assert!(result.is_err());\n        });\n    }\n\n    #[cfg(not(any(target_arch = \"wasm32\", Py_GIL_DISABLED)))]\n    mod proptests {\n        use super::*;\n        use proptest::proptest;\n\n        proptest! {\n            #[test]\n            fn test_time_duration_roundtrip(days in -9999i64..=9999i64, seconds in -86399i64..=86399i64, microseconds in -999999i64..=999999i64) {\n                // Generate a valid duration that should roundtrip successfully\n                Python::attach(|py| {\n                    let duration = Duration::days(days) + Duration::seconds(seconds) + Duration::microseconds(microseconds);\n\n                    // Skip if outside Python's timedelta bounds\n                    let max_seconds = 86_399_999_913_600;\n                    if duration.whole_seconds() <= max_seconds && duration.whole_seconds() >= -max_seconds {\n                        let py_delta = duration.into_pyobject(py).unwrap();\n\n                        // You could add FromPyObject for Duration to fully test the roundtrip\n                        // For now we'll just check that the Python object has the expected properties\n                        let total_seconds = py_delta.call_method0(intern!(py, \"total_seconds\")).unwrap().extract::<f64>().unwrap();\n                        let expected_seconds = duration.whole_seconds() as f64 + (duration.subsec_nanoseconds() as f64 / 1_000_000_000.0);\n\n                        // Allow small floating point differences\n                        assert_eq!(total_seconds, expected_seconds);\n                    }\n                })\n            }\n\n            #[test]\n            fn test_all_valid_dates(\n                year in 1i32..=9999,\n                month_num in 1u8..=12,\n            ) {\n                Python::attach(|py| {\n                    let month = match month_num {\n                        1 => (Month::January, 31),\n                        2 => {\n                            // Handle leap years\n                            if (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0) {\n                                (Month::February, 29)\n                            } else {\n                                (Month::February, 28)\n                            }\n                        },\n                        3 => (Month::March, 31),\n                        4 => (Month::April, 30),\n                        5 => (Month::May, 31),\n                        6 => (Month::June, 30),\n                        7 => (Month::July, 31),\n                        8 => (Month::August, 31),\n                        9 => (Month::September, 30),\n                        10 => (Month::October, 31),\n                        11 => (Month::November, 30),\n                        12 => (Month::December, 31),\n                        _ => unreachable!(),\n                    };\n\n                    // Test the entire month\n                    for day in 1..=month.1 {\n                        let date = Date::from_calendar_date(year, month.0, day).unwrap();\n                        let py_date = date.into_pyobject(py).unwrap();\n                        let roundtripped: Date = py_date.extract().unwrap();\n                        assert_eq!(date, roundtripped);\n                    }\n                });\n            }\n\n            #[test]\n            fn test_time_time_roundtrip_random(\n                hour in 0u8..=23u8,\n                minute in 0u8..=59u8,\n                second in 0u8..=59u8,\n                microsecond in 0u32..=999999u32\n            ) {\n                Python::attach(|py| {\n                    let time = Time::from_hms_micro(hour, minute, second, microsecond).unwrap();\n                    let py_time = time.into_pyobject(py).unwrap();\n                    let roundtripped: Time = py_time.extract().unwrap();\n                    assert_eq!(time, roundtripped);\n                });\n            }\n\n            #[test]\n            fn test_time_primitive_datetime_roundtrip_random(\n                year in 1i32..=9999i32,\n                month in 1u8..=12u8,\n                day in 1u8..=28u8, // Use only valid days for all months\n                hour in 0u8..=23u8,\n                minute in 0u8..=59u8,\n                second in 0u8..=59u8,\n                microsecond in 0u32..=999999u32\n            ) {\n                Python::attach(|py| {\n                    let month = match month {\n                        1 => Month::January,\n                        2 => Month::February,\n                        3 => Month::March,\n                        4 => Month::April,\n                        5 => Month::May,\n                        6 => Month::June,\n                        7 => Month::July,\n                        8 => Month::August,\n                        9 => Month::September,\n                        10 => Month::October,\n                        11 => Month::November,\n                        12 => Month::December,\n                        _ => unreachable!(),\n                    };\n\n                    let date = Date::from_calendar_date(year, month, day).unwrap();\n                    let time = Time::from_hms_micro(hour, minute, second, microsecond).unwrap();\n                    let dt = PrimitiveDateTime::new(date, time);\n\n                    let py_dt = dt.into_pyobject(py).unwrap();\n                    let roundtripped: PrimitiveDateTime = py_dt.extract().unwrap();\n                    assert_eq!(dt, roundtripped);\n                });\n            }\n\n            #[test]\n            fn test_time_utc_offset_roundtrip_random(\n                hours in -23i8..=23i8,\n                minutes in -59i8..=59i8\n            ) {\n                // Skip invalid combinations where hour and minute signs don't match\n                if (hours < 0 && minutes > 0) || (hours > 0 && minutes < 0) {\n                    return Ok(());\n                }\n\n                Python::attach(|py| {\n                    if let Ok(offset) = UtcOffset::from_hms(hours, minutes, 0) {\n                        let py_tz = offset.into_pyobject(py).unwrap();\n                        let roundtripped: UtcOffset = py_tz.extract().unwrap();\n                        assert_eq!(roundtripped.whole_hours(), hours);\n                        assert_eq!(roundtripped.minutes_past_hour(), minutes);\n                    }\n                });\n            }\n\n            #[test]\n            fn test_time_offset_datetime_roundtrip_random(\n                year in 1i32..=9999i32,\n                month in 1u8..=12u8,\n                day in 1u8..=28u8, // Use only valid days for all months\n                hour in 0u8..=23u8,\n                minute in 0u8..=59u8,\n                second in 0u8..=59u8,\n                microsecond in 0u32..=999999u32,\n                tz_hour in -23i8..=23i8,\n                tz_minute in 0i8..=59i8\n            ) {\n                Python::attach(|py| {\n                    let month = match month {\n                        1 => Month::January,\n                        2 => Month::February,\n                        3 => Month::March,\n                        4 => Month::April,\n                        5 => Month::May,\n                        6 => Month::June,\n                        7 => Month::July,\n                        8 => Month::August,\n                        9 => Month::September,\n                        10 => Month::October,\n                        11 => Month::November,\n                        12 => Month::December,\n                        _ => unreachable!(),\n                    };\n\n                    let date = Date::from_calendar_date(year, month, day).unwrap();\n                    let time = Time::from_hms_micro(hour, minute, second, microsecond).unwrap();\n\n                    // Handle timezone sign correctly\n                    let tz_minute = if tz_hour < 0 { -tz_minute } else { tz_minute };\n\n                    if let Ok(offset) = UtcOffset::from_hms(tz_hour, tz_minute, 0) {\n                        let dt = PrimitiveDateTime::new(date, time).assume_offset(offset);\n                        let py_dt = dt.into_pyobject(py).unwrap();\n                        let roundtripped: OffsetDateTime = py_dt.extract().unwrap();\n\n                        assert_eq!(dt.year(), roundtripped.year());\n                        assert_eq!(dt.month(), roundtripped.month());\n                        assert_eq!(dt.day(), roundtripped.day());\n                        assert_eq!(dt.hour(), roundtripped.hour());\n                        assert_eq!(dt.minute(), roundtripped.minute());\n                        assert_eq!(dt.second(), roundtripped.second());\n                        assert_eq!(dt.microsecond(), roundtripped.microsecond());\n                        assert_eq!(dt.offset().whole_hours(), roundtripped.offset().whole_hours());\n                        assert_eq!(dt.offset().minutes_past_hour(), roundtripped.offset().minutes_past_hour());\n                    }\n                });\n            }\n\n            #[test]\n            fn test_time_utc_datetime_roundtrip_random(\n                year in 1i32..=9999i32,\n                month in 1u8..=12u8,\n                day in 1u8..=28u8, // Use only valid days for all months\n                hour in 0u8..=23u8,\n                minute in 0u8..=59u8,\n                second in 0u8..=59u8,\n                microsecond in 0u32..=999999u32\n            ) {\n                Python::attach(|py| {\n                    let month = match month {\n                        1 => Month::January,\n                        2 => Month::February,\n                        3 => Month::March,\n                        4 => Month::April,\n                        5 => Month::May,\n                        6 => Month::June,\n                        7 => Month::July,\n                        8 => Month::August,\n                        9 => Month::September,\n                        10 => Month::October,\n                        11 => Month::November,\n                        12 => Month::December,\n                        _ => unreachable!(),\n                    };\n\n                    let date = Date::from_calendar_date(year, month, day).unwrap();\n                    let time = Time::from_hms_micro(hour, minute, second, microsecond).unwrap();\n                    let primitive_dt = PrimitiveDateTime::new(date, time);\n                    let dt: UtcDateTime = primitive_dt.assume_utc().into();\n\n                    let py_dt = dt.into_pyobject(py).unwrap();\n                    let roundtripped: UtcDateTime = py_dt.extract().unwrap();\n\n                    assert_eq!(dt.year(), roundtripped.year());\n                    assert_eq!(dt.month(), roundtripped.month());\n                    assert_eq!(dt.day(), roundtripped.day());\n                    assert_eq!(dt.hour(), roundtripped.hour());\n                    assert_eq!(dt.minute(), roundtripped.minute());\n                    assert_eq!(dt.second(), roundtripped.second());\n                    assert_eq!(dt.microsecond(), roundtripped.microsecond());\n                })\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/conversions/uuid.rs",
    "content": "#![cfg(feature = \"uuid\")]\n\n//! Conversions to and from [uuid](https://docs.rs/uuid/latest/uuid/)'s [`Uuid`] and [`NonNilUuid`] types.\n//!\n//! This is useful for converting Python's uuid.UUID into and from a native Rust type.\n//!\n//! # Setup\n//!\n//! To use this feature, add to your **`Cargo.toml`**:\n//!\n//! ```toml\n//! [dependencies]\n#![doc = concat!(\"pyo3 = { version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\", features = [\\\"uuid\\\"] }\")]\n//! uuid = \"1.11.0\"\n//! ```\n//!\n//! Note that you must use a compatible version of uuid and PyO3.\n//! The required uuid version may vary based on the version of PyO3.\n//!\n//! # Example\n//!\n//! Rust code to create a function that parses a UUID string and returns it as a `Uuid`:\n//!\n//! ```rust,no_run\n//! use pyo3::prelude::*;\n//! use pyo3::exceptions::PyValueError;\n//! use uuid::Uuid;\n//!\n//! /// Parse a UUID from a string.\n//! #[pyfunction]\n//! fn get_uuid_from_str(s: &str) -> PyResult<Uuid> {\n//!     Uuid::parse_str(s).map_err(|e| PyValueError::new_err(e.to_string()))\n//! }\n//!\n//! /// Passing a Python uuid.UUID directly to Rust.\n//! #[pyfunction]\n//! fn get_uuid(u: Uuid) -> Uuid {\n//!     u\n//! }\n//!\n//! #[pymodule]\n//! fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n//!     m.add_function(wrap_pyfunction!(get_uuid_from_str, m)?)?;\n//!     m.add_function(wrap_pyfunction!(get_uuid, m)?)?;\n//!     Ok(())\n//! }\n//! ```\n//!\n//! Python code that validates the functionality\n//!\n//!\n//! ```python\n//! from my_module import get_uuid_from_str, get_uuid\n//! import uuid\n//!\n//! py_uuid = uuid.uuid4()\n//!\n//! # Convert string to Rust Uuid\n//! rust_uuid = get_uuid_from_str(str(py_uuid))\n//! assert py_uuid == rust_uuid\n//!\n//! # Pass Python UUID directly to Rust\n//! returned_uuid = get_uuid(py_uuid)\n//! assert py_uuid == returned_uuid\n//! ```\nuse uuid::{NonNilUuid, Uuid};\n\nuse crate::conversion::IntoPyObject;\nuse crate::exceptions::{PyTypeError, PyValueError};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::instance::Bound;\nuse crate::sync::PyOnceLock;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_hint_identifier;\nuse crate::types::any::PyAnyMethods;\nuse crate::types::PyType;\nuse crate::{intern, Borrowed, FromPyObject, Py, PyAny, PyErr, PyResult, Python};\n\nfn get_uuid_cls(py: Python<'_>) -> PyResult<&Bound<'_, PyType>> {\n    static UUID_CLS: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n    UUID_CLS.import(py, \"uuid\", \"UUID\")\n}\n\nimpl FromPyObject<'_, '_> for Uuid {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"uuid\", \"UUID\");\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {\n        let py = obj.py();\n        let uuid_cls = get_uuid_cls(py)?;\n\n        if obj.is_instance(uuid_cls)? {\n            let uuid_int: u128 = obj.getattr(intern!(py, \"int\"))?.extract()?;\n            Ok(Uuid::from_u128(uuid_int))\n        } else {\n            Err(PyTypeError::new_err(\"Expected a `uuid.UUID` instance.\"))\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for Uuid {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = type_hint_identifier!(\"uuid\", \"UUID\");\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        let uuid_cls = get_uuid_cls(py)?;\n\n        uuid_cls.call1((py.None(), py.None(), py.None(), py.None(), self.as_u128()))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &Uuid {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Uuid::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl FromPyObject<'_, '_> for NonNilUuid {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = Uuid::INPUT_TYPE;\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> PyResult<Self> {\n        let uuid: Uuid = obj.extract()?;\n        NonNilUuid::new(uuid).ok_or_else(|| PyValueError::new_err(\"UUID is nil\"))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for NonNilUuid {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = Uuid::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Uuid::from(self).into_pyobject(py)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &NonNilUuid {\n    type Target = PyAny;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = NonNilUuid::OUTPUT_TYPE;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::dict::PyDictMethods;\n    use crate::types::PyDict;\n    use std::ffi::CString;\n    use uuid::Uuid;\n\n    macro_rules! convert_constants {\n        ($name:ident, $rs:expr, $py:literal) => {\n            #[test]\n            fn $name() -> PyResult<()> {\n                Python::attach(|py| {\n                    let rs_orig = $rs;\n                    let rs_uuid = rs_orig.into_pyobject(py).unwrap();\n                    let locals = PyDict::new(py);\n                    locals.set_item(\"rs_uuid\", &rs_uuid).unwrap();\n\n                    py.run(\n                        &CString::new(format!(\n                            \"import uuid\\npy_uuid = uuid.UUID('{}')\\nassert py_uuid == rs_uuid\",\n                            $py\n                        ))\n                        .unwrap(),\n                        None,\n                        Some(&locals),\n                    )\n                    .unwrap();\n\n                    let py_uuid = locals.get_item(\"py_uuid\").unwrap().unwrap();\n                    let py_result: Uuid = py_uuid.extract().unwrap();\n                    assert_eq!(rs_orig, py_result);\n\n                    Ok(())\n                })\n            }\n        };\n    }\n\n    convert_constants!(\n        convert_nil,\n        Uuid::nil(),\n        \"00000000-0000-0000-0000-000000000000\"\n    );\n    convert_constants!(\n        convert_max,\n        Uuid::max(),\n        \"ffffffff-ffff-ffff-ffff-ffffffffffff\"\n    );\n\n    convert_constants!(\n        convert_uuid_v4,\n        Uuid::parse_str(\"a4f6d1b9-1898-418f-b11d-ecc6fe1e1f00\").unwrap(),\n        \"a4f6d1b9-1898-418f-b11d-ecc6fe1e1f00\"\n    );\n\n    convert_constants!(\n        convert_uuid_v3,\n        Uuid::parse_str(\"6fa459ea-ee8a-3ca4-894e-db77e160355e\").unwrap(),\n        \"6fa459ea-ee8a-3ca4-894e-db77e160355e\"\n    );\n\n    convert_constants!(\n        convert_uuid_v1,\n        Uuid::parse_str(\"a6cc5730-2261-11ee-9c43-2eb5a363657c\").unwrap(),\n        \"a6cc5730-2261-11ee-9c43-2eb5a363657c\"\n    );\n\n    #[test]\n    fn test_non_nil_uuid() {\n        Python::attach(|py| {\n            let rs_uuid = NonNilUuid::new(Uuid::max()).unwrap();\n            let py_uuid = rs_uuid.into_pyobject(py).unwrap();\n\n            let extract_uuid: NonNilUuid = py_uuid.extract().unwrap();\n            assert_eq!(extract_uuid, rs_uuid);\n\n            let nil_uuid = Uuid::nil().into_pyobject(py).unwrap();\n            let extract_nil: PyResult<NonNilUuid> = nil_uuid.extract();\n            assert!(extract_nil.is_err());\n        })\n    }\n}\n"
  },
  {
    "path": "src/coroutine/cancel.rs",
    "content": "use crate::{Py, PyAny};\nuse std::future::Future;\nuse std::pin::Pin;\nuse std::sync::{Arc, Mutex};\nuse std::task::{Context, Poll, Waker};\n\n#[derive(Debug, Default)]\nstruct Inner {\n    exception: Option<Py<PyAny>>,\n    waker: Option<Waker>,\n}\n\n/// Helper used to wait and retrieve exception thrown in [`Coroutine`](super::Coroutine).\n///\n/// Only the last exception thrown can be retrieved.\n#[derive(Debug, Default)]\npub struct CancelHandle(Arc<Mutex<Inner>>);\n\nimpl CancelHandle {\n    /// Create a new `CoroutineCancel`.\n    pub fn new() -> Self {\n        Default::default()\n    }\n\n    /// Returns whether the associated coroutine has been cancelled.\n    pub fn is_cancelled(&self) -> bool {\n        self.0.lock().unwrap().exception.is_some()\n    }\n\n    /// Poll to retrieve the exception thrown in the associated coroutine.\n    pub fn poll_cancelled(&mut self, cx: &mut Context<'_>) -> Poll<Py<PyAny>> {\n        let mut inner = self.0.lock().unwrap();\n        if let Some(exc) = inner.exception.take() {\n            return Poll::Ready(exc);\n        }\n        if let Some(ref waker) = inner.waker {\n            if cx.waker().will_wake(waker) {\n                return Poll::Pending;\n            }\n        }\n        inner.waker = Some(cx.waker().clone());\n        Poll::Pending\n    }\n\n    /// Retrieve the exception thrown in the associated coroutine.\n    pub async fn cancelled(&mut self) -> Py<PyAny> {\n        Cancelled(self).await\n    }\n\n    #[doc(hidden)]\n    pub fn throw_callback(&self) -> ThrowCallback {\n        ThrowCallback(self.0.clone())\n    }\n}\n\n// Because `poll_fn` is not available in MSRV\nstruct Cancelled<'a>(&'a mut CancelHandle);\n\nimpl Future for Cancelled<'_> {\n    type Output = Py<PyAny>;\n    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {\n        self.0.poll_cancelled(cx)\n    }\n}\n\n#[doc(hidden)]\npub struct ThrowCallback(Arc<Mutex<Inner>>);\n\nimpl ThrowCallback {\n    pub(super) fn throw(&self, exc: Py<PyAny>) {\n        let mut inner = self.0.lock().unwrap();\n        inner.exception = Some(exc);\n        if let Some(waker) = inner.waker.take() {\n            waker.wake();\n        }\n    }\n}\n"
  },
  {
    "path": "src/coroutine/waker.rs",
    "content": "use crate::sync::PyOnceLock;\nuse crate::types::any::PyAnyMethods;\nuse crate::types::PyCFunction;\nuse crate::{intern, wrap_pyfunction, Bound, Py, PyAny, PyResult, Python};\nuse pyo3_macros::pyfunction;\nuse std::sync::Arc;\nuse std::task::Wake;\n\n/// Lazy `asyncio.Future` wrapper, implementing [`Wake`] by calling `Future.set_result`.\n///\n/// asyncio future is let uninitialized until [`initialize_future`][1] is called.\n/// If [`wake`][2] is called before future initialization (during Rust future polling),\n/// [`initialize_future`][1] will return `None` (it is roughly equivalent to `asyncio.sleep(0)`)\n///\n/// [1]: AsyncioWaker::initialize_future\n/// [2]: AsyncioWaker::wake\npub struct AsyncioWaker(PyOnceLock<Option<LoopAndFuture>>);\n\nimpl AsyncioWaker {\n    pub(super) fn new() -> Self {\n        Self(PyOnceLock::new())\n    }\n\n    pub(super) fn reset(&mut self) {\n        self.0.take();\n    }\n\n    pub(super) fn initialize_future<'py>(\n        &self,\n        py: Python<'py>,\n    ) -> PyResult<Option<&Bound<'py, PyAny>>> {\n        let init = || LoopAndFuture::new(py).map(Some);\n        let loop_and_future = self.0.get_or_try_init(py, init)?.as_ref();\n        Ok(loop_and_future.map(|LoopAndFuture { future, .. }| future.bind(py)))\n    }\n}\n\nimpl Wake for AsyncioWaker {\n    fn wake(self: Arc<Self>) {\n        self.wake_by_ref()\n    }\n\n    fn wake_by_ref(self: &Arc<Self>) {\n        Python::attach(|py| {\n            if let Some(loop_and_future) = self.0.get_or_init(py, || None) {\n                loop_and_future\n                    .set_result(py)\n                    .expect(\"unexpected error in coroutine waker\");\n            }\n        });\n    }\n}\n\nstruct LoopAndFuture {\n    event_loop: Py<PyAny>,\n    future: Py<PyAny>,\n}\n\nimpl LoopAndFuture {\n    fn new(py: Python<'_>) -> PyResult<Self> {\n        static GET_RUNNING_LOOP: PyOnceLock<Py<PyAny>> = PyOnceLock::new();\n        let import = || -> PyResult<_> {\n            let module = py.import(\"asyncio\")?;\n            Ok(module.getattr(\"get_running_loop\")?.into())\n        };\n        let event_loop = GET_RUNNING_LOOP.get_or_try_init(py, import)?.call0(py)?;\n        let future = event_loop.call_method0(py, \"create_future\")?;\n        Ok(Self { event_loop, future })\n    }\n\n    fn set_result(&self, py: Python<'_>) -> PyResult<()> {\n        static RELEASE_WAITER: PyOnceLock<Py<PyCFunction>> = PyOnceLock::new();\n        let release_waiter = RELEASE_WAITER.get_or_try_init(py, || {\n            wrap_pyfunction!(release_waiter, py).map(Bound::unbind)\n        })?;\n        // `Future.set_result` must be called in event loop thread,\n        // so it requires `call_soon_threadsafe`\n        let call_soon_threadsafe = self.event_loop.call_method1(\n            py,\n            intern!(py, \"call_soon_threadsafe\"),\n            (release_waiter, self.future.bind(py)),\n        );\n        if let Err(err) = call_soon_threadsafe {\n            // `call_soon_threadsafe` will raise if the event loop is closed;\n            // instead of catching an unspecific `RuntimeError`, check directly if it's closed.\n            let is_closed = self.event_loop.call_method0(py, \"is_closed\")?;\n            if !is_closed.extract(py)? {\n                return Err(err);\n            }\n        }\n        Ok(())\n    }\n}\n\n/// Call `future.set_result` if the future is not done.\n///\n/// Future can be cancelled by the event loop before being waken.\n/// See <https://github.com/python/cpython/blob/main/Lib/asyncio/tasks.py#L452C5-L452C5>\n#[pyfunction(crate = \"crate\")]\nfn release_waiter(future: &Bound<'_, PyAny>) -> PyResult<()> {\n    let done = future.call_method0(intern!(future.py(), \"done\"))?;\n    if !done.extract::<bool>()? {\n        future.call_method1(intern!(future.py(), \"set_result\"), (future.py().None(),))?;\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "src/coroutine.rs",
    "content": "//! Python coroutine implementation, used notably when wrapping `async fn`\n//! with `#[pyfunction]`/`#[pymethods]`.\nuse std::{\n    future::Future,\n    panic,\n    pin::Pin,\n    sync::Arc,\n    task::{Context, Poll, Waker},\n};\n\nuse pyo3_macros::{pyclass, pymethods};\n\nuse crate::{\n    coroutine::{cancel::ThrowCallback, waker::AsyncioWaker},\n    exceptions::{PyAttributeError, PyRuntimeError, PyStopIteration},\n    panic::PanicException,\n    types::{string::PyStringMethods, PyIterator, PyString},\n    Bound, Py, PyAny, PyErr, PyResult, Python,\n};\n\npub(crate) mod cancel;\nmod waker;\n\npub use cancel::CancelHandle;\n\nconst COROUTINE_REUSED_ERROR: &str = \"cannot reuse already awaited coroutine\";\n\n/// Python coroutine wrapping a [`Future`].\n#[pyclass(crate = \"crate\")]\npub struct Coroutine {\n    name: Option<Py<PyString>>,\n    qualname_prefix: Option<&'static str>,\n    throw_callback: Option<ThrowCallback>,\n    #[expect(clippy::type_complexity)]\n    future: Option<Pin<Box<dyn Future<Output = PyResult<Py<PyAny>>> + Send>>>,\n    waker: Option<Arc<AsyncioWaker>>,\n}\n\n// Safety: `Coroutine` is allowed to be `Sync` even though the future is not,\n// because the future is polled with `&mut self` receiver\nunsafe impl Sync for Coroutine {}\n\nimpl Coroutine {\n    ///  Wrap a future into a Python coroutine.\n    ///\n    /// Coroutine `send` polls the wrapped future, ignoring the value passed\n    /// (should always be `None` anyway).\n    ///\n    /// `Coroutine `throw` drop the wrapped future and reraise the exception passed\n    pub(crate) fn new<'py, F>(\n        name: Option<Bound<'py, PyString>>,\n        qualname_prefix: Option<&'static str>,\n        throw_callback: Option<ThrowCallback>,\n        future: F,\n    ) -> Self\n    where\n        F: Future<Output = Result<Py<PyAny>, PyErr>> + Send + 'static,\n    {\n        Self {\n            name: name.map(Bound::unbind),\n            qualname_prefix,\n            throw_callback,\n            future: Some(Box::pin(future)),\n            waker: None,\n        }\n    }\n\n    fn poll(&mut self, py: Python<'_>, throw: Option<Py<PyAny>>) -> PyResult<Py<PyAny>> {\n        // raise if the coroutine has already been run to completion\n        let future_rs = match self.future {\n            Some(ref mut fut) => fut,\n            None => return Err(PyRuntimeError::new_err(COROUTINE_REUSED_ERROR)),\n        };\n        // reraise thrown exception it\n        match (throw, &self.throw_callback) {\n            (Some(exc), Some(cb)) => cb.throw(exc),\n            (Some(exc), None) => {\n                self.close();\n                return Err(PyErr::from_value(exc.into_bound(py)));\n            }\n            (None, _) => {}\n        }\n        // create a new waker, or try to reset it in place\n        if let Some(waker) = self.waker.as_mut().and_then(Arc::get_mut) {\n            waker.reset();\n        } else {\n            self.waker = Some(Arc::new(AsyncioWaker::new()));\n        }\n        let waker = Waker::from(self.waker.clone().unwrap());\n        // poll the Rust future and forward its results if ready\n        // polling is UnwindSafe because the future is dropped in case of panic\n        let poll = || future_rs.as_mut().poll(&mut Context::from_waker(&waker));\n        match panic::catch_unwind(panic::AssertUnwindSafe(poll)) {\n            Ok(Poll::Ready(res)) => {\n                self.close();\n                return Err(PyStopIteration::new_err((res?,)));\n            }\n            Err(err) => {\n                self.close();\n                return Err(PanicException::from_panic_payload(err));\n            }\n            _ => {}\n        }\n        // otherwise, initialize the waker `asyncio.Future`\n        if let Some(future) = self.waker.as_ref().unwrap().initialize_future(py)? {\n            // `asyncio.Future` must be awaited; fortunately, it implements `__iter__ = __await__`\n            // and will yield itself if its result has not been set in polling above\n            if let Some(future) = PyIterator::from_object(future).unwrap().next() {\n                // future has not been leaked into Python for now, and Rust code can only call\n                // `set_result(None)` in `Wake` implementation, so it's safe to unwrap\n                return Ok(future.unwrap().into());\n            }\n        }\n        // if waker has been waken during future polling, this is roughly equivalent to\n        // `await asyncio.sleep(0)`, so just yield `None`.\n        Ok(py.None())\n    }\n}\n\n#[pymethods(crate = \"crate\")]\nimpl Coroutine {\n    #[getter]\n    fn __name__(&self, py: Python<'_>) -> PyResult<Py<PyString>> {\n        match &self.name {\n            Some(name) => Ok(name.clone_ref(py)),\n            None => Err(PyAttributeError::new_err(\"__name__\")),\n        }\n    }\n\n    #[getter]\n    fn __qualname__<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyString>> {\n        match (&self.name, &self.qualname_prefix) {\n            (Some(name), Some(prefix)) => Ok(PyString::new(\n                py,\n                &format!(\"{}.{}\", prefix, name.bind(py).to_cow()?),\n            )),\n            (Some(name), None) => Ok(name.bind(py).clone()),\n            (None, _) => Err(PyAttributeError::new_err(\"__qualname__\")),\n        }\n    }\n\n    fn send(&mut self, py: Python<'_>, _value: &Bound<'_, PyAny>) -> PyResult<Py<PyAny>> {\n        self.poll(py, None)\n    }\n\n    fn throw(&mut self, py: Python<'_>, exc: Py<PyAny>) -> PyResult<Py<PyAny>> {\n        self.poll(py, Some(exc))\n    }\n\n    fn close(&mut self) {\n        // the Rust future is dropped, and the field set to `None`\n        // to indicate the coroutine has been run to completion\n        drop(self.future.take());\n    }\n\n    fn __await__(self_: Py<Self>) -> Py<Self> {\n        self_\n    }\n\n    fn __next__(&mut self, py: Python<'_>) -> PyResult<Py<PyAny>> {\n        self.poll(py, None)\n    }\n}\n"
  },
  {
    "path": "src/err/cast_error.rs",
    "content": "use std::borrow::Cow;\n\nuse crate::{\n    exceptions,\n    types::{\n        PyAnyMethods, PyNone, PyStringMethods, PyTuple, PyTupleMethods, PyType, PyTypeMethods,\n    },\n    Borrowed, Bound, IntoPyObjectExt, Py, PyAny, PyErr, PyErrArguments, PyTypeInfo, Python,\n};\n\n/// Error that indicates an object was not an instance of a given target type.\n#[derive(Debug)]\npub struct CastError<'a, 'py> {\n    /// The original object that failed the `isinstance` check.\n    from: Borrowed<'a, 'py, PyAny>,\n    /// The type we tried (and failed) to convert to.\n    /// (see `PyTypeCheck::classinfo_object`)\n    classinfo: Bound<'py, PyAny>,\n}\n\nimpl<'a, 'py> CastError<'a, 'py> {\n    /// Create a new `CastError` representing a failure to interpret a smart pointer to\n    /// `from` as a type from the given `classinfo`.\n    ///\n    /// As with [`PyTypeCheck::classinfo_object`][crate::PyTypeCheck::classinfo_object],\n    /// valid `classinfo` values are those which can be used with `isinstance`, such as `type`\n    /// objects, tuples of `type` objects, or `typing.Union` instances.\n    #[inline]\n    pub fn new(from: Borrowed<'a, 'py, PyAny>, classinfo: Bound<'py, PyAny>) -> Self {\n        Self { from, classinfo }\n    }\n}\n\n/// Equivalent to [`CastError`] for operations where the smart pointer cast transfers ownership\n/// of the original object.\n///\n/// The original object can be retrieved using [`into_inner`][CastIntoError::into_inner].\n#[derive(Debug)]\npub struct CastIntoError<'py> {\n    from: Bound<'py, PyAny>,\n    classinfo: Bound<'py, PyAny>,\n}\n\nimpl<'py> CastIntoError<'py> {\n    /// Create a new `CastError` representing a failure to interpret a smart pointer to\n    /// `from` as a type from the given `classinfo`.\n    ///\n    /// Equivalent to [`CastError::new`] for owned objects.\n    #[inline]\n    pub fn new(from: Bound<'py, PyAny>, classinfo: Bound<'py, PyAny>) -> Self {\n        Self { from, classinfo }\n    }\n\n    /// Consumes this `CastIntoError` and returns the original object, allowing continued\n    /// use of it after a failed conversion.\n    ///\n    /// See [`cast_into`][Bound::cast_into] for an example.\n    pub fn into_inner(self) -> Bound<'py, PyAny> {\n        self.from\n    }\n}\n\nstruct CastErrorArguments {\n    from: Py<PyAny>,\n    classinfo: Py<PyAny>,\n}\n\nimpl PyErrArguments for CastErrorArguments {\n    fn arguments(self, py: Python<'_>) -> Py<PyAny> {\n        format!(\n            \"{}\",\n            DisplayCastError {\n                from: &self.from.into_bound(py),\n                classinfo: &self.classinfo.into_bound(py),\n            }\n        )\n        .into_py_any(py)\n        .expect(\"failed to create Python string\")\n    }\n}\n\n/// Convert `CastError` to Python `TypeError`.\nimpl std::convert::From<CastError<'_, '_>> for PyErr {\n    fn from(err: CastError<'_, '_>) -> PyErr {\n        let args = CastErrorArguments {\n            from: err.from.to_owned().unbind(),\n            classinfo: err.classinfo.unbind(),\n        };\n\n        exceptions::PyTypeError::new_err(args)\n    }\n}\n\nimpl std::error::Error for CastError<'_, '_> {}\n\nimpl std::fmt::Display for CastError<'_, '_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {\n        DisplayCastError {\n            from: &self.from,\n            classinfo: &self.classinfo,\n        }\n        .fmt(f)\n    }\n}\n\n/// Convert `CastIntoError` to Python `TypeError`.\nimpl std::convert::From<CastIntoError<'_>> for PyErr {\n    fn from(err: CastIntoError<'_>) -> PyErr {\n        let args = CastErrorArguments {\n            from: err.from.to_owned().unbind(),\n            classinfo: err.classinfo.unbind(),\n        };\n\n        exceptions::PyTypeError::new_err(args)\n    }\n}\n\nimpl std::error::Error for CastIntoError<'_> {}\n\nimpl std::fmt::Display for CastIntoError<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {\n        DisplayCastError {\n            from: &self.from.to_owned(),\n            classinfo: &self.classinfo,\n        }\n        .fmt(f)\n    }\n}\n\nstruct DisplayCastError<'a, 'py> {\n    from: &'a Bound<'py, PyAny>,\n    classinfo: &'a Bound<'py, PyAny>,\n}\n\nimpl std::fmt::Display for DisplayCastError<'_, '_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        let to = DisplayClassInfo(self.classinfo);\n        if self.from.is_none() {\n            write!(f, \"'None' is not an instance of '{to}'\")\n        } else {\n            let from = self.from.get_type().qualname();\n            let from = from\n                .as_ref()\n                .map(|name| name.to_string_lossy())\n                .unwrap_or(Cow::Borrowed(\"<failed to extract type name>\"));\n            write!(f, \"'{from}' object is not an instance of '{to}'\")\n        }\n    }\n}\n\nstruct DisplayClassInfo<'a, 'py>(&'a Bound<'py, PyAny>);\n\nimpl std::fmt::Display for DisplayClassInfo<'_, '_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        if let Ok(t) = self.0.cast::<PyType>() {\n            if t.is(PyNone::type_object(t.py())) {\n                f.write_str(\"None\")\n            } else {\n                t.qualname()\n                    .map_err(|_| std::fmt::Error)?\n                    .to_string_lossy()\n                    .fmt(f)\n            }\n        } else if let Ok(t) = self.0.cast::<PyTuple>() {\n            for (i, t) in t.iter().enumerate() {\n                if i > 0 {\n                    f.write_str(\" | \")?;\n                }\n                write!(f, \"{}\", DisplayClassInfo(&t))?;\n            }\n            Ok(())\n        } else {\n            self.0.fmt(f)\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::{\n        types::{PyBool, PyString},\n        PyTypeInfo,\n    };\n\n    use super::*;\n\n    #[test]\n    fn test_display_cast_error() {\n        Python::attach(|py| {\n            let obj = PyBool::new(py, true).to_any();\n            let classinfo = py.get_type::<PyString>().into_any();\n            let err = CastError::new(obj, classinfo);\n            assert_eq!(err.to_string(), \"'bool' object is not an instance of 'str'\");\n        })\n    }\n\n    #[test]\n    fn test_display_cast_error_with_none() {\n        Python::attach(|py| {\n            let obj = py.None().into_bound(py);\n            let classinfo = py.get_type::<PyString>().into_any();\n            let err = CastError::new(obj.as_borrowed(), classinfo);\n            assert_eq!(err.to_string(), \"'None' is not an instance of 'str'\");\n        })\n    }\n\n    #[test]\n    fn test_display_cast_error_with_tuple() {\n        Python::attach(|py| {\n            let obj = PyBool::new(py, true).to_any();\n            let classinfo = PyTuple::new(\n                py,\n                &[\n                    py.get_type::<PyString>().into_any(),\n                    crate::types::PyNone::type_object(py).into_any(),\n                ],\n            )\n            .unwrap()\n            .into_any();\n            let err = CastError::new(obj, classinfo);\n            assert_eq!(\n                err.to_string(),\n                \"'bool' object is not an instance of 'str | None'\"\n            );\n        })\n    }\n\n    #[test]\n    fn test_display_cast_into_error() {\n        Python::attach(|py| {\n            let obj = PyBool::new(py, true).to_any();\n            let classinfo = py.get_type::<PyString>().into_any();\n            let err = CastIntoError::new(obj.to_owned(), classinfo);\n            assert_eq!(err.to_string(), \"'bool' object is not an instance of 'str'\");\n        })\n    }\n\n    #[test]\n    fn test_pyerr_from_cast_error() {\n        Python::attach(|py| {\n            let obj = PyBool::new(py, true).to_any();\n            let classinfo = py.get_type::<PyString>().into_any();\n            let err = CastError::new(obj, classinfo);\n            let py_err: PyErr = err.into();\n            assert_eq!(\n                py_err.to_string(),\n                \"TypeError: 'bool' object is not an instance of 'str'\"\n            );\n        })\n    }\n\n    #[test]\n    fn test_pyerr_from_cast_into_error() {\n        Python::attach(|py| {\n            let obj = PyBool::new(py, true).to_any();\n            let classinfo = py.get_type::<PyString>().into_any();\n            let err = CastIntoError::new(obj.to_owned(), classinfo);\n            let py_err: PyErr = err.into();\n            assert_eq!(\n                py_err.to_string(),\n                \"TypeError: 'bool' object is not an instance of 'str'\"\n            );\n        })\n    }\n}\n"
  },
  {
    "path": "src/err/downcast_error.rs",
    "content": "#![allow(deprecated)]\n\nuse std::borrow::Cow;\n\nuse crate::{\n    exceptions,\n    types::{PyAnyMethods, PyStringMethods, PyType, PyTypeMethods},\n    Borrowed, Bound, IntoPyObject, Py, PyAny, PyErr, PyErrArguments, Python,\n};\n\n/// Error that indicates a failure to convert a PyAny to a more specific Python type.\n#[derive(Debug)]\n#[deprecated(since = \"0.27.0\", note = \"replaced with `CastError`\")]\npub struct DowncastError<'a, 'py> {\n    from: Borrowed<'a, 'py, PyAny>,\n    to: Cow<'static, str>,\n}\n\nimpl<'a, 'py> DowncastError<'a, 'py> {\n    /// Create a new `DowncastError` representing a failure to convert the object\n    /// `from` into the type named in `to`.\n    pub fn new(from: &'a Bound<'py, PyAny>, to: impl Into<Cow<'static, str>>) -> Self {\n        Self {\n            from: from.as_borrowed(),\n            to: to.into(),\n        }\n    }\n}\n\n/// Error that indicates a failure to convert a PyAny to a more specific Python type.\n#[derive(Debug)]\n#[deprecated(since = \"0.27.0\", note = \"replaced with `CastIntoError`\")]\npub struct DowncastIntoError<'py> {\n    from: Bound<'py, PyAny>,\n    to: Cow<'static, str>,\n}\n\nimpl<'py> DowncastIntoError<'py> {\n    /// Create a new `DowncastIntoError` representing a failure to convert the object\n    /// `from` into the type named in `to`.\n    pub fn new(from: Bound<'py, PyAny>, to: impl Into<Cow<'static, str>>) -> Self {\n        Self {\n            from,\n            to: to.into(),\n        }\n    }\n\n    /// Consumes this `DowncastIntoError` and returns the original object, allowing continued\n    /// use of it after a failed conversion.\n    ///\n    /// See [`cast_into`][Bound::cast_into] for an example.\n    pub fn into_inner(self) -> Bound<'py, PyAny> {\n        self.from\n    }\n}\n\nstruct DowncastErrorArguments {\n    from: Py<PyType>,\n    to: Cow<'static, str>,\n}\n\nimpl PyErrArguments for DowncastErrorArguments {\n    fn arguments(self, py: Python<'_>) -> Py<PyAny> {\n        let from = self.from.bind(py).qualname();\n        let from = from\n            .as_ref()\n            .map(|name| name.to_string_lossy())\n            .unwrap_or(Cow::Borrowed(\"<failed to extract type name>\"));\n        format!(\"'{}' object cannot be converted to '{}'\", from, self.to)\n            .into_pyobject(py)\n            .unwrap()\n            .into_any()\n            .unbind()\n    }\n}\n\n/// Convert `CastError` to Python `TypeError`.\nimpl std::convert::From<DowncastError<'_, '_>> for PyErr {\n    fn from(err: DowncastError<'_, '_>) -> PyErr {\n        let args = DowncastErrorArguments {\n            from: err.from.get_type().into(),\n            to: err.to,\n        };\n\n        exceptions::PyTypeError::new_err(args)\n    }\n}\n\nimpl std::error::Error for DowncastError<'_, '_> {}\n\nimpl std::fmt::Display for DowncastError<'_, '_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {\n        display_downcast_error(f, &self.from, &self.to)\n    }\n}\n\n/// Convert `DowncastIntoError` to Python `TypeError`.\nimpl std::convert::From<DowncastIntoError<'_>> for PyErr {\n    fn from(err: DowncastIntoError<'_>) -> PyErr {\n        let args = DowncastErrorArguments {\n            from: err.from.get_type().into(),\n            to: err.to,\n        };\n\n        exceptions::PyTypeError::new_err(args)\n    }\n}\n\nimpl std::error::Error for DowncastIntoError<'_> {}\n\nimpl std::fmt::Display for DowncastIntoError<'_> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {\n        display_downcast_error(f, &self.from, &self.to)\n    }\n}\n\nfn display_downcast_error(\n    f: &mut std::fmt::Formatter<'_>,\n    from: &Bound<'_, PyAny>,\n    to: &str,\n) -> std::fmt::Result {\n    write!(\n        f,\n        \"'{}' object cannot be converted to '{}'\",\n        from.get_type().qualname().map_err(|_| std::fmt::Error)?,\n        to\n    )\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_display_downcast_error() {\n        Python::attach(|py| {\n            let obj = py.None().into_bound(py);\n            let err = DowncastError::new(&obj, \"int\");\n            assert_eq!(\n                err.to_string(),\n                \"'NoneType' object cannot be converted to 'int'\"\n            );\n        })\n    }\n\n    #[test]\n    fn test_display_downcast_into_error() {\n        Python::attach(|py| {\n            let obj = py.None().into_bound(py);\n            let err = DowncastIntoError::new(obj, \"int\");\n            assert_eq!(\n                err.to_string(),\n                \"'NoneType' object cannot be converted to 'int'\"\n            );\n        })\n    }\n\n    #[test]\n    fn test_pyerr_from_downcast_error() {\n        Python::attach(|py| {\n            let obj = py.None().into_bound(py);\n            let err = DowncastError::new(&obj, \"int\");\n            let py_err: PyErr = err.into();\n            assert_eq!(\n                py_err.to_string(),\n                \"TypeError: 'NoneType' object cannot be converted to 'int'\"\n            );\n        })\n    }\n\n    #[test]\n    fn test_pyerr_from_downcast_into_error() {\n        Python::attach(|py| {\n            let obj = py.None().into_bound(py);\n            let err = DowncastIntoError::new(obj, \"int\");\n            let py_err: PyErr = err.into();\n            assert_eq!(\n                py_err.to_string(),\n                \"TypeError: 'NoneType' object cannot be converted to 'int'\"\n            );\n        })\n    }\n}\n"
  },
  {
    "path": "src/err/err_state.rs",
    "content": "use std::{\n    cell::UnsafeCell,\n    sync::{Mutex, Once},\n    thread::ThreadId,\n};\n\n#[cfg(not(Py_3_12))]\nuse crate::sync::MutexExt;\nuse crate::{\n    exceptions::{PyBaseException, PyTypeError},\n    ffi,\n    ffi_ptr_ext::FfiPtrExt,\n    types::{PyAnyMethods, PyTraceback, PyType},\n    Bound, Py, PyAny, PyErrArguments, PyTypeInfo, Python,\n};\n\npub(crate) struct PyErrState {\n    // Safety: can only hand out references when in the \"normalized\" state. Will never change\n    // after normalization.\n    normalized: Once,\n    // Guard against re-entrancy when normalizing the exception state.\n    normalizing_thread: Mutex<Option<ThreadId>>,\n    inner: UnsafeCell<Option<PyErrStateInner>>,\n}\n\n// Safety: The inner value is protected by locking to ensure that only the normalized state is\n// handed out as a reference.\nunsafe impl Send for PyErrState {}\nunsafe impl Sync for PyErrState {}\n#[cfg(feature = \"nightly\")]\nunsafe impl crate::marker::Ungil for PyErrState {}\n\nimpl PyErrState {\n    pub(crate) fn lazy(f: Box<PyErrStateLazyFn>) -> Self {\n        Self::from_inner(PyErrStateInner::Lazy(f))\n    }\n\n    pub(crate) fn lazy_arguments(ptype: Py<PyAny>, args: impl PyErrArguments + 'static) -> Self {\n        Self::from_inner(PyErrStateInner::Lazy(Box::new(move |py| {\n            PyErrStateLazyFnOutput {\n                ptype,\n                pvalue: args.arguments(py),\n            }\n        })))\n    }\n\n    pub(crate) fn normalized(normalized: PyErrStateNormalized) -> Self {\n        let state = Self::from_inner(PyErrStateInner::Normalized(normalized));\n        // This state is already normalized, by completing the Once immediately we avoid\n        // reaching the `py.detach` in `make_normalized` which is less efficient\n        // and introduces a GIL switch which could deadlock.\n        // See https://github.com/PyO3/pyo3/issues/4764\n        state.normalized.call_once(|| {});\n        state\n    }\n\n    pub(crate) fn restore(self, py: Python<'_>) {\n        self.inner\n            .into_inner()\n            .expect(\"PyErr state should never be invalid outside of normalization\")\n            .restore(py)\n    }\n\n    fn from_inner(inner: PyErrStateInner) -> Self {\n        Self {\n            normalized: Once::new(),\n            normalizing_thread: Mutex::new(None),\n            inner: UnsafeCell::new(Some(inner)),\n        }\n    }\n\n    #[inline]\n    pub(crate) fn as_normalized(&self, py: Python<'_>) -> &PyErrStateNormalized {\n        if self.normalized.is_completed() {\n            match unsafe {\n                // Safety: self.inner will never be written again once normalized.\n                &*self.inner.get()\n            } {\n                Some(PyErrStateInner::Normalized(n)) => return n,\n                _ => unreachable!(),\n            }\n        }\n\n        self.make_normalized(py)\n    }\n\n    #[cold]\n    fn make_normalized(&self, py: Python<'_>) -> &PyErrStateNormalized {\n        // This process is safe because:\n        // - Write happens only once, and then never will change again.\n        // - The `Once` ensure that only one thread will do the write.\n\n        // Guard against re-entrant normalization, because `Once` does not provide\n        // re-entrancy guarantees.\n        if let Some(thread) = self.normalizing_thread.lock().unwrap().as_ref() {\n            assert!(\n                !(*thread == std::thread::current().id()),\n                \"Re-entrant normalization of PyErrState detected\"\n            );\n        }\n\n        // avoid deadlock of `.call_once` with the GIL\n        py.detach(|| {\n            self.normalized.call_once(|| {\n                self.normalizing_thread\n                    .lock()\n                    .unwrap()\n                    .replace(std::thread::current().id());\n\n                // Safety: no other thread can access the inner value while we are normalizing it.\n                let state = unsafe {\n                    (*self.inner.get())\n                        .take()\n                        .expect(\"Cannot normalize a PyErr while already normalizing it.\")\n                };\n\n                let normalized_state =\n                    Python::attach(|py| PyErrStateInner::Normalized(state.normalize(py)));\n\n                // Safety: no other thread can access the inner value while we are normalizing it.\n                unsafe {\n                    *self.inner.get() = Some(normalized_state);\n                }\n            })\n        });\n\n        match unsafe {\n            // Safety: self.inner will never be written again once normalized.\n            &*self.inner.get()\n        } {\n            Some(PyErrStateInner::Normalized(n)) => n,\n            _ => unreachable!(),\n        }\n    }\n}\n\npub(crate) struct PyErrStateNormalized {\n    #[cfg(not(Py_3_12))]\n    ptype: Py<PyType>,\n    pub pvalue: Py<PyBaseException>,\n    #[cfg(not(Py_3_12))]\n    ptraceback: std::sync::Mutex<Option<Py<PyTraceback>>>,\n}\n\nimpl PyErrStateNormalized {\n    pub(crate) fn new(pvalue: Bound<'_, PyBaseException>) -> Self {\n        Self {\n            #[cfg(not(Py_3_12))]\n            ptype: pvalue.get_type().into(),\n            #[cfg(not(Py_3_12))]\n            ptraceback: unsafe {\n                Mutex::new(\n                    ffi::PyException_GetTraceback(pvalue.as_ptr())\n                        .assume_owned_or_opt(pvalue.py())\n                        .map(|b| b.cast_into_unchecked().unbind()),\n                )\n            },\n            pvalue: pvalue.into(),\n        }\n    }\n\n    #[cfg(not(Py_3_12))]\n    pub(crate) fn ptype<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> {\n        self.ptype.bind(py).clone()\n    }\n\n    #[cfg(Py_3_12)]\n    pub(crate) fn ptype<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> {\n        self.pvalue.bind(py).get_type()\n    }\n\n    #[cfg(not(Py_3_12))]\n    pub(crate) fn ptraceback<'py>(&self, py: Python<'py>) -> Option<Bound<'py, PyTraceback>> {\n        self.ptraceback\n            .lock_py_attached(py)\n            .unwrap()\n            .as_ref()\n            .map(|traceback| traceback.bind(py).clone())\n    }\n\n    #[cfg(Py_3_12)]\n    pub(crate) fn ptraceback<'py>(&self, py: Python<'py>) -> Option<Bound<'py, PyTraceback>> {\n        unsafe {\n            ffi::PyException_GetTraceback(self.pvalue.as_ptr())\n                .assume_owned_or_opt(py)\n                .map(|b| b.cast_into_unchecked())\n        }\n    }\n\n    #[cfg(not(Py_3_12))]\n    pub(crate) fn set_ptraceback<'py>(&self, py: Python<'py>, tb: Option<Bound<'py, PyTraceback>>) {\n        *self.ptraceback.lock_py_attached(py).unwrap() = tb.map(Bound::unbind);\n    }\n\n    #[cfg(Py_3_12)]\n    pub(crate) fn set_ptraceback<'py>(&self, py: Python<'py>, tb: Option<Bound<'py, PyTraceback>>) {\n        let tb = tb\n            .as_ref()\n            .map(Bound::as_ptr)\n            .unwrap_or_else(|| crate::types::PyNone::get(py).as_ptr());\n\n        unsafe { ffi::PyException_SetTraceback(self.pvalue.as_ptr(), tb) };\n    }\n\n    pub(crate) fn take(py: Python<'_>) -> Option<PyErrStateNormalized> {\n        #[cfg(Py_3_12)]\n        {\n            // Safety: PyErr_GetRaisedException can be called when attached to Python and\n            // returns either NULL or an owned reference.\n            unsafe { ffi::PyErr_GetRaisedException().assume_owned_or_opt(py) }.map(|pvalue| {\n                PyErrStateNormalized {\n                    // Safety: PyErr_GetRaisedException returns a valid exception type.\n                    pvalue: unsafe { pvalue.cast_into_unchecked() }.unbind(),\n                }\n            })\n        }\n\n        #[cfg(not(Py_3_12))]\n        {\n            let (ptype, pvalue, ptraceback) = unsafe {\n                let mut ptype: *mut ffi::PyObject = std::ptr::null_mut();\n                let mut pvalue: *mut ffi::PyObject = std::ptr::null_mut();\n                let mut ptraceback: *mut ffi::PyObject = std::ptr::null_mut();\n\n                ffi::PyErr_Fetch(&mut ptype, &mut pvalue, &mut ptraceback);\n\n                // Ensure that the exception coming from the interpreter is normalized.\n                if !ptype.is_null() {\n                    ffi::PyErr_NormalizeException(&mut ptype, &mut pvalue, &mut ptraceback);\n                }\n\n                // Safety: PyErr_NormalizeException will have produced up to three owned\n                // references of the correct types.\n                (\n                    ptype\n                        .assume_owned_or_opt(py)\n                        .map(|b| b.cast_into_unchecked()),\n                    pvalue\n                        .assume_owned_or_opt(py)\n                        .map(|b| b.cast_into_unchecked()),\n                    ptraceback\n                        .assume_owned_or_opt(py)\n                        .map(|b| b.cast_into_unchecked()),\n                )\n            };\n\n            ptype.map(|ptype| PyErrStateNormalized {\n                ptype: ptype.unbind(),\n                pvalue: pvalue.expect(\"normalized exception value missing\").unbind(),\n                ptraceback: std::sync::Mutex::new(ptraceback.map(Bound::unbind)),\n            })\n        }\n    }\n\n    #[cfg(not(Py_3_12))]\n    unsafe fn from_normalized_ffi_tuple(\n        py: Python<'_>,\n        ptype: *mut ffi::PyObject,\n        pvalue: *mut ffi::PyObject,\n        ptraceback: *mut ffi::PyObject,\n    ) -> Self {\n        PyErrStateNormalized {\n            ptype: unsafe {\n                ptype\n                    .assume_owned_or_opt(py)\n                    .expect(\"Exception type missing\")\n                    .cast_into_unchecked()\n            }\n            .unbind(),\n            pvalue: unsafe {\n                pvalue\n                    .assume_owned_or_opt(py)\n                    .expect(\"Exception value missing\")\n                    .cast_into_unchecked()\n            }\n            .unbind(),\n            ptraceback: Mutex::new(\n                unsafe { ptraceback.assume_owned_or_opt(py) }\n                    .map(|b| unsafe { b.cast_into_unchecked() }.unbind()),\n            ),\n        }\n    }\n\n    pub fn clone_ref(&self, py: Python<'_>) -> Self {\n        Self {\n            #[cfg(not(Py_3_12))]\n            ptype: self.ptype.clone_ref(py),\n            pvalue: self.pvalue.clone_ref(py),\n            #[cfg(not(Py_3_12))]\n            ptraceback: std::sync::Mutex::new(\n                self.ptraceback\n                    .lock_py_attached(py)\n                    .unwrap()\n                    .as_ref()\n                    .map(|ptraceback| ptraceback.clone_ref(py)),\n            ),\n        }\n    }\n}\n\npub(crate) struct PyErrStateLazyFnOutput {\n    pub(crate) ptype: Py<PyAny>,\n    pub(crate) pvalue: Py<PyAny>,\n}\n\npub(crate) type PyErrStateLazyFn =\n    dyn for<'py> FnOnce(Python<'py>) -> PyErrStateLazyFnOutput + Send + Sync;\n\nenum PyErrStateInner {\n    Lazy(Box<PyErrStateLazyFn>),\n    Normalized(PyErrStateNormalized),\n}\n\nimpl PyErrStateInner {\n    fn normalize(self, py: Python<'_>) -> PyErrStateNormalized {\n        match self {\n            #[cfg(not(Py_3_12))]\n            PyErrStateInner::Lazy(lazy) => {\n                let (ptype, pvalue, ptraceback) = lazy_into_normalized_ffi_tuple(py, lazy);\n                unsafe {\n                    PyErrStateNormalized::from_normalized_ffi_tuple(py, ptype, pvalue, ptraceback)\n                }\n            }\n            #[cfg(Py_3_12)]\n            PyErrStateInner::Lazy(lazy) => {\n                // To keep the implementation simple, just write the exception into the interpreter,\n                // which will cause it to be normalized\n                raise_lazy(py, lazy);\n                PyErrStateNormalized::take(py)\n                    .expect(\"exception missing after writing to the interpreter\")\n            }\n            PyErrStateInner::Normalized(normalized) => normalized,\n        }\n    }\n\n    #[cfg(not(Py_3_12))]\n    fn restore(self, py: Python<'_>) {\n        let (ptype, pvalue, ptraceback) = match self {\n            PyErrStateInner::Lazy(lazy) => lazy_into_normalized_ffi_tuple(py, lazy),\n            PyErrStateInner::Normalized(PyErrStateNormalized {\n                ptype,\n                pvalue,\n                ptraceback,\n            }) => (\n                ptype.into_ptr(),\n                pvalue.into_ptr(),\n                ptraceback\n                    .into_inner()\n                    .unwrap()\n                    .map_or(std::ptr::null_mut(), Py::into_ptr),\n            ),\n        };\n        unsafe { ffi::PyErr_Restore(ptype, pvalue, ptraceback) }\n    }\n\n    #[cfg(Py_3_12)]\n    fn restore(self, py: Python<'_>) {\n        match self {\n            PyErrStateInner::Lazy(lazy) => raise_lazy(py, lazy),\n            PyErrStateInner::Normalized(PyErrStateNormalized { pvalue }) => unsafe {\n                ffi::PyErr_SetRaisedException(pvalue.into_ptr())\n            },\n        }\n    }\n}\n\n#[cfg(not(Py_3_12))]\nfn lazy_into_normalized_ffi_tuple(\n    py: Python<'_>,\n    lazy: Box<PyErrStateLazyFn>,\n) -> (*mut ffi::PyObject, *mut ffi::PyObject, *mut ffi::PyObject) {\n    // To be consistent with 3.12 logic, go via raise_lazy, but also then normalize\n    // the resulting exception\n    raise_lazy(py, lazy);\n    let mut ptype = std::ptr::null_mut();\n    let mut pvalue = std::ptr::null_mut();\n    let mut ptraceback = std::ptr::null_mut();\n    unsafe {\n        ffi::PyErr_Fetch(&mut ptype, &mut pvalue, &mut ptraceback);\n        ffi::PyErr_NormalizeException(&mut ptype, &mut pvalue, &mut ptraceback);\n    }\n    (ptype, pvalue, ptraceback)\n}\n\n/// Raises a \"lazy\" exception state into the Python interpreter.\n///\n/// In principle this could be split in two; first a function to create an exception\n/// in a normalized state, and then a call to `PyErr_SetRaisedException` to raise it.\n///\n/// This would require either moving some logic from C to Rust, or requesting a new\n/// API in CPython.\nfn raise_lazy(py: Python<'_>, lazy: Box<PyErrStateLazyFn>) {\n    let PyErrStateLazyFnOutput { ptype, pvalue } = lazy(py);\n    unsafe {\n        if ffi::PyExceptionClass_Check(ptype.as_ptr()) == 0 {\n            ffi::PyErr_SetString(\n                PyTypeError::type_object_raw(py).cast(),\n                c\"exceptions must derive from BaseException\".as_ptr(),\n            )\n        } else {\n            ffi::PyErr_SetObject(ptype.as_ptr(), pvalue.as_ptr())\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n\n    use crate::{\n        exceptions::PyValueError, sync::PyOnceLock, Py, PyAny, PyErr, PyErrArguments, Python,\n    };\n\n    #[test]\n    #[should_panic(expected = \"Re-entrant normalization of PyErrState detected\")]\n    fn test_reentrant_normalization() {\n        static ERR: PyOnceLock<PyErr> = PyOnceLock::new();\n\n        struct RecursiveArgs;\n\n        impl PyErrArguments for RecursiveArgs {\n            fn arguments(self, py: Python<'_>) -> Py<PyAny> {\n                // .value(py) triggers normalization\n                ERR.get(py)\n                    .expect(\"is set just below\")\n                    .value(py)\n                    .clone()\n                    .into()\n            }\n        }\n\n        Python::attach(|py| {\n            ERR.set(py, PyValueError::new_err(RecursiveArgs)).unwrap();\n            ERR.get(py).expect(\"is set just above\").value(py);\n        })\n    }\n\n    #[test]\n    #[cfg(not(target_arch = \"wasm32\"))] // We are building wasm Python with pthreads disabled\n    fn test_no_deadlock_thread_switch() {\n        static ERR: PyOnceLock<PyErr> = PyOnceLock::new();\n\n        struct GILSwitchArgs;\n\n        impl PyErrArguments for GILSwitchArgs {\n            fn arguments(self, py: Python<'_>) -> Py<PyAny> {\n                // releasing the GIL potentially allows for other threads to deadlock\n                // with the normalization going on here\n                py.detach(|| {\n                    std::thread::sleep(std::time::Duration::from_millis(10));\n                });\n                py.None()\n            }\n        }\n\n        Python::attach(|py| ERR.set(py, PyValueError::new_err(GILSwitchArgs)).unwrap());\n\n        // Let many threads attempt to read the normalized value at the same time\n        let handles = (0..10)\n            .map(|_| {\n                std::thread::spawn(|| {\n                    Python::attach(|py| {\n                        ERR.get(py).expect(\"is set just above\").value(py);\n                    });\n                })\n            })\n            .collect::<Vec<_>>();\n\n        for handle in handles {\n            handle.join().unwrap();\n        }\n\n        // We should never have deadlocked, and should be able to run\n        // this assertion\n        Python::attach(|py| {\n            assert!(ERR\n                .get(py)\n                .expect(\"is set above\")\n                .is_instance_of::<PyValueError>(py))\n        });\n    }\n}\n"
  },
  {
    "path": "src/err/impls.rs",
    "content": "use crate::{err::PyErrArguments, exceptions, types, PyErr, Python};\nuse crate::{IntoPyObject, Py, PyAny};\nuse std::io;\n\n/// Convert `PyErr` to `io::Error`\nimpl From<PyErr> for io::Error {\n    fn from(err: PyErr) -> Self {\n        let kind = Python::attach(|py| {\n            if err.is_instance_of::<exceptions::PyBrokenPipeError>(py) {\n                io::ErrorKind::BrokenPipe\n            } else if err.is_instance_of::<exceptions::PyConnectionRefusedError>(py) {\n                io::ErrorKind::ConnectionRefused\n            } else if err.is_instance_of::<exceptions::PyConnectionAbortedError>(py) {\n                io::ErrorKind::ConnectionAborted\n            } else if err.is_instance_of::<exceptions::PyConnectionResetError>(py) {\n                io::ErrorKind::ConnectionReset\n            } else if err.is_instance_of::<exceptions::PyInterruptedError>(py) {\n                io::ErrorKind::Interrupted\n            } else if err.is_instance_of::<exceptions::PyFileNotFoundError>(py) {\n                io::ErrorKind::NotFound\n            } else if err.is_instance_of::<exceptions::PyPermissionError>(py) {\n                io::ErrorKind::PermissionDenied\n            } else if err.is_instance_of::<exceptions::PyFileExistsError>(py) {\n                io::ErrorKind::AlreadyExists\n            } else if err.is_instance_of::<exceptions::PyBlockingIOError>(py) {\n                io::ErrorKind::WouldBlock\n            } else if err.is_instance_of::<exceptions::PyTimeoutError>(py) {\n                io::ErrorKind::TimedOut\n            } else if err.is_instance_of::<exceptions::PyMemoryError>(py) {\n                io::ErrorKind::OutOfMemory\n            } else if err.is_instance_of::<exceptions::PyIsADirectoryError>(py) {\n                io::ErrorKind::IsADirectory\n            } else if err.is_instance_of::<exceptions::PyNotADirectoryError>(py) {\n                io::ErrorKind::NotADirectory\n            } else {\n                io::ErrorKind::Other\n            }\n        });\n        io::Error::new(kind, err)\n    }\n}\n\n/// Create `PyErr` from `io::Error`\n/// (`OSError` except if the `io::Error` is wrapping a Python exception,\n/// in this case the exception is returned)\nimpl From<io::Error> for PyErr {\n    fn from(err: io::Error) -> PyErr {\n        // If the error wraps a Python error we return it\n        if err.get_ref().is_some_and(|e| e.is::<PyErr>()) {\n            return *err.into_inner().unwrap().downcast().unwrap();\n        }\n        match err.kind() {\n            io::ErrorKind::BrokenPipe => exceptions::PyBrokenPipeError::new_err(err),\n            io::ErrorKind::ConnectionRefused => exceptions::PyConnectionRefusedError::new_err(err),\n            io::ErrorKind::ConnectionAborted => exceptions::PyConnectionAbortedError::new_err(err),\n            io::ErrorKind::ConnectionReset => exceptions::PyConnectionResetError::new_err(err),\n            io::ErrorKind::Interrupted => exceptions::PyInterruptedError::new_err(err),\n            io::ErrorKind::NotFound => exceptions::PyFileNotFoundError::new_err(err),\n            io::ErrorKind::PermissionDenied => exceptions::PyPermissionError::new_err(err),\n            io::ErrorKind::AlreadyExists => exceptions::PyFileExistsError::new_err(err),\n            io::ErrorKind::WouldBlock => exceptions::PyBlockingIOError::new_err(err),\n            io::ErrorKind::TimedOut => exceptions::PyTimeoutError::new_err(err),\n            io::ErrorKind::OutOfMemory => exceptions::PyMemoryError::new_err(err),\n            io::ErrorKind::IsADirectory => exceptions::PyIsADirectoryError::new_err(err),\n            io::ErrorKind::NotADirectory => exceptions::PyNotADirectoryError::new_err(err),\n            _ => exceptions::PyOSError::new_err(err),\n        }\n    }\n}\n\nimpl PyErrArguments for io::Error {\n    fn arguments(self, py: Python<'_>) -> Py<PyAny> {\n        //FIXME(icxolu) remove unwrap\n        self.to_string()\n            .into_pyobject(py)\n            .unwrap()\n            .into_any()\n            .unbind()\n    }\n}\n\nimpl<W> From<io::IntoInnerError<W>> for PyErr {\n    fn from(err: io::IntoInnerError<W>) -> PyErr {\n        err.into_error().into()\n    }\n}\n\nimpl<W: Send + Sync> PyErrArguments for io::IntoInnerError<W> {\n    fn arguments(self, py: Python<'_>) -> Py<PyAny> {\n        self.into_error().arguments(py)\n    }\n}\n\nimpl From<std::convert::Infallible> for PyErr {\n    fn from(_: std::convert::Infallible) -> PyErr {\n        unreachable!()\n    }\n}\n\nmacro_rules! impl_to_pyerr {\n    ($err: ty, $pyexc: ty) => {\n        impl PyErrArguments for $err {\n            fn arguments(self, py: Python<'_>) -> $crate::Py<$crate::PyAny> {\n                // FIXME(icxolu) remove unwrap\n                self.to_string()\n                    .into_pyobject(py)\n                    .unwrap()\n                    .into_any()\n                    .unbind()\n            }\n        }\n\n        impl std::convert::From<$err> for PyErr {\n            fn from(err: $err) -> PyErr {\n                <$pyexc>::new_err(err)\n            }\n        }\n    };\n}\n\nstruct Utf8ErrorWithBytes {\n    err: std::str::Utf8Error,\n    bytes: Vec<u8>,\n}\n\nimpl PyErrArguments for Utf8ErrorWithBytes {\n    fn arguments(self, py: Python<'_>) -> Py<PyAny> {\n        let Self { err, bytes } = self;\n        let start = err.valid_up_to();\n        let end = err.error_len().map_or(bytes.len(), |l| start + l);\n\n        let encoding = types::PyString::new(py, \"utf-8\").into_any();\n        let bytes = types::PyBytes::new(py, &bytes).into_any();\n        let start = types::PyInt::new(py, start).into_any();\n        let end = types::PyInt::new(py, end).into_any();\n        let reason = types::PyString::new(py, \"invalid utf-8\").into_any();\n\n        // FIXME(icxolu) remove unwrap\n        types::PyTuple::new(py, &[encoding, bytes, start, end, reason])\n            .unwrap()\n            .into_any()\n            .unbind()\n    }\n}\n\nimpl PyErrArguments for std::string::FromUtf8Error {\n    fn arguments(self, py: Python<'_>) -> Py<PyAny> {\n        Utf8ErrorWithBytes {\n            err: self.utf8_error(),\n            bytes: self.into_bytes(),\n        }\n        .arguments(py)\n    }\n}\n\nimpl std::convert::From<std::string::FromUtf8Error> for PyErr {\n    fn from(err: std::string::FromUtf8Error) -> PyErr {\n        exceptions::PyUnicodeDecodeError::new_err(err)\n    }\n}\n\nimpl PyErrArguments for std::ffi::IntoStringError {\n    fn arguments(self, py: Python<'_>) -> Py<PyAny> {\n        Utf8ErrorWithBytes {\n            err: self.utf8_error(),\n            bytes: self.into_cstring().into_bytes(),\n        }\n        .arguments(py)\n    }\n}\n\nimpl std::convert::From<std::ffi::IntoStringError> for PyErr {\n    fn from(err: std::ffi::IntoStringError) -> PyErr {\n        exceptions::PyUnicodeDecodeError::new_err(err)\n    }\n}\n\nimpl_to_pyerr!(std::array::TryFromSliceError, exceptions::PyValueError);\nimpl_to_pyerr!(std::num::ParseIntError, exceptions::PyValueError);\nimpl_to_pyerr!(std::num::ParseFloatError, exceptions::PyValueError);\nimpl_to_pyerr!(std::num::TryFromIntError, exceptions::PyValueError);\nimpl_to_pyerr!(std::str::ParseBoolError, exceptions::PyValueError);\nimpl_to_pyerr!(std::ffi::NulError, exceptions::PyValueError);\nimpl_to_pyerr!(std::net::AddrParseError, exceptions::PyValueError);\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    use crate::exceptions::PyUnicodeDecodeError;\n    use crate::types::PyAnyMethods;\n    use crate::{IntoPyObjectExt as _, PyErr, Python};\n    use std::io;\n\n    #[test]\n    fn io_errors() {\n        use crate::types::any::PyAnyMethods;\n\n        let check_err = |kind, expected_ty| {\n            Python::attach(|py| {\n                let rust_err = io::Error::new(kind, \"some error msg\");\n\n                let py_err: PyErr = rust_err.into();\n                let py_err_msg = format!(\"{expected_ty}: some error msg\");\n                assert_eq!(py_err.to_string(), py_err_msg);\n                let py_error_clone = py_err.clone_ref(py);\n\n                let rust_err_from_py_err: io::Error = py_err.into();\n                assert_eq!(rust_err_from_py_err.to_string(), py_err_msg);\n                assert_eq!(rust_err_from_py_err.kind(), kind);\n\n                let py_err_recovered_from_rust_err: PyErr = rust_err_from_py_err.into();\n                assert!(py_err_recovered_from_rust_err\n                    .value(py)\n                    .is(py_error_clone.value(py))); // It should be the same exception\n            })\n        };\n\n        check_err(io::ErrorKind::BrokenPipe, \"BrokenPipeError\");\n        check_err(io::ErrorKind::ConnectionRefused, \"ConnectionRefusedError\");\n        check_err(io::ErrorKind::ConnectionAborted, \"ConnectionAbortedError\");\n        check_err(io::ErrorKind::ConnectionReset, \"ConnectionResetError\");\n        check_err(io::ErrorKind::Interrupted, \"InterruptedError\");\n        check_err(io::ErrorKind::NotFound, \"FileNotFoundError\");\n        check_err(io::ErrorKind::PermissionDenied, \"PermissionError\");\n        check_err(io::ErrorKind::AlreadyExists, \"FileExistsError\");\n        check_err(io::ErrorKind::WouldBlock, \"BlockingIOError\");\n        check_err(io::ErrorKind::TimedOut, \"TimeoutError\");\n        check_err(io::ErrorKind::IsADirectory, \"IsADirectoryError\");\n        check_err(io::ErrorKind::NotADirectory, \"NotADirectoryError\");\n    }\n\n    #[test]\n    #[allow(invalid_from_utf8)]\n    fn utf8_errors() {\n        let bytes = b\"abc\\xffdef\".to_vec();\n\n        let check_err = |py_err: PyErr| {\n            Python::attach(|py| {\n                let py_err = py_err.into_bound_py_any(py).unwrap();\n\n                assert!(py_err.is_instance_of::<exceptions::PyUnicodeDecodeError>());\n                assert_eq!(\n                    py_err\n                        .getattr(\"encoding\")\n                        .unwrap()\n                        .extract::<String>()\n                        .unwrap(),\n                    \"utf-8\"\n                );\n                assert_eq!(\n                    py_err\n                        .getattr(\"object\")\n                        .unwrap()\n                        .extract::<Vec<u8>>()\n                        .unwrap(),\n                    &*bytes\n                );\n                assert_eq!(\n                    py_err.getattr(\"start\").unwrap().extract::<usize>().unwrap(),\n                    3\n                );\n                assert_eq!(\n                    py_err.getattr(\"end\").unwrap().extract::<usize>().unwrap(),\n                    4\n                );\n                assert_eq!(\n                    py_err\n                        .getattr(\"reason\")\n                        .unwrap()\n                        .extract::<String>()\n                        .unwrap(),\n                    \"invalid utf-8\"\n                );\n            });\n        };\n\n        let utf8_err_with_bytes = PyUnicodeDecodeError::new_err(Utf8ErrorWithBytes {\n            err: std::str::from_utf8(&bytes).expect_err(\"\\\\xff is invalid utf-8\"),\n            bytes: bytes.clone(),\n        });\n        check_err(utf8_err_with_bytes);\n\n        let from_utf8_err = String::from_utf8(bytes.clone())\n            .expect_err(\"\\\\xff is invalid utf-8\")\n            .into();\n        check_err(from_utf8_err);\n\n        let from_utf8_err = std::ffi::CString::new(bytes.clone())\n            .unwrap()\n            .into_string()\n            .expect_err(\"\\\\xff is invalid utf-8\")\n            .into();\n        check_err(from_utf8_err);\n    }\n}\n"
  },
  {
    "path": "src/err/mod.rs",
    "content": "use crate::conversion::IntoPyObject;\nuse crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::instance::Bound;\n#[cfg(Py_3_11)]\nuse crate::intern;\nuse crate::panic::PanicException;\nuse crate::py_result_ext::PyResultExt;\nuse crate::type_object::PyTypeInfo;\nuse crate::types::any::PyAnyMethods;\n#[cfg(Py_3_11)]\nuse crate::types::PyString;\nuse crate::types::{\n    string::PyStringMethods, traceback::PyTracebackMethods, typeobject::PyTypeMethods, PyTraceback,\n    PyType,\n};\nuse crate::{exceptions::PyBaseException, ffi};\nuse crate::{BoundObject, Py, PyAny, Python};\nuse err_state::{PyErrState, PyErrStateLazyFnOutput, PyErrStateNormalized};\nuse std::convert::Infallible;\nuse std::ffi::CStr;\n\nmod cast_error;\nmod downcast_error;\nmod err_state;\nmod impls;\n\npub use cast_error::{CastError, CastIntoError};\n#[allow(deprecated)]\npub use downcast_error::{DowncastError, DowncastIntoError};\n\n/// Represents a Python exception.\n///\n/// To avoid needing access to [`Python`] in `Into` conversions to create `PyErr` (thus improving\n/// compatibility with `?` and other Rust errors) this type supports creating exceptions instances\n/// in a lazy fashion, where the full Python object for the exception is created only when needed.\n///\n/// Accessing the contained exception in any way, such as with [`value`](PyErr::value),\n/// [`get_type`](PyErr::get_type), or [`is_instance`](PyErr::is_instance)\n/// will create the full exception object if it was not already created.\npub struct PyErr {\n    state: PyErrState,\n}\n\n// The inner value is only accessed through ways that require proving the gil is held\n#[cfg(feature = \"nightly\")]\nunsafe impl crate::marker::Ungil for PyErr {}\n\n/// Represents the result of a Python call.\npub type PyResult<T> = Result<T, PyErr>;\n\n/// Helper conversion trait that allows to use custom arguments for lazy exception construction.\npub trait PyErrArguments: Send + Sync {\n    /// Arguments for exception\n    fn arguments(self, py: Python<'_>) -> Py<PyAny>;\n}\n\nimpl<T> PyErrArguments for T\nwhere\n    T: for<'py> IntoPyObject<'py> + Send + Sync,\n{\n    fn arguments(self, py: Python<'_>) -> Py<PyAny> {\n        // FIXME: `arguments` should become fallible\n        match self.into_pyobject(py) {\n            Ok(obj) => obj.into_any().unbind(),\n            Err(e) => panic!(\"Converting PyErr arguments failed: {}\", e.into()),\n        }\n    }\n}\n\nimpl PyErr {\n    /// Creates a new PyErr of type `T`.\n    ///\n    /// `args` can be:\n    /// * a tuple: the exception instance will be created using the equivalent to the Python\n    ///   expression `T(*tuple)`\n    /// * any other value: the exception instance will be created using the equivalent to the Python\n    ///   expression `T(value)`\n    ///\n    /// This exception instance will be initialized lazily. This avoids the need for the Python GIL\n    /// to be held, but requires `args` to be `Send` and `Sync`. If `args` is not `Send` or `Sync`,\n    /// consider using [`PyErr::from_value`] instead.\n    ///\n    /// If `T` does not inherit from `BaseException`, then a `TypeError` will be returned.\n    ///\n    /// If calling T's constructor with `args` raises an exception, that exception will be returned.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use pyo3::prelude::*;\n    /// use pyo3::exceptions::PyTypeError;\n    ///\n    /// #[pyfunction]\n    /// fn always_throws() -> PyResult<()> {\n    ///     Err(PyErr::new::<PyTypeError, _>(\"Error message\"))\n    /// }\n    /// #\n    /// # Python::attach(|py| {\n    /// #     let fun = pyo3::wrap_pyfunction!(always_throws, py).unwrap();\n    /// #     let err = fun.call0().expect_err(\"called a function that should always return an error but the return value was Ok\");\n    /// #     assert!(err.is_instance_of::<PyTypeError>(py))\n    /// # });\n    /// ```\n    ///\n    /// In most cases, you can use a concrete exception's constructor instead:\n    ///\n    /// ```\n    /// use pyo3::prelude::*;\n    /// use pyo3::exceptions::PyTypeError;\n    ///\n    /// #[pyfunction]\n    /// fn always_throws() -> PyResult<()> {\n    ///     Err(PyTypeError::new_err(\"Error message\"))\n    /// }\n    /// #\n    /// # Python::attach(|py| {\n    /// #     let fun = pyo3::wrap_pyfunction!(always_throws, py).unwrap();\n    /// #     let err = fun.call0().expect_err(\"called a function that should always return an error but the return value was Ok\");\n    /// #     assert!(err.is_instance_of::<PyTypeError>(py))\n    /// # });\n    /// ```\n    #[inline]\n    pub fn new<T, A>(args: A) -> PyErr\n    where\n        T: PyTypeInfo,\n        A: PyErrArguments + Send + Sync + 'static,\n    {\n        PyErr::from_state(PyErrState::lazy(Box::new(move |py| {\n            PyErrStateLazyFnOutput {\n                ptype: T::type_object(py).into(),\n                pvalue: args.arguments(py),\n            }\n        })))\n    }\n\n    /// Constructs a new PyErr from the given Python type and arguments.\n    ///\n    /// `ty` is the exception type; usually one of the standard exceptions\n    /// like `exceptions::PyRuntimeError`.\n    ///\n    /// `args` is either a tuple or a single value, with the same meaning as in [`PyErr::new`].\n    ///\n    /// If `ty` does not inherit from `BaseException`, then a `TypeError` will be returned.\n    ///\n    /// If calling `ty` with `args` raises an exception, that exception will be returned.\n    pub fn from_type<A>(ty: Bound<'_, PyType>, args: A) -> PyErr\n    where\n        A: PyErrArguments + Send + Sync + 'static,\n    {\n        PyErr::from_state(PyErrState::lazy_arguments(ty.unbind().into_any(), args))\n    }\n\n    /// Creates a new PyErr.\n    ///\n    /// If `obj` is a Python exception object, the PyErr will contain that object.\n    ///\n    /// If `obj` is a Python exception type object, this is equivalent to `PyErr::from_type(obj, ())`.\n    ///\n    /// Otherwise, a `TypeError` is created.\n    ///\n    /// # Examples\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::PyTypeInfo;\n    /// use pyo3::exceptions::PyTypeError;\n    /// use pyo3::types::PyString;\n    ///\n    /// Python::attach(|py| {\n    ///     // Case #1: Exception object\n    ///     let err = PyErr::from_value(PyTypeError::new_err(\"some type error\")\n    ///         .value(py).clone().into_any());\n    ///     assert_eq!(err.to_string(), \"TypeError: some type error\");\n    ///\n    ///     // Case #2: Exception type\n    ///     let err = PyErr::from_value(PyTypeError::type_object(py).into_any());\n    ///     assert_eq!(err.to_string(), \"TypeError: \");\n    ///\n    ///     // Case #3: Invalid exception value\n    ///     let err = PyErr::from_value(PyString::new(py, \"foo\").into_any());\n    ///     assert_eq!(\n    ///         err.to_string(),\n    ///         \"TypeError: exceptions must derive from BaseException\"\n    ///     );\n    /// });\n    /// ```\n    pub fn from_value(obj: Bound<'_, PyAny>) -> PyErr {\n        let state = match obj.cast_into::<PyBaseException>() {\n            Ok(obj) => PyErrState::normalized(PyErrStateNormalized::new(obj)),\n            Err(err) => {\n                // Assume obj is Type[Exception]; let later normalization handle if this\n                // is not the case\n                let obj = err.into_inner();\n                let py = obj.py();\n                PyErrState::lazy_arguments(obj.unbind(), py.None())\n            }\n        };\n\n        PyErr::from_state(state)\n    }\n\n    /// Returns the type of this exception.\n    ///\n    /// # Examples\n    /// ```rust\n    /// use pyo3::{prelude::*, exceptions::PyTypeError, types::PyType};\n    ///\n    /// Python::attach(|py| {\n    ///     let err: PyErr = PyTypeError::new_err((\"some type error\",));\n    ///     assert!(err.get_type(py).is(&PyType::new::<PyTypeError>(py)));\n    /// });\n    /// ```\n    pub fn get_type<'py>(&self, py: Python<'py>) -> Bound<'py, PyType> {\n        self.normalized(py).ptype(py)\n    }\n\n    /// Returns the value of this exception.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::{exceptions::PyTypeError, PyErr, Python};\n    ///\n    /// Python::attach(|py| {\n    ///     let err: PyErr = PyTypeError::new_err((\"some type error\",));\n    ///     assert!(err.is_instance_of::<PyTypeError>(py));\n    ///     assert_eq!(err.value(py).to_string(), \"some type error\");\n    /// });\n    /// ```\n    pub fn value<'py>(&self, py: Python<'py>) -> &Bound<'py, PyBaseException> {\n        self.normalized(py).pvalue.bind(py)\n    }\n\n    /// Consumes self to take ownership of the exception value contained in this error.\n    pub fn into_value(self, py: Python<'_>) -> Py<PyBaseException> {\n        // NB technically this causes one reference count increase and decrease in quick succession\n        // on pvalue, but it's probably not worth optimizing this right now for the additional code\n        // complexity.\n        let normalized = self.normalized(py);\n        let exc = normalized.pvalue.clone_ref(py);\n        if let Some(tb) = normalized.ptraceback(py) {\n            unsafe {\n                ffi::PyException_SetTraceback(exc.as_ptr(), tb.as_ptr());\n            }\n        }\n        exc\n    }\n\n    /// Returns the traceback of this exception object.\n    ///\n    /// # Examples\n    /// ```rust\n    /// use pyo3::{exceptions::PyTypeError, Python};\n    ///\n    /// Python::attach(|py| {\n    ///     let err = PyTypeError::new_err((\"some type error\",));\n    ///     assert!(err.traceback(py).is_none());\n    /// });\n    /// ```\n    pub fn traceback<'py>(&self, py: Python<'py>) -> Option<Bound<'py, PyTraceback>> {\n        self.normalized(py).ptraceback(py)\n    }\n\n    /// Set the traceback associated with the exception, pass `None` to clear it.\n    pub fn set_traceback<'py>(&self, py: Python<'_>, tb: Option<Bound<'py, PyTraceback>>) {\n        self.normalized(py).set_ptraceback(py, tb)\n    }\n\n    /// Gets whether an error is present in the Python interpreter's global state.\n    #[inline]\n    pub fn occurred(_: Python<'_>) -> bool {\n        unsafe { !ffi::PyErr_Occurred().is_null() }\n    }\n\n    /// Takes the current error from the Python interpreter's global state and clears the global\n    /// state. If no error is set, returns `None`.\n    ///\n    /// If the error is a `PanicException` (which would have originated from a panic in a pyo3\n    /// callback) then this function will resume the panic.\n    ///\n    /// Use this function when it is not known if an error should be present. If the error is\n    /// expected to have been set, for example from [`PyErr::occurred`] or by an error return value\n    /// from a C FFI function, use [`PyErr::fetch`].\n    pub fn take(py: Python<'_>) -> Option<PyErr> {\n        let state = PyErrStateNormalized::take(py)?;\n\n        if PanicException::is_exact_type_of(state.pvalue.bind(py)) {\n            Self::print_panic_and_unwind(py, state)\n        }\n\n        Some(PyErr::from_state(PyErrState::normalized(state)))\n    }\n\n    #[cold]\n    fn print_panic_and_unwind(py: Python<'_>, state: PyErrStateNormalized) -> ! {\n        let msg: String = state\n            .pvalue\n            .bind(py)\n            .str()\n            .map(|py_str| py_str.to_string_lossy().into())\n            .unwrap_or_else(|_| String::from(\"Unwrapped panic from Python code\"));\n\n        eprintln!(\"--- PyO3 is resuming a panic after fetching a PanicException from Python. ---\");\n        eprintln!(\"Python stack trace below:\");\n\n        PyErrState::normalized(state).restore(py);\n\n        // SAFETY: thread is attached and error was just set in the interpreter\n        unsafe {\n            ffi::PyErr_PrintEx(0);\n        }\n\n        std::panic::resume_unwind(Box::new(msg))\n    }\n\n    /// Equivalent to [PyErr::take], but when no error is set:\n    ///  - Panics in debug mode.\n    ///  - Returns a `SystemError` in release mode.\n    ///\n    /// This behavior is consistent with Python's internal handling of what happens when a C return\n    /// value indicates an error occurred but the global error state is empty. (A lack of exception\n    /// should be treated as a bug in the code which returned an error code but did not set an\n    /// exception.)\n    ///\n    /// Use this function when the error is expected to have been set, for example from\n    /// [PyErr::occurred] or by an error return value from a C FFI function.\n    #[cfg_attr(debug_assertions, track_caller)]\n    #[inline]\n    pub fn fetch(py: Python<'_>) -> PyErr {\n        PyErr::take(py).unwrap_or_else(failed_to_fetch)\n    }\n\n    /// Creates a new exception type with the given name and docstring.\n    ///\n    /// - `base` can be an existing exception type to subclass, or a tuple of classes.\n    /// - `dict` specifies an optional dictionary of class variables and methods.\n    /// - `doc` will be the docstring seen by python users.\n    ///\n    ///\n    /// # Errors\n    ///\n    /// This function returns an error if `name` is not of the form `<module>.<ExceptionName>`.\n    pub fn new_type<'py>(\n        py: Python<'py>,\n        name: &CStr,\n        doc: Option<&CStr>,\n        base: Option<&Bound<'py, PyType>>,\n        dict: Option<Py<PyAny>>,\n    ) -> PyResult<Py<PyType>> {\n        let base: *mut ffi::PyObject = match base {\n            None => std::ptr::null_mut(),\n            Some(obj) => obj.as_ptr(),\n        };\n\n        let dict: *mut ffi::PyObject = match dict {\n            None => std::ptr::null_mut(),\n            Some(obj) => obj.as_ptr(),\n        };\n\n        let doc_ptr = match doc.as_ref() {\n            Some(c) => c.as_ptr(),\n            None => std::ptr::null(),\n        };\n\n        // SAFETY: correct call to FFI function, return value is known to be a new\n        // exception type or null on error\n        unsafe {\n            ffi::PyErr_NewExceptionWithDoc(name.as_ptr(), doc_ptr, base, dict)\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n        }\n        .map(Bound::unbind)\n    }\n\n    /// Prints a standard traceback to `sys.stderr`.\n    pub fn display(&self, py: Python<'_>) {\n        #[cfg(Py_3_12)]\n        unsafe {\n            ffi::PyErr_DisplayException(self.value(py).as_ptr())\n        }\n\n        #[cfg(not(Py_3_12))]\n        unsafe {\n            // keep the bound `traceback` alive for entire duration of\n            // PyErr_Display. if we inline this, the `Bound` will be dropped\n            // after the argument got evaluated, leading to call with a dangling\n            // pointer.\n            let traceback = self.traceback(py);\n            let type_bound = self.get_type(py);\n            ffi::PyErr_Display(\n                type_bound.as_ptr(),\n                self.value(py).as_ptr(),\n                traceback\n                    .as_ref()\n                    .map_or(std::ptr::null_mut(), |traceback| traceback.as_ptr()),\n            )\n        }\n    }\n\n    /// Calls `sys.excepthook` and then prints a standard traceback to `sys.stderr`.\n    pub fn print(&self, py: Python<'_>) {\n        self.clone_ref(py).restore(py);\n        unsafe { ffi::PyErr_PrintEx(0) }\n    }\n\n    /// Calls `sys.excepthook` and then prints a standard traceback to `sys.stderr`.\n    ///\n    /// Additionally sets `sys.last_{type,value,traceback,exc}` attributes to this exception.\n    pub fn print_and_set_sys_last_vars(&self, py: Python<'_>) {\n        self.clone_ref(py).restore(py);\n        unsafe { ffi::PyErr_PrintEx(1) }\n    }\n\n    /// Returns true if the current exception matches the exception in `exc`.\n    ///\n    /// If `exc` is a class object, this also returns `true` when `self` is an instance of a subclass.\n    /// If `exc` is a tuple, all exceptions in the tuple (and recursively in subtuples) are searched for a match.\n    pub fn matches<'py, T>(&self, py: Python<'py>, exc: T) -> Result<bool, T::Error>\n    where\n        T: IntoPyObject<'py>,\n    {\n        Ok(self.is_instance(py, &exc.into_pyobject(py)?.into_any().as_borrowed()))\n    }\n\n    /// Returns true if the current exception is instance of `T`.\n    #[inline]\n    pub fn is_instance(&self, py: Python<'_>, ty: &Bound<'_, PyAny>) -> bool {\n        let type_bound = self.get_type(py);\n        (unsafe { ffi::PyErr_GivenExceptionMatches(type_bound.as_ptr(), ty.as_ptr()) }) != 0\n    }\n\n    /// Returns true if the current exception is instance of `T`.\n    #[inline]\n    pub fn is_instance_of<T>(&self, py: Python<'_>) -> bool\n    where\n        T: PyTypeInfo,\n    {\n        self.is_instance(py, &T::type_object(py))\n    }\n\n    /// Writes the error back to the Python interpreter's global state.\n    /// This is the opposite of `PyErr::fetch()`.\n    #[inline]\n    pub fn restore(self, py: Python<'_>) {\n        self.state.restore(py)\n    }\n\n    /// Reports the error as unraisable.\n    ///\n    /// This calls `sys.unraisablehook()` using the current exception and obj argument.\n    ///\n    /// This method is useful to report errors in situations where there is no good mechanism\n    /// to report back to the Python land.  In Python this is used to indicate errors in\n    /// background threads or destructors which are protected.  In Rust code this is commonly\n    /// useful when you are calling into a Python callback which might fail, but there is no\n    /// obvious way to handle this error other than logging it.\n    ///\n    /// Calling this method has the benefit that the error goes back into a standardized callback\n    /// in Python which for instance allows unittests to ensure that no unraisable error\n    /// actually happened by hooking `sys.unraisablehook`.\n    ///\n    /// Example:\n    /// ```rust\n    /// # use pyo3::prelude::*;\n    /// # use pyo3::exceptions::PyRuntimeError;\n    /// # fn failing_function() -> PyResult<()> { Err(PyRuntimeError::new_err(\"foo\")) }\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     match failing_function() {\n    ///         Err(pyerr) => pyerr.write_unraisable(py, None),\n    ///         Ok(..) => { /* do something here */ }\n    ///     }\n    ///     Ok(())\n    /// })\n    /// # }\n    #[inline]\n    pub fn write_unraisable(self, py: Python<'_>, obj: Option<&Bound<'_, PyAny>>) {\n        self.restore(py);\n        unsafe { ffi::PyErr_WriteUnraisable(obj.map_or(std::ptr::null_mut(), Bound::as_ptr)) }\n    }\n\n    /// Issues a warning message.\n    ///\n    /// May return an `Err(PyErr)` if warnings-as-errors is enabled.\n    ///\n    /// Equivalent to `warnings.warn()` in Python.\n    ///\n    /// The `category` should be one of the `Warning` classes available in\n    /// [`pyo3::exceptions`](crate::exceptions), or a subclass.  The Python\n    /// object can be retrieved using [`Python::get_type()`].\n    ///\n    /// Example:\n    /// ```rust\n    /// # use pyo3::prelude::*;\n    /// # use pyo3::ffi::c_str;\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let user_warning = py.get_type::<pyo3::exceptions::PyUserWarning>();\n    ///     PyErr::warn(py, &user_warning, c\"I am warning you\", 0)?;\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    pub fn warn<'py>(\n        py: Python<'py>,\n        category: &Bound<'py, PyAny>,\n        message: &CStr,\n        stacklevel: i32,\n    ) -> PyResult<()> {\n        error_on_minusone(py, unsafe {\n            ffi::PyErr_WarnEx(\n                category.as_ptr(),\n                message.as_ptr(),\n                stacklevel as ffi::Py_ssize_t,\n            )\n        })\n    }\n\n    /// Issues a warning message, with more control over the warning attributes.\n    ///\n    /// May return a `PyErr` if warnings-as-errors is enabled.\n    ///\n    /// Equivalent to `warnings.warn_explicit()` in Python.\n    ///\n    /// The `category` should be one of the `Warning` classes available in\n    /// [`pyo3::exceptions`](crate::exceptions), or a subclass.\n    pub fn warn_explicit<'py>(\n        py: Python<'py>,\n        category: &Bound<'py, PyAny>,\n        message: &CStr,\n        filename: &CStr,\n        lineno: i32,\n        module: Option<&CStr>,\n        registry: Option<&Bound<'py, PyAny>>,\n    ) -> PyResult<()> {\n        let module_ptr = match module {\n            None => std::ptr::null_mut(),\n            Some(s) => s.as_ptr(),\n        };\n        let registry: *mut ffi::PyObject = match registry {\n            None => std::ptr::null_mut(),\n            Some(obj) => obj.as_ptr(),\n        };\n        error_on_minusone(py, unsafe {\n            ffi::PyErr_WarnExplicit(\n                category.as_ptr(),\n                message.as_ptr(),\n                filename.as_ptr(),\n                lineno,\n                module_ptr,\n                registry,\n            )\n        })\n    }\n\n    /// Clone the PyErr. This requires the GIL, which is why PyErr does not implement Clone.\n    ///\n    /// # Examples\n    /// ```rust\n    /// use pyo3::{exceptions::PyTypeError, PyErr, Python, prelude::PyAnyMethods};\n    /// Python::attach(|py| {\n    ///     let err: PyErr = PyTypeError::new_err((\"some type error\",));\n    ///     let err_clone = err.clone_ref(py);\n    ///     assert!(err.get_type(py).is(&err_clone.get_type(py)));\n    ///     assert!(err.value(py).is(err_clone.value(py)));\n    ///     match err.traceback(py) {\n    ///         None => assert!(err_clone.traceback(py).is_none()),\n    ///         Some(tb) => assert!(err_clone.traceback(py).unwrap().is(&tb)),\n    ///     }\n    /// });\n    /// ```\n    #[inline]\n    pub fn clone_ref(&self, py: Python<'_>) -> PyErr {\n        PyErr::from_state(PyErrState::normalized(self.normalized(py).clone_ref(py)))\n    }\n\n    /// Return the cause (either an exception instance, or None, set by `raise ... from ...`)\n    /// associated with the exception, as accessible from Python through `__cause__`.\n    pub fn cause(&self, py: Python<'_>) -> Option<PyErr> {\n        use crate::ffi_ptr_ext::FfiPtrExt;\n        let obj =\n            unsafe { ffi::PyException_GetCause(self.value(py).as_ptr()).assume_owned_or_opt(py) };\n        // PyException_GetCause is documented as potentially returning PyNone, but only GraalPy seems to actually do that\n        #[cfg(GraalPy)]\n        if let Some(cause) = &obj {\n            if cause.is_none() {\n                return None;\n            }\n        }\n        obj.map(Self::from_value)\n    }\n\n    /// Set the cause associated with the exception, pass `None` to clear it.\n    pub fn set_cause(&self, py: Python<'_>, cause: Option<Self>) {\n        let value = self.value(py);\n        let cause = cause.map(|err| err.into_value(py));\n        unsafe {\n            // PyException_SetCause _steals_ a reference to cause, so must use .into_ptr()\n            ffi::PyException_SetCause(\n                value.as_ptr(),\n                cause.map_or(std::ptr::null_mut(), Py::into_ptr),\n            );\n        }\n    }\n\n    /// Return the context (either an exception instance, or None, set by an implicit exception\n    /// during handling of another exception) associated with the exception, as accessible from\n    /// Python through `__context__`.\n    pub fn context(&self, py: Python<'_>) -> Option<PyErr> {\n        unsafe {\n            ffi::PyException_GetContext(self.value(py).as_ptr())\n                .assume_owned_or_opt(py)\n                .map(Self::from_value)\n        }\n    }\n\n    /// Set the context associated with the exception, pass `None` to clear it.\n    pub fn set_context(&self, py: Python<'_>, context: Option<PyErr>) {\n        let value = self.value(py);\n        let context = context.map(|err| err.into_value(py));\n        unsafe {\n            ffi::PyException_SetContext(\n                value.as_ptr(),\n                context.map_or(std::ptr::null_mut(), Py::into_ptr),\n            );\n        }\n    }\n\n    /// Equivalent to calling `add_note` on the exception in Python.\n    #[cfg(Py_3_11)]\n    pub fn add_note<N: for<'py> IntoPyObject<'py, Target = PyString>>(\n        &self,\n        py: Python<'_>,\n        note: N,\n    ) -> PyResult<()> {\n        self.value(py)\n            .call_method1(intern!(py, \"add_note\"), (note,))?;\n        Ok(())\n    }\n\n    #[inline]\n    fn from_state(state: PyErrState) -> PyErr {\n        PyErr { state }\n    }\n\n    #[inline]\n    fn normalized(&self, py: Python<'_>) -> &PyErrStateNormalized {\n        self.state.as_normalized(py)\n    }\n}\n\n/// Called when `PyErr::fetch` is called but no exception is set.\n#[cold]\n#[cfg_attr(debug_assertions, track_caller)]\nfn failed_to_fetch() -> PyErr {\n    const FAILED_TO_FETCH: &str = \"attempted to fetch exception but none was set\";\n\n    if cfg!(debug_assertions) {\n        panic!(\"{}\", FAILED_TO_FETCH)\n    } else {\n        crate::exceptions::PySystemError::new_err(FAILED_TO_FETCH)\n    }\n}\n\nimpl std::fmt::Debug for PyErr {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {\n        Python::attach(|py| {\n            f.debug_struct(\"PyErr\")\n                .field(\"type\", &self.get_type(py))\n                .field(\"value\", self.value(py))\n                .field(\n                    \"traceback\",\n                    &self.traceback(py).map(|tb| match tb.format() {\n                        Ok(s) => s,\n                        Err(err) => {\n                            err.write_unraisable(py, Some(&tb));\n                            // It would be nice to format what we can of the\n                            // error, but we can't guarantee that the error\n                            // won't have another unformattable traceback inside\n                            // it and we want to avoid an infinite recursion.\n                            format!(\"<unformattable {tb:?}>\")\n                        }\n                    }),\n                )\n                .finish()\n        })\n    }\n}\n\nimpl std::fmt::Display for PyErr {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        Python::attach(|py| {\n            let value = self.value(py);\n            let type_name = value.get_type().qualname().map_err(|_| std::fmt::Error)?;\n            write!(f, \"{type_name}\")?;\n            if let Ok(s) = value.str() {\n                write!(f, \": {}\", &s.to_string_lossy())\n            } else {\n                write!(f, \": <exception str() failed>\")\n            }\n        })\n    }\n}\n\nimpl std::error::Error for PyErr {}\n\nimpl<'py> IntoPyObject<'py> for PyErr {\n    type Target = PyBaseException;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyBaseException::TYPE_HINT;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.into_value(py).into_bound(py))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &PyErr {\n    type Target = PyBaseException;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyErr::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        self.clone_ref(py).into_pyobject(py)\n    }\n}\n\n/// Python exceptions that can be converted to [`PyErr`].\n///\n/// This is used to implement [`From<Bound<'_, T>> for PyErr`].\n///\n/// Users should not need to implement this trait directly. It is implemented automatically in the\n/// [`crate::import_exception!`] and [`crate::create_exception!`] macros.\npub trait ToPyErr {}\n\nimpl<'py, T> std::convert::From<Bound<'py, T>> for PyErr\nwhere\n    T: ToPyErr,\n{\n    #[inline]\n    fn from(err: Bound<'py, T>) -> PyErr {\n        PyErr::from_value(err.into_any())\n    }\n}\n\n/// Returns Ok if the error code is not -1.\n#[inline]\npub(crate) fn error_on_minusone<T: SignedInteger>(py: Python<'_>, result: T) -> PyResult<()> {\n    if result != T::MINUS_ONE {\n        Ok(())\n    } else {\n        Err(PyErr::fetch(py))\n    }\n}\n\npub(crate) trait SignedInteger: Eq {\n    const MINUS_ONE: Self;\n}\n\nmacro_rules! impl_signed_integer {\n    ($t:ty) => {\n        impl SignedInteger for $t {\n            const MINUS_ONE: Self = -1;\n        }\n    };\n}\n\nimpl_signed_integer!(i8);\nimpl_signed_integer!(i16);\nimpl_signed_integer!(i32);\nimpl_signed_integer!(i64);\nimpl_signed_integer!(i128);\nimpl_signed_integer!(isize);\n\n#[cfg(test)]\nmod tests {\n    use super::PyErrState;\n    use crate::exceptions::{self, PyTypeError, PyValueError};\n    use crate::impl_::pyclass::{value_of, IsSend, IsSync};\n    use crate::test_utils::assert_warnings;\n    use crate::{PyErr, PyTypeInfo, Python};\n\n    #[test]\n    fn no_error() {\n        assert!(Python::attach(PyErr::take).is_none());\n    }\n\n    #[test]\n    fn set_valueerror() {\n        Python::attach(|py| {\n            let err: PyErr = exceptions::PyValueError::new_err(\"some exception message\");\n            assert!(err.is_instance_of::<exceptions::PyValueError>(py));\n            err.restore(py);\n            assert!(PyErr::occurred(py));\n            let err = PyErr::fetch(py);\n            assert!(err.is_instance_of::<exceptions::PyValueError>(py));\n            assert_eq!(err.to_string(), \"ValueError: some exception message\");\n        })\n    }\n\n    #[test]\n    fn invalid_error_type() {\n        Python::attach(|py| {\n            let err: PyErr = PyErr::new::<crate::types::PyString, _>(());\n            assert!(err.is_instance_of::<exceptions::PyTypeError>(py));\n            err.restore(py);\n            let err = PyErr::fetch(py);\n\n            assert!(err.is_instance_of::<exceptions::PyTypeError>(py));\n            assert_eq!(\n                err.to_string(),\n                \"TypeError: exceptions must derive from BaseException\"\n            );\n        })\n    }\n\n    #[test]\n    fn set_typeerror() {\n        Python::attach(|py| {\n            let err: PyErr = exceptions::PyTypeError::new_err(());\n            err.restore(py);\n            assert!(PyErr::occurred(py));\n            drop(PyErr::fetch(py));\n        });\n    }\n\n    #[test]\n    #[should_panic(expected = \"new panic\")]\n    fn fetching_panic_exception_resumes_unwind() {\n        use crate::panic::PanicException;\n\n        Python::attach(|py| {\n            let err: PyErr = PanicException::new_err(\"new panic\");\n            err.restore(py);\n            assert!(PyErr::occurred(py));\n\n            // should resume unwind\n            let _ = PyErr::fetch(py);\n        });\n    }\n\n    #[test]\n    #[should_panic(expected = \"new panic\")]\n    #[cfg(not(Py_3_12))]\n    fn fetching_normalized_panic_exception_resumes_unwind() {\n        use crate::panic::PanicException;\n\n        Python::attach(|py| {\n            let err: PyErr = PanicException::new_err(\"new panic\");\n            // Restoring an error doesn't normalize it before Python 3.12,\n            // so we have to explicitly test this case.\n            let _ = err.normalized(py);\n            err.restore(py);\n            assert!(PyErr::occurred(py));\n\n            // should resume unwind\n            let _ = PyErr::fetch(py);\n        });\n    }\n\n    #[test]\n    fn err_debug() {\n        // Debug representation should be like the following (without the newlines):\n        // PyErr {\n        //     type: <class 'Exception'>,\n        //     value: Exception('banana'),\n        //     traceback:  Some(\\\"Traceback (most recent call last):\\\\n  File \\\\\\\"<string>\\\\\\\", line 1, in <module>\\\\n\\\")\n        // }\n\n        Python::attach(|py| {\n            let err = py\n                .run(c\"raise Exception('banana')\", None, None)\n                .expect_err(\"raising should have given us an error\");\n\n            let debug_str = format!(\"{err:?}\");\n            assert!(debug_str.starts_with(\"PyErr { \"));\n            assert!(debug_str.ends_with(\" }\"));\n\n            // Strip \"PyErr { \" and \" }\". Split into 3 substrings to separate type,\n            // value, and traceback while not splitting the string within traceback.\n            let mut fields = debug_str[\"PyErr { \".len()..debug_str.len() - 2].splitn(3, \", \");\n\n            assert_eq!(fields.next().unwrap(), \"type: <class 'Exception'>\");\n            assert_eq!(fields.next().unwrap(), \"value: Exception('banana')\");\n            assert_eq!(\n                fields.next().unwrap(),\n                \"traceback: Some(\\\"Traceback (most recent call last):\\\\n  File \\\\\\\"<string>\\\\\\\", line 1, in <module>\\\\n\\\")\"\n            );\n\n            assert!(fields.next().is_none());\n        });\n    }\n\n    #[test]\n    fn err_display() {\n        Python::attach(|py| {\n            let err = py\n                .run(c\"raise Exception('banana')\", None, None)\n                .expect_err(\"raising should have given us an error\");\n            assert_eq!(err.to_string(), \"Exception: banana\");\n        });\n    }\n\n    #[test]\n    fn test_pyerr_send_sync() {\n        assert!(value_of!(IsSend, PyErr));\n        assert!(value_of!(IsSync, PyErr));\n\n        assert!(value_of!(IsSend, PyErrState));\n        assert!(value_of!(IsSync, PyErrState));\n    }\n\n    #[test]\n    fn test_pyerr_matches() {\n        Python::attach(|py| {\n            let err = PyErr::new::<PyValueError, _>(\"foo\");\n            assert!(err.matches(py, PyValueError::type_object(py)).unwrap());\n\n            assert!(err\n                .matches(\n                    py,\n                    (PyValueError::type_object(py), PyTypeError::type_object(py))\n                )\n                .unwrap());\n\n            assert!(!err.matches(py, PyTypeError::type_object(py)).unwrap());\n\n            // String is not a valid exception class, so we should get a TypeError\n            let err: PyErr = PyErr::from_type(crate::types::PyString::type_object(py), \"foo\");\n            assert!(err.matches(py, PyTypeError::type_object(py)).unwrap());\n        })\n    }\n\n    #[test]\n    fn test_pyerr_cause() {\n        Python::attach(|py| {\n            let err = py\n                .run(c\"raise Exception('banana')\", None, None)\n                .expect_err(\"raising should have given us an error\");\n            assert!(err.cause(py).is_none());\n\n            let err = py\n                .run(\n                    c\"raise Exception('banana') from Exception('apple')\",\n                    None,\n                    None,\n                )\n                .expect_err(\"raising should have given us an error\");\n            let cause = err\n                .cause(py)\n                .expect(\"raising from should have given us a cause\");\n            assert_eq!(cause.to_string(), \"Exception: apple\");\n\n            err.set_cause(py, None);\n            assert!(err.cause(py).is_none());\n\n            let new_cause = exceptions::PyValueError::new_err(\"orange\");\n            err.set_cause(py, Some(new_cause));\n            let cause = err\n                .cause(py)\n                .expect(\"set_cause should have given us a cause\");\n            assert_eq!(cause.to_string(), \"ValueError: orange\");\n        });\n    }\n\n    #[test]\n    fn warnings() {\n        use crate::types::any::PyAnyMethods;\n        // Note: although the warning filter is interpreter global, keeping the\n        // GIL locked should prevent effects to be visible to other testing\n        // threads.\n        Python::attach(|py| {\n            let cls = py.get_type::<exceptions::PyUserWarning>();\n\n            // Reset warning filter to default state\n            let warnings = py.import(\"warnings\").unwrap();\n            warnings.call_method0(\"resetwarnings\").unwrap();\n\n            // First, test the warning is emitted\n            assert_warnings!(\n                py,\n                { PyErr::warn(py, &cls, c\"I am warning you\", 0).unwrap() },\n                [(exceptions::PyUserWarning, \"I am warning you\")]\n            );\n\n            // Test with raising\n            warnings\n                .call_method1(\"simplefilter\", (\"error\", &cls))\n                .unwrap();\n            PyErr::warn(py, &cls, c\"I am warning you\", 0).unwrap_err();\n\n            // Test with error for an explicit module\n            warnings.call_method0(\"resetwarnings\").unwrap();\n            warnings\n                .call_method1(\"filterwarnings\", (\"error\", \"\", &cls, \"pyo3test\"))\n                .unwrap();\n\n            // This has the wrong module and will not raise, just be emitted\n            assert_warnings!(\n                py,\n                { PyErr::warn(py, &cls, c\"I am warning you\", 0).unwrap() },\n                [(exceptions::PyUserWarning, \"I am warning you\")]\n            );\n\n            let err = PyErr::warn_explicit(\n                py,\n                &cls,\n                c\"I am warning you\",\n                c\"pyo3test.py\",\n                427,\n                None,\n                None,\n            )\n            .unwrap_err();\n            assert!(err\n                .value(py)\n                .getattr(\"args\")\n                .unwrap()\n                .get_item(0)\n                .unwrap()\n                .eq(\"I am warning you\")\n                .unwrap());\n\n            // Finally, reset filter again\n            warnings.call_method0(\"resetwarnings\").unwrap();\n        });\n    }\n\n    #[test]\n    #[cfg(Py_3_11)]\n    fn test_add_note() {\n        use crate::types::any::PyAnyMethods;\n        Python::attach(|py| {\n            let err = PyErr::new::<exceptions::PyValueError, _>(\"original error\");\n            err.add_note(py, \"additional context\").unwrap();\n\n            let notes = err.value(py).getattr(\"__notes__\").unwrap();\n            assert_eq!(notes.len().unwrap(), 1);\n            assert_eq!(\n                notes.get_item(0).unwrap().extract::<String>().unwrap(),\n                \"additional context\"\n            );\n        });\n    }\n\n    #[test]\n    fn test_set_context() {\n        Python::attach(|py| {\n            let err = PyErr::new::<PyValueError, _>(\"original error\");\n            assert!(err.context(py).is_none());\n\n            let context = PyErr::new::<PyTypeError, _>(\"context error\");\n            err.set_context(py, Some(context));\n            assert!(err.context(py).unwrap().is_instance_of::<PyTypeError>(py));\n\n            err.set_context(py, None);\n            assert!(err.context(py).is_none());\n        })\n    }\n}\n"
  },
  {
    "path": "src/exceptions.rs",
    "content": "//! Exception and warning types defined by Python.\n//!\n//! The structs in this module represent Python's built-in exceptions and\n//! warnings, while the modules comprise structs representing errors defined in\n//! Python code.\n//!\n//! The latter are created with the\n//! [`import_exception`](crate::import_exception) macro, which you can use\n//! yourself to import Python classes that are ultimately derived from\n//! `BaseException`.\n\nuse crate::{ffi, Bound, PyResult, Python};\nuse std::ffi::CStr;\nuse std::ops;\n\n/// The boilerplate to convert between a Rust type and a Python exception.\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! impl_exception_boilerplate {\n    ($name: ident) => {\n        impl $name {\n            /// Creates a new [`PyErr`] of this type.\n            ///\n            /// [`PyErr`]: https://docs.rs/pyo3/latest/pyo3/struct.PyErr.html \"PyErr in pyo3\"\n            #[inline]\n            #[allow(dead_code, reason = \"user may not call this function\")]\n            pub fn new_err<A>(args: A) -> $crate::PyErr\n            where\n                A: $crate::PyErrArguments + ::std::marker::Send + ::std::marker::Sync + 'static,\n            {\n                $crate::PyErr::new::<$name, A>(args)\n            }\n        }\n\n        impl $crate::ToPyErr for $name {}\n    };\n}\n\n/// Defines a Rust type for an exception defined in Python code.\n///\n/// # Syntax\n///\n/// ```import_exception!(module, MyError)```\n///\n/// * `module` is the name of the containing module.\n/// * `MyError` is the name of the new exception type.\n///\n/// # Examples\n/// ```\n/// use pyo3::import_exception;\n/// use pyo3::types::IntoPyDict;\n/// use pyo3::Python;\n///\n/// import_exception!(socket, gaierror);\n///\n/// # fn main() -> pyo3::PyResult<()> {\n/// Python::attach(|py| {\n///     let ctx = [(\"gaierror\", py.get_type::<gaierror>())].into_py_dict(py)?;\n///     pyo3::py_run!(py, *ctx, \"import socket; assert gaierror is socket.gaierror\");\n/// #   Ok(())\n/// })\n/// # }\n///\n/// ```\n#[macro_export]\nmacro_rules! import_exception {\n    ($module: expr, $name: ident) => {\n        /// A Rust type representing an exception defined in Python code.\n        ///\n        /// This type was created by the [`pyo3::import_exception!`] macro - see its documentation\n        /// for more information.\n        ///\n        /// [`pyo3::import_exception!`]: https://docs.rs/pyo3/latest/pyo3/macro.import_exception.html \"import_exception in pyo3\"\n        #[repr(transparent)]\n        #[allow(non_camel_case_types, reason = \"matches imported exception name, e.g. `socket.herror`\")]\n        pub struct $name($crate::PyAny);\n\n        $crate::impl_exception_boilerplate!($name);\n\n        $crate::pyobject_native_type_core!(\n            $name,\n            $name::type_object_raw,\n            stringify!($name),\n            stringify!($module),\n            #module=::std::option::Option::Some(stringify!($module))\n        );\n\n        impl $name {\n            fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject {\n                use $crate::types::PyTypeMethods;\n                static TYPE_OBJECT: $crate::impl_::exceptions::ImportedExceptionTypeObject =\n                    $crate::impl_::exceptions::ImportedExceptionTypeObject::new(stringify!($module), stringify!($name));\n                TYPE_OBJECT.get(py).as_type_ptr()\n            }\n        }\n    };\n}\n\n/// Deprecated name for `import_exception!`.\n#[macro_export]\n#[deprecated(since = \"0.27.0\", note = \"renamed to `import_exception!` instead\")]\nmacro_rules! import_exception_bound {\n    ($module: expr, $name: ident) => {\n        $crate::import_exception!($module, $name);\n    };\n}\n\n/// Defines a new exception type.\n///\n/// # Syntax\n///\n/// * `module` is the name of the containing module.\n/// * `name` is the name of the new exception type.\n/// * `base` is the base class of `MyError`, usually [`PyException`].\n/// * `doc` (optional) is the docstring visible to users (with `.__doc__` and `help()`) and\n///\n/// accompanies your error type in your crate's documentation.\n///\n/// # Examples\n///\n/// ```\n/// use pyo3::prelude::*;\n/// use pyo3::create_exception;\n/// use pyo3::exceptions::PyException;\n///\n/// create_exception!(my_module, MyError, PyException, \"Some description.\");\n///\n/// #[pyfunction]\n/// fn raise_myerror() -> PyResult<()> {\n///     let err = MyError::new_err(\"Some error happened.\");\n///     Err(err)\n/// }\n///\n/// #[pymodule]\n/// fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n///     m.add(\"MyError\", m.py().get_type::<MyError>())?;\n///     m.add_function(wrap_pyfunction!(raise_myerror, m)?)?;\n///     Ok(())\n/// }\n/// # fn main() -> PyResult<()> {\n/// #     Python::attach(|py| -> PyResult<()> {\n/// #         let fun = wrap_pyfunction!(raise_myerror, py)?;\n/// #         let locals = pyo3::types::PyDict::new(py);\n/// #         locals.set_item(\"MyError\", py.get_type::<MyError>())?;\n/// #         locals.set_item(\"raise_myerror\", fun)?;\n/// #\n/// #         py.run(\n/// # c\"try:\n/// #     raise_myerror()\n/// # except MyError as e:\n/// #     assert e.__doc__ == 'Some description.'\n/// #     assert str(e) == 'Some error happened.'\",\n/// #             None,\n/// #             Some(&locals),\n/// #         )?;\n/// #\n/// #         Ok(())\n/// #     })\n/// # }\n/// ```\n///\n/// Python code can handle this exception like any other exception:\n///\n/// ```python\n/// from my_module import MyError, raise_myerror\n///\n/// try:\n///     raise_myerror()\n/// except MyError as e:\n///     assert e.__doc__ == 'Some description.'\n///     assert str(e) == 'Some error happened.'\n/// ```\n///\n#[macro_export]\nmacro_rules! create_exception {\n    ($module: expr, $name: ident, $base: ty) => {\n        #[repr(transparent)]\n        pub struct $name($crate::PyAny);\n\n        $crate::impl_exception_boilerplate!($name);\n\n        $crate::create_exception_type_object!($module, $name, $base, None);\n    };\n    ($module: expr, $name: ident, $base: ty, $doc: expr) => {\n        #[repr(transparent)]\n        #[doc = $doc]\n        pub struct $name($crate::PyAny);\n\n        $crate::impl_exception_boilerplate!($name);\n\n        $crate::create_exception_type_object!($module, $name, $base, Some($doc));\n    };\n}\n\n/// `impl PyTypeInfo for $name` where `$name` is an\n/// exception newly defined in Rust code.\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! create_exception_type_object {\n    ($module: expr, $name: ident, $base: ty, None) => {\n        $crate::create_exception_type_object!($module, $name, $base, ::std::option::Option::None);\n    };\n    ($module: expr, $name: ident, $base: ty, Some($doc: expr)) => {\n        $crate::create_exception_type_object!(\n            $module,\n            $name,\n            $base,\n            ::std::option::Option::Some($crate::ffi::c_str!($doc))\n        );\n    };\n    ($module: expr, $name: ident, $base: ty, $doc: expr) => {\n        $crate::pyobject_native_type_named!($name);\n\n        // SAFETY: macro caller has upheld the safety contracts\n        unsafe impl $crate::type_object::PyTypeInfo for $name {\n            const NAME: &'static str = stringify!($name);\n            const MODULE: ::std::option::Option<&'static str> =\n                ::std::option::Option::Some(stringify!($module));\n            $crate::create_exception_type_hint!($module, $name);\n\n            #[inline]\n            #[allow(clippy::redundant_closure_call)]\n            fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject {\n                use $crate::sync::PyOnceLock;\n                static TYPE_OBJECT: PyOnceLock<$crate::Py<$crate::types::PyType>> =\n                    PyOnceLock::new();\n\n                TYPE_OBJECT\n                    .get_or_init(py, || {\n                        $crate::PyErr::new_type(\n                            py,\n                            $crate::ffi::c_str!(concat!(\n                                stringify!($module),\n                                \".\",\n                                stringify!($name)\n                            )),\n                            $doc,\n                            ::std::option::Option::Some(&py.get_type::<$base>()),\n                            ::std::option::Option::None,\n                        )\n                        .expect(\"Failed to initialize new exception type.\")\n                    })\n                    .as_ptr()\n                    .cast()\n            }\n        }\n\n        impl $name {\n            #[doc(hidden)]\n            pub const _PYO3_DEF: $crate::impl_::pymodule::AddTypeToModule<Self> =\n                $crate::impl_::pymodule::AddTypeToModule::new();\n\n            #[allow(dead_code)]\n            #[doc(hidden)]\n            pub const _PYO3_INTROSPECTION_ID: &'static str =\n                concat!(stringify!($module), stringify!($name));\n        }\n    };\n}\n\n/// Adds a TYPE_HINT constant if the `experimental-inspect`  feature is enabled.\n#[cfg(not(feature = \"experimental-inspect\"))]\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! create_exception_type_hint(\n    ($module: expr, $name: ident) => {};\n);\n\n#[cfg(feature = \"experimental-inspect\")]\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! create_exception_type_hint(\n    ($module: expr, $name: ident) => {\n        const TYPE_HINT: $crate::inspect::PyStaticExpr = $crate::inspect::PyStaticExpr::PyClass($crate::inspect::PyClassNameStaticExpr::new(\n            &$crate::type_hint_identifier!(stringify!($module), stringify!($name)),\n            Self::_PYO3_INTROSPECTION_ID\n        ));\n    };\n);\n\nmacro_rules! impl_native_exception (\n    ($name:ident, $exc_name:ident, $python_name:expr, $doc:expr, $layout:path $(, #checkfunction=$checkfunction:path)?) => (\n        #[doc = $doc]\n        #[repr(transparent)]\n        #[allow(clippy::upper_case_acronyms, reason = \"Python exception names\")]\n        pub struct $name($crate::PyAny);\n\n        $crate::impl_exception_boilerplate!($name);\n        $crate::pyobject_native_type!($name, $layout, |_py| unsafe { $crate::ffi::$exc_name as *mut $crate::ffi::PyTypeObject }, \"builtins\", $python_name $(, #checkfunction=$checkfunction)?);\n        $crate::pyobject_subclassable_native_type!($name, $layout);\n    );\n    ($name:ident, $exc_name:ident, $python_name:expr, $doc:expr) => (\n        impl_native_exception!($name, $exc_name, $python_name, $doc, $crate::ffi::PyBaseExceptionObject);\n    )\n);\n\nmacro_rules! native_doc(\n    ($name: literal, $alt: literal) => (\n        concat!(\n\"Represents Python's [`\", $name, \"`](https://docs.python.org/3/library/exceptions.html#\", $name, \") exception.\n\n\", $alt\n        )\n    );\n    ($name: literal) => (\n        concat!(\n\"\nRepresents Python's [`\", $name, \"`](https://docs.python.org/3/library/exceptions.html#\", $name, \") exception.\n\n# Example: Raising \", $name, \" from Rust\n\nThis exception can be sent to Python code by converting it into a\n[`PyErr`](crate::PyErr), where Python code can then catch it.\n```\nuse pyo3::prelude::*;\nuse pyo3::exceptions::Py\", $name, \";\n\n#[pyfunction]\nfn always_throws() -> PyResult<()> {\n    let message = \\\"I'm \", $name ,\", and I was raised from Rust.\\\";\n    Err(Py\", $name, \"::new_err(message))\n}\n#\n# Python::attach(|py| {\n#     let fun = pyo3::wrap_pyfunction!(always_throws, py).unwrap();\n#     let err = fun.call0().expect_err(\\\"called a function that should always return an error but the return value was Ok\\\");\n#     assert!(err.is_instance_of::<Py\", $name, \">(py))\n# });\n```\n\nPython code:\n ```python\n from my_module import always_throws\n\ntry:\n    always_throws()\nexcept \", $name, \" as e:\n    print(f\\\"Caught an exception: {e}\\\")\n```\n\n# Example: Catching \", $name, \" in Rust\n\n```\nuse pyo3::prelude::*;\nuse pyo3::exceptions::Py\", $name, \";\nuse pyo3::ffi::c_str;\n\nPython::attach(|py| {\n    let result: PyResult<()> = py.run(c_str!(\\\"raise \", $name, \"\\\"), None, None);\n\n    let error_type = match result {\n        Ok(_) => \\\"Not an error\\\",\n        Err(error) if error.is_instance_of::<Py\", $name, \">(py) => \\\"\" , $name, \"\\\",\n        Err(_) => \\\"Some other error\\\",\n    };\n\n    assert_eq!(error_type, \\\"\", $name, \"\\\");\n});\n```\n\"\n        )\n    );\n);\n\nimpl_native_exception!(\n    PyBaseException,\n    PyExc_BaseException,\n    \"BaseException\",\n    native_doc!(\"BaseException\"),\n    ffi::PyBaseExceptionObject,\n    #checkfunction=ffi::PyExceptionInstance_Check\n);\nimpl_native_exception!(\n    PyException,\n    PyExc_Exception,\n    \"Exception\",\n    native_doc!(\"Exception\")\n);\nimpl_native_exception!(\n    PyStopAsyncIteration,\n    PyExc_StopAsyncIteration,\n    \"StopAsyncIteration\",\n    native_doc!(\"StopAsyncIteration\")\n);\nimpl_native_exception!(\n    PyStopIteration,\n    PyExc_StopIteration,\n    \"StopIteration\",\n    native_doc!(\"StopIteration\"),\n    ffi::PyStopIterationObject\n);\nimpl_native_exception!(\n    PyGeneratorExit,\n    PyExc_GeneratorExit,\n    \"GeneratorExit\",\n    native_doc!(\"GeneratorExit\")\n);\nimpl_native_exception!(\n    PyArithmeticError,\n    PyExc_ArithmeticError,\n    \"ArithmeticError\",\n    native_doc!(\"ArithmeticError\")\n);\nimpl_native_exception!(\n    PyLookupError,\n    PyExc_LookupError,\n    \"LookupError\",\n    native_doc!(\"LookupError\")\n);\n\nimpl_native_exception!(\n    PyAssertionError,\n    PyExc_AssertionError,\n    \"AssertionError\",\n    native_doc!(\"AssertionError\")\n);\nimpl_native_exception!(\n    PyAttributeError,\n    PyExc_AttributeError,\n    \"AttributeError\",\n    native_doc!(\"AttributeError\")\n);\nimpl_native_exception!(\n    PyBufferError,\n    PyExc_BufferError,\n    \"BufferError\",\n    native_doc!(\"BufferError\")\n);\nimpl_native_exception!(\n    PyEOFError,\n    PyExc_EOFError,\n    \"EOFError\",\n    native_doc!(\"EOFError\")\n);\nimpl_native_exception!(\n    PyFloatingPointError,\n    PyExc_FloatingPointError,\n    \"FloatingPointError\",\n    native_doc!(\"FloatingPointError\")\n);\n#[cfg(not(any(PyPy, GraalPy)))]\nimpl_native_exception!(\n    PyOSError,\n    PyExc_OSError,\n    \"OSError\",\n    native_doc!(\"OSError\"),\n    ffi::PyOSErrorObject\n);\n#[cfg(any(PyPy, GraalPy))]\nimpl_native_exception!(PyOSError, PyExc_OSError, \"OSError\", native_doc!(\"OSError\"));\nimpl_native_exception!(\n    PyImportError,\n    PyExc_ImportError,\n    \"ImportError\",\n    native_doc!(\"ImportError\")\n);\n\nimpl_native_exception!(\n    PyModuleNotFoundError,\n    PyExc_ModuleNotFoundError,\n    \"ModuleNotFoundError\",\n    native_doc!(\"ModuleNotFoundError\")\n);\n\nimpl_native_exception!(\n    PyIndexError,\n    PyExc_IndexError,\n    \"IndexError\",\n    native_doc!(\"IndexError\")\n);\nimpl_native_exception!(\n    PyKeyError,\n    PyExc_KeyError,\n    \"KeyError\",\n    native_doc!(\"KeyError\")\n);\nimpl_native_exception!(\n    PyKeyboardInterrupt,\n    PyExc_KeyboardInterrupt,\n    \"KeyboardInterrupt\",\n    native_doc!(\"KeyboardInterrupt\")\n);\nimpl_native_exception!(\n    PyMemoryError,\n    PyExc_MemoryError,\n    \"MemoryError\",\n    native_doc!(\"MemoryError\")\n);\nimpl_native_exception!(\n    PyNameError,\n    PyExc_NameError,\n    \"NameError\",\n    native_doc!(\"NameError\")\n);\nimpl_native_exception!(\n    PyOverflowError,\n    PyExc_OverflowError,\n    \"OverflowError\",\n    native_doc!(\"OverflowError\")\n);\nimpl_native_exception!(\n    PyRuntimeError,\n    PyExc_RuntimeError,\n    \"RuntimeError\",\n    native_doc!(\"RuntimeError\")\n);\nimpl_native_exception!(\n    PyRecursionError,\n    PyExc_RecursionError,\n    \"RecursionError\",\n    native_doc!(\"RecursionError\")\n);\nimpl_native_exception!(\n    PyNotImplementedError,\n    PyExc_NotImplementedError,\n    \"NotImplementedError\",\n    native_doc!(\"NotImplementedError\")\n);\n#[cfg(not(any(PyPy, GraalPy)))]\nimpl_native_exception!(\n    PySyntaxError,\n    PyExc_SyntaxError,\n    \"SyntaxError\",\n    native_doc!(\"SyntaxError\"),\n    ffi::PySyntaxErrorObject\n);\n#[cfg(any(PyPy, GraalPy))]\nimpl_native_exception!(\n    PySyntaxError,\n    PyExc_SyntaxError,\n    \"SyntaxError\",\n    native_doc!(\"SyntaxError\")\n);\nimpl_native_exception!(\n    PyReferenceError,\n    PyExc_ReferenceError,\n    \"ReferenceError\",\n    native_doc!(\"ReferenceError\")\n);\nimpl_native_exception!(\n    PySystemError,\n    PyExc_SystemError,\n    \"SystemError\",\n    native_doc!(\"SystemError\")\n);\n#[cfg(not(any(PyPy, GraalPy)))]\nimpl_native_exception!(\n    PySystemExit,\n    PyExc_SystemExit,\n    \"SystemExit\",\n    native_doc!(\"SystemExit\"),\n    ffi::PySystemExitObject\n);\n#[cfg(any(PyPy, GraalPy))]\nimpl_native_exception!(\n    PySystemExit,\n    PyExc_SystemExit,\n    \"SystemExit\",\n    native_doc!(\"SystemExit\")\n);\nimpl_native_exception!(\n    PyTypeError,\n    PyExc_TypeError,\n    \"TypeError\",\n    native_doc!(\"TypeError\")\n);\nimpl_native_exception!(\n    PyUnboundLocalError,\n    PyExc_UnboundLocalError,\n    \"UnboundLocalError\",\n    native_doc!(\"UnboundLocalError\")\n);\n#[cfg(not(any(PyPy, GraalPy)))]\nimpl_native_exception!(\n    PyUnicodeError,\n    PyExc_UnicodeError,\n    \"UnicodeError\",\n    native_doc!(\"UnicodeError\"),\n    ffi::PyUnicodeErrorObject\n);\n#[cfg(any(PyPy, GraalPy))]\nimpl_native_exception!(\n    PyUnicodeError,\n    PyExc_UnicodeError,\n    \"UnicodeError\",\n    native_doc!(\"UnicodeError\")\n);\n// these four errors need arguments, so they're too annoying to write tests for using macros...\nimpl_native_exception!(\n    PyUnicodeDecodeError,\n    PyExc_UnicodeDecodeError,\n    \"UnicodeDecodeError\",\n    native_doc!(\"UnicodeDecodeError\", \"\")\n);\nimpl_native_exception!(\n    PyUnicodeEncodeError,\n    PyExc_UnicodeEncodeError,\n    \"UnicodeEncodeError\",\n    native_doc!(\"UnicodeEncodeError\", \"\")\n);\nimpl_native_exception!(\n    PyUnicodeTranslateError,\n    PyExc_UnicodeTranslateError,\n    \"UnicodeTranslateError\",\n    native_doc!(\"UnicodeTranslateError\", \"\")\n);\n#[cfg(Py_3_11)]\nimpl_native_exception!(\n    PyBaseExceptionGroup,\n    PyExc_BaseExceptionGroup,\n    \"BaseExceptionGroup\",\n    native_doc!(\"BaseExceptionGroup\", \"\")\n);\nimpl_native_exception!(\n    PyValueError,\n    PyExc_ValueError,\n    \"ValueError\",\n    native_doc!(\"ValueError\")\n);\nimpl_native_exception!(\n    PyZeroDivisionError,\n    PyExc_ZeroDivisionError,\n    \"ZeroDivisionError\",\n    native_doc!(\"ZeroDivisionError\")\n);\n\nimpl_native_exception!(\n    PyBlockingIOError,\n    PyExc_BlockingIOError,\n    \"BlockingIOError\",\n    native_doc!(\"BlockingIOError\")\n);\nimpl_native_exception!(\n    PyBrokenPipeError,\n    PyExc_BrokenPipeError,\n    \"BrokenPipeError\",\n    native_doc!(\"BrokenPipeError\")\n);\nimpl_native_exception!(\n    PyChildProcessError,\n    PyExc_ChildProcessError,\n    \"ChildProcessError\",\n    native_doc!(\"ChildProcessError\")\n);\nimpl_native_exception!(\n    PyConnectionError,\n    PyExc_ConnectionError,\n    \"ConnectionError\",\n    native_doc!(\"ConnectionError\")\n);\nimpl_native_exception!(\n    PyConnectionAbortedError,\n    PyExc_ConnectionAbortedError,\n    \"ConnectionAbortedError\",\n    native_doc!(\"ConnectionAbortedError\")\n);\nimpl_native_exception!(\n    PyConnectionRefusedError,\n    PyExc_ConnectionRefusedError,\n    \"ConnectionRefusedError\",\n    native_doc!(\"ConnectionRefusedError\")\n);\nimpl_native_exception!(\n    PyConnectionResetError,\n    PyExc_ConnectionResetError,\n    \"ConnectionResetError\",\n    native_doc!(\"ConnectionResetError\")\n);\nimpl_native_exception!(\n    PyFileExistsError,\n    PyExc_FileExistsError,\n    \"FileExistsError\",\n    native_doc!(\"FileExistsError\")\n);\nimpl_native_exception!(\n    PyFileNotFoundError,\n    PyExc_FileNotFoundError,\n    \"FileNotFoundError\",\n    native_doc!(\"FileNotFoundError\")\n);\nimpl_native_exception!(\n    PyInterruptedError,\n    PyExc_InterruptedError,\n    \"InterruptedError\",\n    native_doc!(\"InterruptedError\")\n);\nimpl_native_exception!(\n    PyIsADirectoryError,\n    PyExc_IsADirectoryError,\n    \"IsADirectoryError\",\n    native_doc!(\"IsADirectoryError\")\n);\nimpl_native_exception!(\n    PyNotADirectoryError,\n    PyExc_NotADirectoryError,\n    \"NotADirectoryError\",\n    native_doc!(\"NotADirectoryError\")\n);\nimpl_native_exception!(\n    PyPermissionError,\n    PyExc_PermissionError,\n    \"PermissionError\",\n    native_doc!(\"PermissionError\")\n);\nimpl_native_exception!(\n    PyProcessLookupError,\n    PyExc_ProcessLookupError,\n    \"ProcessLookupError\",\n    native_doc!(\"ProcessLookupError\")\n);\nimpl_native_exception!(\n    PyTimeoutError,\n    PyExc_TimeoutError,\n    \"TimeoutError\",\n    native_doc!(\"TimeoutError\")\n);\n\n/// Alias of `PyOSError`, corresponding to `EnvironmentError` alias in Python.\npub type PyEnvironmentError = PyOSError;\n\n/// Alias of `PyOSError`, corresponding to `IOError` alias in Python.\npub type PyIOError = PyOSError;\n\n#[cfg(windows)]\n/// Alias of `PyOSError`, corresponding to `WindowsError` alias in Python.\npub type PyWindowsError = PyOSError;\n\nimpl PyUnicodeDecodeError {\n    /// Creates a Python `UnicodeDecodeError`.\n    pub fn new<'py>(\n        py: Python<'py>,\n        encoding: &CStr,\n        input: &[u8],\n        range: ops::Range<usize>,\n        reason: &CStr,\n    ) -> PyResult<Bound<'py, PyUnicodeDecodeError>> {\n        use crate::ffi_ptr_ext::FfiPtrExt;\n        use crate::py_result_ext::PyResultExt;\n        unsafe {\n            ffi::PyUnicodeDecodeError_Create(\n                encoding.as_ptr(),\n                input.as_ptr().cast(),\n                input.len() as ffi::Py_ssize_t,\n                range.start as ffi::Py_ssize_t,\n                range.end as ffi::Py_ssize_t,\n                reason.as_ptr(),\n            )\n            .assume_owned_or_err(py)\n        }\n        .cast_into()\n    }\n\n    /// Creates a Python `UnicodeDecodeError` from a Rust UTF-8 decoding error.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use pyo3::prelude::*;\n    /// use pyo3::exceptions::PyUnicodeDecodeError;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let invalid_utf8 = b\"fo\\xd8o\";\n    /// #   #[expect(invalid_from_utf8)]\n    ///     let err = std::str::from_utf8(invalid_utf8).expect_err(\"should be invalid utf8\");\n    ///     let decode_err = PyUnicodeDecodeError::new_utf8(py, invalid_utf8, err)?;\n    ///     assert_eq!(\n    ///         decode_err.to_string(),\n    ///         \"'utf-8' codec can't decode byte 0xd8 in position 2: invalid utf-8\"\n    ///     );\n    ///     Ok(())\n    /// })\n    /// # }\n    pub fn new_utf8<'py>(\n        py: Python<'py>,\n        input: &[u8],\n        err: std::str::Utf8Error,\n    ) -> PyResult<Bound<'py, PyUnicodeDecodeError>> {\n        let start = err.valid_up_to();\n        let end = err.error_len().map_or(input.len(), |l| start + l);\n        PyUnicodeDecodeError::new(py, c\"utf-8\", input, start..end, c\"invalid utf-8\")\n    }\n\n    /// Create a new [`PyErr`](crate::PyErr) of this type from a Rust UTF-8 decoding error.\n    ///\n    /// This is equivalent to [`PyUnicodeDecodeError::new_utf8`], but returning a\n    /// [`PyErr`](crate::PyErr) instead of an exception object.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// use pyo3::prelude::*;\n    /// use pyo3::exceptions::PyUnicodeDecodeError;\n    ///\n    /// Python::attach(|py| {\n    ///     let invalid_utf8 = b\"fo\\xd8o\";\n    ///     # #[expect(invalid_from_utf8)]\n    ///     let err = std::str::from_utf8(invalid_utf8).expect_err(\"should be invalid utf8\");\n    ///     let py_err = PyUnicodeDecodeError::new_err_from_utf8(py, invalid_utf8, err);\n    /// })\n    /// ```\n    pub fn new_err_from_utf8(\n        py: Python<'_>,\n        bytes: &[u8],\n        err: std::str::Utf8Error,\n    ) -> crate::PyErr {\n        match Self::new_utf8(py, bytes, err) {\n            Ok(e) => crate::PyErr::from_value(e.into_any()),\n            Err(e) => e,\n        }\n    }\n}\n\nimpl_native_exception!(PyWarning, PyExc_Warning, \"Warning\", native_doc!(\"Warning\"));\nimpl_native_exception!(\n    PyUserWarning,\n    PyExc_UserWarning,\n    \"UserWarning\",\n    native_doc!(\"UserWarning\")\n);\nimpl_native_exception!(\n    PyDeprecationWarning,\n    PyExc_DeprecationWarning,\n    \"DeprecationWarning\",\n    native_doc!(\"DeprecationWarning\")\n);\nimpl_native_exception!(\n    PyPendingDeprecationWarning,\n    PyExc_PendingDeprecationWarning,\n    \"PendingDeprecationWarning\",\n    native_doc!(\"PendingDeprecationWarning\")\n);\nimpl_native_exception!(\n    PySyntaxWarning,\n    PyExc_SyntaxWarning,\n    \"SyntaxWarning\",\n    native_doc!(\"SyntaxWarning\")\n);\nimpl_native_exception!(\n    PyRuntimeWarning,\n    PyExc_RuntimeWarning,\n    \"RuntimeWarning\",\n    native_doc!(\"RuntimeWarning\")\n);\nimpl_native_exception!(\n    PyFutureWarning,\n    PyExc_FutureWarning,\n    \"FutureWarning\",\n    native_doc!(\"FutureWarning\")\n);\nimpl_native_exception!(\n    PyImportWarning,\n    PyExc_ImportWarning,\n    \"ImportWarning\",\n    native_doc!(\"ImportWarning\")\n);\nimpl_native_exception!(\n    PyUnicodeWarning,\n    PyExc_UnicodeWarning,\n    \"UnicodeWarning\",\n    native_doc!(\"UnicodeWarning\")\n);\nimpl_native_exception!(\n    PyBytesWarning,\n    PyExc_BytesWarning,\n    \"BytesWarning\",\n    native_doc!(\"BytesWarning\")\n);\nimpl_native_exception!(\n    PyResourceWarning,\n    PyExc_ResourceWarning,\n    \"ResourceWarning\",\n    native_doc!(\"ResourceWarning\")\n);\n\n#[cfg(Py_3_10)]\nimpl_native_exception!(\n    PyEncodingWarning,\n    PyExc_EncodingWarning,\n    \"EncodingWarning\",\n    native_doc!(\"EncodingWarning\")\n);\n\n#[cfg(test)]\nmacro_rules! test_exception {\n    ($exc_ty:ident $(, |$py:tt| $constructor:expr )?) => {\n        #[allow(non_snake_case, reason = \"test matches exception name\")]\n        #[test]\n        fn $exc_ty () {\n            use super::$exc_ty;\n\n            $crate::Python::attach(|py| {\n                let err: $crate::PyErr = {\n                    None\n                    $(\n                        .or(Some({ let $py = py; $constructor }))\n                    )?\n                        .unwrap_or($exc_ty::new_err(\"a test exception\"))\n                };\n\n                assert!(err.is_instance_of::<$exc_ty>(py));\n\n                let value = err.value(py).as_any().cast::<$exc_ty>().unwrap();\n\n                assert!($crate::PyErr::from(value.clone()).is_instance_of::<$exc_ty>(py));\n            })\n        }\n    };\n}\n\n/// Exceptions defined in Python's [`asyncio`](https://docs.python.org/3/library/asyncio.html)\n/// module.\npub mod asyncio {\n    import_exception!(asyncio, CancelledError);\n    import_exception!(asyncio, InvalidStateError);\n    import_exception!(asyncio, TimeoutError);\n    import_exception!(asyncio, IncompleteReadError);\n    import_exception!(asyncio, LimitOverrunError);\n    import_exception!(asyncio, QueueEmpty);\n    import_exception!(asyncio, QueueFull);\n\n    #[cfg(test)]\n    mod tests {\n        test_exception!(CancelledError);\n        test_exception!(InvalidStateError);\n        test_exception!(TimeoutError);\n        test_exception!(IncompleteReadError, |_| IncompleteReadError::new_err((\n            \"partial\", \"expected\"\n        )));\n        test_exception!(LimitOverrunError, |_| LimitOverrunError::new_err((\n            \"message\", \"consumed\"\n        )));\n        test_exception!(QueueEmpty);\n        test_exception!(QueueFull);\n    }\n}\n\n/// Exceptions defined in Python's [`socket`](https://docs.python.org/3/library/socket.html)\n/// module.\npub mod socket {\n    import_exception!(socket, herror);\n    import_exception!(socket, gaierror);\n    import_exception!(socket, timeout);\n\n    #[cfg(test)]\n    mod tests {\n        test_exception!(herror);\n        test_exception!(gaierror);\n        test_exception!(timeout);\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::any::PyAnyMethods;\n    use crate::types::{IntoPyDict, PyDict};\n    use crate::{IntoPyObjectExt as _, PyErr};\n\n    import_exception!(socket, gaierror);\n    import_exception!(email.errors, MessageError);\n\n    #[test]\n    fn test_check_exception() {\n        Python::attach(|py| {\n            let err: PyErr = gaierror::new_err(());\n            let socket = py\n                .import(\"socket\")\n                .map_err(|e| e.display(py))\n                .expect(\"could not import socket\");\n\n            let d = PyDict::new(py);\n            d.set_item(\"socket\", socket)\n                .map_err(|e| e.display(py))\n                .expect(\"could not setitem\");\n\n            d.set_item(\"exc\", err)\n                .map_err(|e| e.display(py))\n                .expect(\"could not setitem\");\n\n            py.run(c\"assert isinstance(exc, socket.gaierror)\", None, Some(&d))\n                .map_err(|e| e.display(py))\n                .expect(\"assertion failed\");\n        });\n    }\n\n    #[test]\n    fn test_check_exception_nested() {\n        Python::attach(|py| {\n            let err: PyErr = MessageError::new_err(());\n            let email = py\n                .import(\"email\")\n                .map_err(|e| e.display(py))\n                .expect(\"could not import email\");\n\n            let d = PyDict::new(py);\n            d.set_item(\"email\", email)\n                .map_err(|e| e.display(py))\n                .expect(\"could not setitem\");\n            d.set_item(\"exc\", err)\n                .map_err(|e| e.display(py))\n                .expect(\"could not setitem\");\n\n            py.run(\n                c\"assert isinstance(exc, email.errors.MessageError)\",\n                None,\n                Some(&d),\n            )\n            .map_err(|e| e.display(py))\n            .expect(\"assertion failed\");\n        });\n    }\n\n    #[test]\n    fn custom_exception() {\n        create_exception!(mymodule, CustomError, PyException);\n\n        Python::attach(|py| {\n            let error_type = py.get_type::<CustomError>();\n            let ctx = [(\"CustomError\", error_type)].into_py_dict(py).unwrap();\n            let type_description: String = py\n                .eval(c\"str(CustomError)\", None, Some(&ctx))\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(type_description, \"<class 'mymodule.CustomError'>\");\n            py.run(\n                c\"assert CustomError('oops').args == ('oops',)\",\n                None,\n                Some(&ctx),\n            )\n            .unwrap();\n            py.run(c\"assert CustomError.__doc__ is None\", None, Some(&ctx))\n                .unwrap();\n        });\n    }\n\n    #[test]\n    fn custom_exception_dotted_module() {\n        create_exception!(mymodule.exceptions, CustomError, PyException);\n        Python::attach(|py| {\n            let error_type = py.get_type::<CustomError>();\n            let ctx = [(\"CustomError\", error_type)].into_py_dict(py).unwrap();\n            let type_description: String = py\n                .eval(c\"str(CustomError)\", None, Some(&ctx))\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(\n                type_description,\n                \"<class 'mymodule.exceptions.CustomError'>\"\n            );\n        });\n    }\n\n    #[test]\n    fn custom_exception_doc() {\n        create_exception!(mymodule, CustomError, PyException, \"Some docs\");\n\n        Python::attach(|py| {\n            let error_type = py.get_type::<CustomError>();\n            let ctx = [(\"CustomError\", error_type)].into_py_dict(py).unwrap();\n            let type_description: String = py\n                .eval(c\"str(CustomError)\", None, Some(&ctx))\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(type_description, \"<class 'mymodule.CustomError'>\");\n            py.run(\n                c\"assert CustomError('oops').args == ('oops',)\",\n                None,\n                Some(&ctx),\n            )\n            .unwrap();\n            py.run(\n                c\"assert CustomError.__doc__ == 'Some docs'\",\n                None,\n                Some(&ctx),\n            )\n            .unwrap();\n        });\n    }\n\n    #[test]\n    fn custom_exception_doc_expr() {\n        create_exception!(\n            mymodule,\n            CustomError,\n            PyException,\n            concat!(\"Some\", \" more \", stringify!(docs))\n        );\n\n        Python::attach(|py| {\n            let error_type = py.get_type::<CustomError>();\n            let ctx = [(\"CustomError\", error_type)].into_py_dict(py).unwrap();\n            let type_description: String = py\n                .eval(c\"str(CustomError)\", None, Some(&ctx))\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(type_description, \"<class 'mymodule.CustomError'>\");\n            py.run(\n                c\"assert CustomError('oops').args == ('oops',)\",\n                None,\n                Some(&ctx),\n            )\n            .unwrap();\n            py.run(\n                c\"assert CustomError.__doc__ == 'Some more docs'\",\n                None,\n                Some(&ctx),\n            )\n            .unwrap();\n        });\n    }\n\n    #[test]\n    fn native_exception_debug() {\n        Python::attach(|py| {\n            let exc = py\n                .run(c\"raise Exception('banana')\", None, None)\n                .expect_err(\"raising should have given us an error\")\n                .into_value(py)\n                .into_bound(py);\n            assert_eq!(\n                format!(\"{exc:?}\"),\n                exc.repr().unwrap().extract::<String>().unwrap()\n            );\n        });\n    }\n\n    #[test]\n    fn native_exception_display() {\n        Python::attach(|py| {\n            let exc = py\n                .run(c\"raise Exception('banana')\", None, None)\n                .expect_err(\"raising should have given us an error\")\n                .into_value(py)\n                .into_bound(py);\n            assert_eq!(\n                exc.to_string(),\n                exc.str().unwrap().extract::<String>().unwrap()\n            );\n        });\n    }\n\n    #[test]\n    fn unicode_decode_error() {\n        let invalid_utf8 = b\"fo\\xd8o\";\n        #[expect(invalid_from_utf8)]\n        let err = std::str::from_utf8(invalid_utf8).expect_err(\"should be invalid utf8\");\n        Python::attach(|py| {\n            let decode_err = PyUnicodeDecodeError::new_utf8(py, invalid_utf8, err).unwrap();\n            assert_eq!(\n                format!(\"{decode_err:?}\"),\n                \"UnicodeDecodeError('utf-8', b'fo\\\\xd8o', 2, 3, 'invalid utf-8')\"\n            );\n\n            // Restoring should preserve the same error\n            let e: PyErr = decode_err.into();\n            e.restore(py);\n\n            assert_eq!(\n                PyErr::fetch(py).to_string(),\n                \"UnicodeDecodeError: \\'utf-8\\' codec can\\'t decode byte 0xd8 in position 2: invalid utf-8\"\n            );\n        });\n    }\n    #[cfg(Py_3_11)]\n    test_exception!(PyBaseExceptionGroup, |_| PyBaseExceptionGroup::new_err((\n        \"msg\",\n        vec![PyValueError::new_err(\"err\")]\n    )));\n    test_exception!(PyBaseException);\n    test_exception!(PyException);\n    test_exception!(PyStopAsyncIteration);\n    test_exception!(PyStopIteration);\n    test_exception!(PyGeneratorExit);\n    test_exception!(PyArithmeticError);\n    test_exception!(PyLookupError);\n    test_exception!(PyAssertionError);\n    test_exception!(PyAttributeError);\n    test_exception!(PyBufferError);\n    test_exception!(PyEOFError);\n    test_exception!(PyFloatingPointError);\n    test_exception!(PyOSError);\n    test_exception!(PyImportError);\n    test_exception!(PyModuleNotFoundError);\n    test_exception!(PyIndexError);\n    test_exception!(PyKeyError);\n    test_exception!(PyKeyboardInterrupt);\n    test_exception!(PyMemoryError);\n    test_exception!(PyNameError);\n    test_exception!(PyOverflowError);\n    test_exception!(PyRuntimeError);\n    test_exception!(PyRecursionError);\n    test_exception!(PyNotImplementedError);\n    test_exception!(PySyntaxError);\n    test_exception!(PyReferenceError);\n    test_exception!(PySystemError);\n    test_exception!(PySystemExit);\n    test_exception!(PyTypeError);\n    test_exception!(PyUnboundLocalError);\n    test_exception!(PyUnicodeError);\n    test_exception!(PyUnicodeDecodeError, |py| {\n        let invalid_utf8 = b\"fo\\xd8o\";\n        #[expect(invalid_from_utf8)]\n        let err = std::str::from_utf8(invalid_utf8).expect_err(\"should be invalid utf8\");\n        PyErr::from_value(\n            PyUnicodeDecodeError::new_utf8(py, invalid_utf8, err)\n                .unwrap()\n                .into_any(),\n        )\n    });\n    test_exception!(PyUnicodeEncodeError, |py| py\n        .eval(c\"chr(40960).encode('ascii')\", None, None)\n        .unwrap_err());\n    test_exception!(PyUnicodeTranslateError, |_| {\n        PyUnicodeTranslateError::new_err((\"\\u{3042}\", 0, 1, \"ouch\"))\n    });\n    test_exception!(PyValueError);\n    test_exception!(PyZeroDivisionError);\n    test_exception!(PyBlockingIOError);\n    test_exception!(PyBrokenPipeError);\n    test_exception!(PyChildProcessError);\n    test_exception!(PyConnectionError);\n    test_exception!(PyConnectionAbortedError);\n    test_exception!(PyConnectionRefusedError);\n    test_exception!(PyConnectionResetError);\n    test_exception!(PyFileExistsError);\n    test_exception!(PyFileNotFoundError);\n    test_exception!(PyInterruptedError);\n    test_exception!(PyIsADirectoryError);\n    test_exception!(PyNotADirectoryError);\n    test_exception!(PyPermissionError);\n    test_exception!(PyProcessLookupError);\n    test_exception!(PyTimeoutError);\n    test_exception!(PyEnvironmentError);\n    test_exception!(PyIOError);\n    #[cfg(windows)]\n    test_exception!(PyWindowsError);\n\n    test_exception!(PyWarning);\n    test_exception!(PyUserWarning);\n    test_exception!(PyDeprecationWarning);\n    test_exception!(PyPendingDeprecationWarning);\n    test_exception!(PySyntaxWarning);\n    test_exception!(PyRuntimeWarning);\n    test_exception!(PyFutureWarning);\n    test_exception!(PyImportWarning);\n    test_exception!(PyUnicodeWarning);\n    test_exception!(PyBytesWarning);\n    #[cfg(Py_3_10)]\n    test_exception!(PyEncodingWarning);\n\n    #[test]\n    #[allow(invalid_from_utf8)]\n    fn unicode_decode_error_from_utf8() {\n        Python::attach(|py| {\n            let bytes = b\"abc\\xffdef\".to_vec();\n\n            let check_err = |py_err: PyErr| {\n                let py_err = py_err.into_bound_py_any(py).unwrap();\n\n                assert!(py_err.is_instance_of::<PyUnicodeDecodeError>());\n                assert_eq!(\n                    py_err\n                        .getattr(\"encoding\")\n                        .unwrap()\n                        .extract::<String>()\n                        .unwrap(),\n                    \"utf-8\"\n                );\n                assert_eq!(\n                    py_err\n                        .getattr(\"object\")\n                        .unwrap()\n                        .extract::<Vec<u8>>()\n                        .unwrap(),\n                    &*bytes\n                );\n                assert_eq!(\n                    py_err.getattr(\"start\").unwrap().extract::<usize>().unwrap(),\n                    3\n                );\n                assert_eq!(\n                    py_err.getattr(\"end\").unwrap().extract::<usize>().unwrap(),\n                    4\n                );\n                assert_eq!(\n                    py_err\n                        .getattr(\"reason\")\n                        .unwrap()\n                        .extract::<String>()\n                        .unwrap(),\n                    \"invalid utf-8\"\n                );\n            };\n\n            let utf8_err_with_bytes = PyUnicodeDecodeError::new_err_from_utf8(\n                py,\n                &bytes,\n                std::str::from_utf8(&bytes).expect_err(\"\\\\xff is invalid utf-8\"),\n            );\n            check_err(utf8_err_with_bytes);\n        })\n    }\n}\n"
  },
  {
    "path": "src/ffi/mod.rs",
    "content": "//! Raw FFI declarations for Python's C API.\n//!\n//! This module provides low level bindings to the Python interpreter.\n//! It is meant for advanced users only - regular PyO3 users shouldn't\n//! need to interact with this module at all.\n//!\n//! The contents of this module are not documented here, as it would entail\n//! basically copying the documentation from CPython. Consult the [Python/C API Reference\n//! Manual][capi] for up-to-date documentation.\n//!\n//! # Safety\n//!\n//! The functions in this module lack individual safety documentation, but\n//! generally the following apply:\n//! - Pointer arguments have to point to a valid Python object of the correct type,\n//!   although null pointers are sometimes valid input.\n//! - The vast majority can only be used safely while the GIL is held.\n//! - Some functions have additional safety requirements, consult the\n//!   [Python/C API Reference Manual][capi] for more information.\n//!\n//! [capi]: https://docs.python.org/3/c-api/index.html\n\n#[cfg(test)]\nmod tests;\n\n//  reexport raw bindings exposed in pyo3_ffi\npub use pyo3_ffi::*;\n\n/// Helper to enable #\\[pymethods\\] to see the workaround for __ipow__ on Python 3.7\n#[doc(hidden)]\npub use crate::impl_::pymethods::ipowfunc;\n"
  },
  {
    "path": "src/ffi/tests.rs",
    "content": "use crate::ffi::*;\nuse crate::Python;\n\n#[cfg(not(Py_LIMITED_API))]\nuse crate::types::any::PyAnyMethods;\n\n#[cfg(all(not(Py_LIMITED_API), any(not(any(PyPy, GraalPy)), feature = \"macros\")))]\nuse crate::types::PyString;\n\n#[cfg(not(Py_LIMITED_API))]\nuse crate::{types::PyDict, Bound, PyAny};\n#[cfg(not(any(Py_3_12, Py_LIMITED_API, GraalPy)))]\nuse libc::wchar_t;\n\n#[cfg(not(Py_LIMITED_API))]\n#[cfg_attr(target_arch = \"wasm32\", ignore)] // DateTime import fails on wasm for mysterious reasons\n#[test]\nfn test_datetime_fromtimestamp() {\n    use crate::IntoPyObject;\n    Python::attach(|py| {\n        let args = (100,).into_pyobject(py).unwrap();\n        let dt = unsafe {\n            PyDateTime_IMPORT();\n            Bound::from_owned_ptr(py, PyDateTime_FromTimestamp(args.as_ptr()))\n        };\n        let locals = PyDict::new(py);\n        locals.set_item(\"dt\", dt).unwrap();\n        py.run(\n            c\"import datetime; assert dt == datetime.datetime.fromtimestamp(100)\",\n            None,\n            Some(&locals),\n        )\n        .unwrap();\n    })\n}\n\n#[cfg(not(Py_LIMITED_API))]\n#[cfg_attr(target_arch = \"wasm32\", ignore)] // DateTime import fails on wasm for mysterious reasons\n#[test]\nfn test_date_fromtimestamp() {\n    use crate::IntoPyObject;\n    Python::attach(|py| {\n        let args = (100,).into_pyobject(py).unwrap();\n        let dt = unsafe {\n            PyDateTime_IMPORT();\n            Bound::from_owned_ptr(py, PyDate_FromTimestamp(args.as_ptr()))\n        };\n        let locals = PyDict::new(py);\n        locals.set_item(\"dt\", dt).unwrap();\n        py.run(\n            c\"import datetime; assert dt == datetime.date.fromtimestamp(100)\",\n            None,\n            Some(&locals),\n        )\n        .unwrap();\n    })\n}\n\n#[cfg(not(Py_LIMITED_API))]\n#[cfg_attr(target_arch = \"wasm32\", ignore)] // DateTime import fails on wasm for mysterious reasons\n#[test]\nfn test_utc_timezone() {\n    Python::attach(|py| {\n        let utc_timezone: Bound<'_, PyAny> = unsafe {\n            PyDateTime_IMPORT();\n            Bound::from_borrowed_ptr(py, PyDateTime_TimeZone_UTC())\n        };\n        let locals = PyDict::new(py);\n        locals.set_item(\"utc_timezone\", utc_timezone).unwrap();\n        py.run(\n            c\"import datetime; assert utc_timezone is datetime.timezone.utc\",\n            None,\n            Some(&locals),\n        )\n        .unwrap();\n    })\n}\n\n#[test]\n#[cfg(not(Py_LIMITED_API))]\n#[cfg(feature = \"macros\")]\n#[cfg_attr(target_arch = \"wasm32\", ignore)] // DateTime import fails on wasm for mysterious reasons\nfn test_timezone_from_offset() {\n    use crate::{ffi_ptr_ext::FfiPtrExt, types::PyDelta};\n\n    Python::attach(|py| {\n        let delta = PyDelta::new(py, 0, 100, 0, false).unwrap();\n        let tz = unsafe { PyTimeZone_FromOffset(delta.as_ptr()).assume_owned(py) };\n        crate::py_run!(\n            py,\n            tz,\n            \"import datetime; assert tz == datetime.timezone(datetime.timedelta(seconds=100))\"\n        );\n    })\n}\n\n#[test]\n#[cfg(not(Py_LIMITED_API))]\n#[cfg(feature = \"macros\")]\n#[cfg_attr(target_arch = \"wasm32\", ignore)] // DateTime import fails on wasm for mysterious reasons\nfn test_timezone_from_offset_and_name() {\n    use crate::{ffi_ptr_ext::FfiPtrExt, types::PyDelta};\n\n    Python::attach(|py| {\n        let delta = PyDelta::new(py, 0, 100, 0, false).unwrap();\n        let tzname = PyString::new(py, \"testtz\");\n        let tz = unsafe {\n            PyTimeZone_FromOffsetAndName(delta.as_ptr(), tzname.as_ptr()).assume_owned(py)\n        };\n        crate::py_run!(\n            py,\n            tz,\n            \"import datetime; assert tz == datetime.timezone(datetime.timedelta(seconds=100), 'testtz')\"\n        );\n    })\n}\n\n#[test]\n#[cfg(not(any(Py_LIMITED_API, GraalPy)))]\nfn ascii_object_bitfield() {\n    let ob_base: PyObject = unsafe { std::mem::zeroed() };\n\n    #[cfg_attr(Py_3_14, allow(unused_mut, unused_variables))]\n    let mut o = PyASCIIObject {\n        ob_base,\n        length: 0,\n        #[cfg(any(Py_3_11, not(PyPy)))]\n        hash: 0,\n        state: 0u32,\n        #[cfg(not(Py_3_12))]\n        wstr: std::ptr::null_mut() as *mut wchar_t,\n    };\n\n    #[cfg(not(Py_3_14))]\n    unsafe {\n        assert_eq!(o.interned(), 0);\n        assert_eq!(o.kind(), 0);\n        assert_eq!(o.compact(), 0);\n        assert_eq!(o.ascii(), 0);\n        #[cfg(not(Py_3_12))]\n        assert_eq!(o.ready(), 0);\n\n        let interned_count = if cfg!(Py_3_12) { 2 } else { 4 };\n\n        for i in 0..interned_count {\n            o.set_interned(i);\n            assert_eq!(o.interned(), i);\n        }\n\n        for i in 0..8 {\n            o.set_kind(i);\n            assert_eq!(o.kind(), i);\n        }\n\n        o.set_compact(1);\n        assert_eq!(o.compact(), 1);\n\n        o.set_ascii(1);\n        assert_eq!(o.ascii(), 1);\n\n        #[cfg(not(Py_3_12))]\n        o.set_ready(1);\n        #[cfg(not(Py_3_12))]\n        assert_eq!(o.ready(), 1);\n\n        #[cfg(Py_3_12)]\n        o.set_statically_allocated(1);\n        #[cfg(Py_3_12)]\n        assert_eq!(o.statically_allocated(), 1);\n    }\n}\n\n#[test]\n#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\nfn ascii() {\n    Python::attach(|py| {\n        // This test relies on implementation details of PyString.\n        let s = PyString::new(py, \"hello, world\");\n        let ptr = s.as_ptr();\n\n        unsafe {\n            #[cfg(not(Py_3_14))]\n            {\n                let ascii_ptr = ptr as *mut PyASCIIObject;\n                let ascii = ascii_ptr.as_ref().unwrap();\n\n                assert_eq!(ascii.interned(), 0);\n                assert_eq!(ascii.kind(), PyUnicode_1BYTE_KIND);\n                assert_eq!(ascii.compact(), 1);\n                assert_eq!(ascii.ascii(), 1);\n                #[cfg(not(Py_3_12))]\n                assert_eq!(ascii.ready(), 1);\n\n                assert_eq!(PyUnicode_IS_ASCII(ptr), 1);\n                assert_eq!(PyUnicode_IS_COMPACT(ptr), 1);\n                assert_eq!(PyUnicode_IS_COMPACT_ASCII(ptr), 1);\n            }\n\n            assert!(!PyUnicode_1BYTE_DATA(ptr).is_null());\n            // 2 and 4 byte macros return nonsense for this string instance.\n            assert_eq!(PyUnicode_KIND(ptr), PyUnicode_1BYTE_KIND);\n\n            #[cfg(not(Py_3_14))]\n            assert!(!_PyUnicode_COMPACT_DATA(ptr).is_null());\n            // _PyUnicode_NONCOMPACT_DATA isn't valid for compact strings.\n            assert!(!PyUnicode_DATA(ptr).is_null());\n\n            assert_eq!(PyUnicode_GET_LENGTH(ptr), s.len().unwrap() as Py_ssize_t);\n            assert_eq!(PyUnicode_IS_READY(ptr), 1);\n\n            // This has potential to mutate object. But it should be a no-op since\n            // we're already ready.\n            assert_eq!(PyUnicode_READY(ptr), 0);\n        }\n    })\n}\n\n#[test]\n#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\nfn ucs4() {\n    Python::attach(|py| {\n        let s = \"哈哈🐈\";\n        let py_string = PyString::new(py, s);\n        let ptr = py_string.as_ptr();\n\n        unsafe {\n            #[cfg(not(Py_3_14))]\n            {\n                let ascii_ptr = ptr as *mut PyASCIIObject;\n                let ascii = ascii_ptr.as_ref().unwrap();\n\n                assert_eq!(ascii.interned(), 0);\n                assert_eq!(ascii.kind(), PyUnicode_4BYTE_KIND);\n                assert_eq!(ascii.compact(), 1);\n                assert_eq!(ascii.ascii(), 0);\n                #[cfg(not(Py_3_12))]\n                assert_eq!(ascii.ready(), 1);\n\n                assert_eq!(PyUnicode_IS_ASCII(ptr), 0);\n                assert_eq!(PyUnicode_IS_COMPACT(ptr), 1);\n                assert_eq!(PyUnicode_IS_COMPACT_ASCII(ptr), 0);\n            }\n            assert!(!PyUnicode_4BYTE_DATA(ptr).is_null());\n            assert_eq!(PyUnicode_KIND(ptr), PyUnicode_4BYTE_KIND);\n\n            #[cfg(not(Py_3_14))]\n            assert!(!_PyUnicode_COMPACT_DATA(ptr).is_null());\n            // _PyUnicode_NONCOMPACT_DATA isn't valid for compact strings.\n            assert!(!PyUnicode_DATA(ptr).is_null());\n\n            assert_eq!(\n                PyUnicode_GET_LENGTH(ptr),\n                py_string.len().unwrap() as Py_ssize_t\n            );\n            assert_eq!(PyUnicode_IS_READY(ptr), 1);\n\n            // This has potential to mutate object. But it should be a no-op since\n            // we're already ready.\n            assert_eq!(PyUnicode_READY(ptr), 0);\n        }\n    })\n}\n\n#[test]\n#[cfg(not(Py_LIMITED_API))]\n#[cfg_attr(target_arch = \"wasm32\", ignore)] // DateTime import fails on wasm for mysterious reasons\nfn test_get_tzinfo() {\n    use crate::types::PyTzInfo;\n\n    crate::Python::attach(|py| {\n        use crate::types::{PyDateTime, PyTime};\n\n        let utc: &Bound<'_, _> = &PyTzInfo::utc(py).unwrap();\n\n        let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(utc)).unwrap();\n\n        assert!(\n            unsafe { Bound::from_borrowed_ptr(py, PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) }\n                .is(utc)\n        );\n\n        let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, None).unwrap();\n\n        assert!(\n            unsafe { Bound::from_borrowed_ptr(py, PyDateTime_DATE_GET_TZINFO(dt.as_ptr())) }\n                .is_none()\n        );\n\n        let t = PyTime::new(py, 0, 0, 0, 0, Some(utc)).unwrap();\n\n        assert!(\n            unsafe { Bound::from_borrowed_ptr(py, PyDateTime_TIME_GET_TZINFO(t.as_ptr())) }.is(utc)\n        );\n\n        let t = PyTime::new(py, 0, 0, 0, 0, None).unwrap();\n\n        assert!(\n            unsafe { Bound::from_borrowed_ptr(py, PyDateTime_TIME_GET_TZINFO(t.as_ptr())) }\n                .is_none()\n        );\n    })\n}\n\n#[test]\nfn test_inc_dec_ref() {\n    Python::attach(|py| {\n        let obj = py.eval(c\"object()\", None, None).unwrap();\n\n        let ref_count = obj._get_refcnt();\n        let ptr = obj.as_ptr();\n\n        unsafe { Py_INCREF(ptr) };\n\n        assert_eq!(obj._get_refcnt(), ref_count + 1);\n\n        unsafe { Py_DECREF(ptr) };\n\n        assert_eq!(obj._get_refcnt(), ref_count);\n    })\n}\n\n#[test]\n#[cfg(Py_3_12)]\nfn test_inc_dec_ref_immortal() {\n    Python::attach(|py| {\n        let obj = py.None();\n\n        let ref_count = obj._get_refcnt(py);\n        let ptr = obj.as_ptr();\n\n        unsafe { Py_INCREF(ptr) };\n\n        assert_eq!(obj._get_refcnt(py), ref_count);\n\n        unsafe { Py_DECREF(ptr) };\n\n        assert_eq!(obj._get_refcnt(py), ref_count);\n    })\n}\n"
  },
  {
    "path": "src/ffi_ptr_ext.rs",
    "content": "use crate::sealed::Sealed;\nuse crate::{\n    ffi,\n    instance::{Borrowed, Bound},\n    PyAny, PyResult, Python,\n};\n\npub(crate) trait FfiPtrExt: Sealed {\n    /// Assumes this pointer carries a Python reference which needs to be decref'd.\n    ///\n    /// If the pointer is NULL, this function will fetch an error.\n    unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult<Bound<'_, PyAny>>;\n\n    /// Same as `assume_owned_or_err`, but doesn't fetch an error on NULL.\n    unsafe fn assume_owned_or_opt(self, py: Python<'_>) -> Option<Bound<'_, PyAny>>;\n\n    /// Same as `assume_owned_or_err`, but panics on NULL.\n    unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny>;\n\n    /// Same as `assume_owned_or_err`, but does not check for NULL.\n    unsafe fn assume_owned_unchecked(self, py: Python<'_>) -> Bound<'_, PyAny>;\n\n    /// Assumes this pointer is borrowed from a parent object.\n    ///\n    /// Warning: the lifetime `'a` is not bounded by the function arguments; the caller is\n    /// responsible to ensure this is tied to some appropriate lifetime.\n    unsafe fn assume_borrowed_or_err<'a>(self, py: Python<'_>)\n        -> PyResult<Borrowed<'a, '_, PyAny>>;\n\n    /// Same as `assume_borrowed_or_err`, but doesn't fetch an error on NULL.\n    unsafe fn assume_borrowed_or_opt<'a>(self, py: Python<'_>) -> Option<Borrowed<'a, '_, PyAny>>;\n\n    /// Same as `assume_borrowed_or_err`, but panics on NULL.\n    unsafe fn assume_borrowed<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny>;\n\n    /// Same as `assume_borrowed_or_err`, but does not check for NULL.\n    unsafe fn assume_borrowed_unchecked<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny>;\n}\n\nimpl FfiPtrExt for *mut ffi::PyObject {\n    #[inline]\n    unsafe fn assume_owned_or_err(self, py: Python<'_>) -> PyResult<Bound<'_, PyAny>> {\n        unsafe { Bound::from_owned_ptr_or_err(py, self) }\n    }\n\n    #[inline]\n    unsafe fn assume_owned_or_opt(self, py: Python<'_>) -> Option<Bound<'_, PyAny>> {\n        unsafe { Bound::from_owned_ptr_or_opt(py, self) }\n    }\n\n    #[inline]\n    #[track_caller]\n    unsafe fn assume_owned(self, py: Python<'_>) -> Bound<'_, PyAny> {\n        unsafe { Bound::from_owned_ptr(py, self) }\n    }\n\n    #[inline]\n    unsafe fn assume_owned_unchecked(self, py: Python<'_>) -> Bound<'_, PyAny> {\n        unsafe { Bound::from_owned_ptr_unchecked(py, self) }\n    }\n\n    #[inline]\n    unsafe fn assume_borrowed_or_err<'a>(\n        self,\n        py: Python<'_>,\n    ) -> PyResult<Borrowed<'a, '_, PyAny>> {\n        unsafe { Borrowed::from_ptr_or_err(py, self) }\n    }\n\n    #[inline]\n    unsafe fn assume_borrowed_or_opt<'a>(self, py: Python<'_>) -> Option<Borrowed<'a, '_, PyAny>> {\n        unsafe { Borrowed::from_ptr_or_opt(py, self) }\n    }\n\n    #[inline]\n    #[track_caller]\n    unsafe fn assume_borrowed<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny> {\n        unsafe { Borrowed::from_ptr(py, self) }\n    }\n\n    #[inline]\n    unsafe fn assume_borrowed_unchecked<'a>(self, py: Python<'_>) -> Borrowed<'a, '_, PyAny> {\n        unsafe { Borrowed::from_ptr_unchecked(py, self) }\n    }\n}\n"
  },
  {
    "path": "src/fmt.rs",
    "content": "#[cfg(any(doc, all(Py_3_14, not(Py_LIMITED_API))))]\nuse crate::{types::PyString, Python};\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\nuse {\n    crate::ffi::{\n        PyUnicodeWriter_Create, PyUnicodeWriter_Discard, PyUnicodeWriter_Finish,\n        PyUnicodeWriter_WriteChar, PyUnicodeWriter_WriteUTF8,\n    },\n    crate::ffi_ptr_ext::FfiPtrExt,\n    crate::impl_::callback::WrappingCastTo,\n    crate::py_result_ext::PyResultExt,\n    crate::IntoPyObject,\n    crate::{ffi, Bound, PyErr, PyResult},\n    std::fmt,\n    std::mem::ManuallyDrop,\n    std::ptr::NonNull,\n};\n\n/// This macro is analogous to Rust's [`format!`] macro, but returns a [`PyString`] instead of a [`String`].\n///\n/// # Arguments\n///\n/// The arguments are exactly like [`format!`], but with `py` (a [`Python`] token) as the first argument:\n///\n/// # Interning Advantage\n///\n/// If the format string is a static string and all arguments are constant at compile time,\n/// this macro will intern the string in Python, offering better performance and memory usage\n/// compared to [`PyString::from_fmt`].\n///\n/// ```rust\n/// # use pyo3::{py_format, Python, types::PyString, Bound};\n/// Python::attach(|py| {\n///     let py_string: Bound<'_, PyString> = py_format!(py, \"{} {}\", \"hello\", \"world\").unwrap();\n///     assert_eq!(py_string.to_string(), \"hello world\");\n/// });\n/// ```\n#[macro_export]\nmacro_rules! py_format {\n    ($py: expr, $($arg:tt)*) => {{\n        if let Some(static_string) = format_args!($($arg)*).as_str() {\n            static INTERNED: $crate::sync::PyOnceLock<$crate::Py<$crate::types::PyString>> = $crate::sync::PyOnceLock::new();\n            Ok(\n                INTERNED\n                .get_or_init($py, || $crate::types::PyString::intern($py, static_string).unbind())\n                .bind($py)\n                .to_owned()\n            )\n        } else {\n            $crate::types::PyString::from_fmt($py, format_args!($($arg)*))\n        }\n    }}\n}\n\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\n/// The `PyUnicodeWriter` is a utility for efficiently constructing Python strings\npub(crate) struct PyUnicodeWriter<'py> {\n    python: Python<'py>,\n    writer: NonNull<ffi::PyUnicodeWriter>,\n    last_error: Option<PyErr>,\n}\n\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\nimpl<'py> PyUnicodeWriter<'py> {\n    /// Creates a new `PyUnicodeWriter`.\n    pub fn new(py: Python<'py>) -> PyResult<Self> {\n        Self::with_capacity(py, 0)\n    }\n\n    /// Creates a new `PyUnicodeWriter` with the specified initial capacity.\n    #[inline]\n    pub fn with_capacity(py: Python<'py>, capacity: usize) -> PyResult<Self> {\n        match NonNull::new(unsafe { PyUnicodeWriter_Create(capacity.wrapping_cast()) }) {\n            Some(ptr) => Ok(PyUnicodeWriter {\n                python: py,\n                writer: ptr,\n                last_error: None,\n            }),\n            None => Err(PyErr::fetch(py)),\n        }\n    }\n\n    /// Consumes the `PyUnicodeWriter` and returns a `Bound<PyString>` containing the constructed string.\n    #[inline]\n    pub fn into_py_string(mut self) -> PyResult<Bound<'py, PyString>> {\n        let py = self.python;\n        if let Some(error) = self.take_error() {\n            Err(error)\n        } else {\n            unsafe {\n                PyUnicodeWriter_Finish(ManuallyDrop::new(self).as_ptr())\n                    .assume_owned_or_err(py)\n                    .cast_into_unchecked()\n            }\n        }\n    }\n\n    /// When fmt::Write returned an error, this function can be used to retrieve the last error that occurred.\n    #[inline]\n    pub fn take_error(&mut self) -> Option<PyErr> {\n        self.last_error.take()\n    }\n\n    #[inline]\n    fn as_ptr(&self) -> *mut ffi::PyUnicodeWriter {\n        self.writer.as_ptr()\n    }\n\n    #[inline]\n    fn set_error(&mut self) {\n        self.last_error = Some(PyErr::fetch(self.python));\n    }\n}\n\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\nimpl fmt::Write for PyUnicodeWriter<'_> {\n    #[inline]\n    fn write_str(&mut self, s: &str) -> fmt::Result {\n        let result = unsafe {\n            PyUnicodeWriter_WriteUTF8(self.as_ptr(), s.as_ptr().cast(), s.len() as isize)\n        };\n        if result < 0 {\n            self.set_error();\n            Err(fmt::Error)\n        } else {\n            Ok(())\n        }\n    }\n\n    #[inline]\n    fn write_char(&mut self, c: char) -> fmt::Result {\n        let result = unsafe { PyUnicodeWriter_WriteChar(self.as_ptr(), c.into()) };\n        if result < 0 {\n            self.set_error();\n            Err(fmt::Error)\n        } else {\n            Ok(())\n        }\n    }\n}\n\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\nimpl Drop for PyUnicodeWriter<'_> {\n    #[inline]\n    fn drop(&mut self) {\n        unsafe {\n            PyUnicodeWriter_Discard(self.as_ptr());\n        }\n    }\n}\n\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\nimpl<'py> IntoPyObject<'py> for PyUnicodeWriter<'py> {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = PyErr;\n\n    #[inline]\n    fn into_pyobject(self, _py: Python<'py>) -> PyResult<Bound<'py, PyString>> {\n        self.into_py_string()\n    }\n}\n\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\nimpl<'py> TryInto<Bound<'py, PyString>> for PyUnicodeWriter<'py> {\n    type Error = PyErr;\n\n    #[inline]\n    fn try_into(self) -> PyResult<Bound<'py, PyString>> {\n        self.into_py_string()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    #[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\n    use super::*;\n    use crate::types::PyStringMethods;\n    use crate::{IntoPyObject, Python};\n\n    #[test]\n    #[allow(clippy::write_literal)]\n    #[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\n    fn unicode_writer_test() {\n        use std::fmt::Write;\n        Python::attach(|py| {\n            let mut writer = PyUnicodeWriter::new(py).unwrap();\n            write!(writer, \"Hello {}!\", \"world\").unwrap();\n            writer.write_char('😎').unwrap();\n            let result = writer.into_py_string().unwrap();\n            assert_eq!(result.to_string(), \"Hello world!😎\");\n        });\n    }\n\n    #[test]\n    #[allow(clippy::write_literal)]\n    #[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\n    fn unicode_writer_with_capacity() {\n        use std::fmt::Write;\n        Python::attach(|py| {\n            let mut writer = PyUnicodeWriter::with_capacity(py, 10).unwrap();\n            write!(writer, \"Hello {}!\", \"world\").unwrap();\n            writer.write_char('😎').unwrap();\n            let result = writer.into_py_string().unwrap();\n            assert_eq!(result.to_string(), \"Hello world!😎\");\n        });\n    }\n\n    #[test]\n    fn test_pystring_from_fmt() {\n        Python::attach(|py| {\n            py_format!(py, \"Hello {}!\", \"world\").unwrap();\n        });\n    }\n\n    #[test]\n    fn test_complex_format() {\n        Python::attach(|py| {\n            let complex_value = (42, \"foo\", [0; 0]).into_pyobject(py).unwrap();\n            let py_string = py_format!(py, \"This is some complex value: {complex_value}\").unwrap();\n            let actual = py_string.to_cow().unwrap();\n            let expected = \"This is some complex value: (42, 'foo', [])\";\n            assert_eq!(actual, expected);\n        });\n    }\n}\n"
  },
  {
    "path": "src/impl_/callback.rs",
    "content": "//! Utilities for a Python callable object that invokes a Rust function.\n\nuse crate::err::{PyErr, PyResult};\nuse crate::exceptions::PyOverflowError;\nuse crate::ffi::{self, Py_hash_t};\nuse crate::{BoundObject, IntoPyObject, Py, PyAny, Python};\nuse std::ffi::c_int;\n\n/// A type which can be the return type of a python C-API callback\npub trait PyCallbackOutput: Copy + py_callback_output::Sealed {\n    /// The error value to return to python if the callback raised an exception\n    const ERR_VALUE: Self;\n}\n\n/// Seals `PyCallbackOutput` so that types outside PyO3 cannot implement it.\nmod py_callback_output {\n    use std::os::raw::c_int;\n\n    use pyo3_ffi::Py_ssize_t;\n\n    use crate::ffi::PyObject;\n\n    pub trait Sealed {}\n\n    impl Sealed for *mut PyObject {}\n    impl Sealed for c_int {}\n    impl Sealed for Py_ssize_t {}\n}\n\nimpl PyCallbackOutput for *mut ffi::PyObject {\n    const ERR_VALUE: Self = std::ptr::null_mut();\n}\n\nimpl PyCallbackOutput for std::ffi::c_int {\n    const ERR_VALUE: Self = -1;\n}\n\nimpl PyCallbackOutput for ffi::Py_ssize_t {\n    const ERR_VALUE: Self = -1;\n}\n\n/// Convert the result of callback function into the appropriate return value.\npub trait IntoPyCallbackOutput<'py, Target>: into_py_callback_output::Sealed<'py, Target> {\n    fn convert(self, py: Python<'py>) -> PyResult<Target>;\n}\n\n/// Seals `IntoPyCallbackOutput` so that types outside PyO3 cannot implement it.\nmod into_py_callback_output {\n    use pyo3_ffi::Py_hash_t;\n\n    use crate::{\n        ffi,\n        impl_::callback::{HashCallbackOutput, IntoPyCallbackOutput, WrappingCastTo},\n        IntoPyObject, Py, PyAny, PyErr,\n    };\n\n    pub trait Sealed<'py, Target> {}\n\n    impl<'py, T: IntoPyObject<'py>> Sealed<'py, *mut ffi::PyObject> for T {}\n    impl<'py, T: IntoPyCallbackOutput<'py, U>, E: Into<PyErr>, U> Sealed<'py, U> for Result<T, E> {}\n    impl Sealed<'_, Self> for *mut ffi::PyObject {}\n    impl Sealed<'_, std::ffi::c_int> for () {}\n    impl Sealed<'_, std::ffi::c_int> for bool {}\n    impl Sealed<'_, ()> for () {}\n    impl Sealed<'_, ffi::Py_ssize_t> for usize {}\n    impl Sealed<'_, bool> for bool {}\n    impl Sealed<'_, usize> for usize {}\n    impl<'py, T: IntoPyObject<'py>> Sealed<'py, Py<PyAny>> for T {}\n    impl Sealed<'_, Py_hash_t> for HashCallbackOutput {}\n    impl<T: WrappingCastTo<Py_hash_t>> Sealed<'_, HashCallbackOutput> for T {}\n}\n\nimpl<'py, T, E, U> IntoPyCallbackOutput<'py, U> for Result<T, E>\nwhere\n    T: IntoPyCallbackOutput<'py, U>,\n    E: Into<PyErr>,\n{\n    #[inline]\n    fn convert(self, py: Python<'py>) -> PyResult<U> {\n        match self {\n            Ok(v) => v.convert(py),\n            Err(e) => Err(e.into()),\n        }\n    }\n}\n\nimpl<'py, T> IntoPyCallbackOutput<'py, *mut ffi::PyObject> for T\nwhere\n    T: IntoPyObject<'py>,\n{\n    #[inline]\n    fn convert(self, py: Python<'py>) -> PyResult<*mut ffi::PyObject> {\n        self.into_pyobject(py)\n            .map(BoundObject::into_ptr)\n            .map_err(Into::into)\n    }\n}\n\nimpl IntoPyCallbackOutput<'_, Self> for *mut ffi::PyObject {\n    #[inline]\n    fn convert(self, _: Python<'_>) -> PyResult<Self> {\n        Ok(self)\n    }\n}\n\nimpl IntoPyCallbackOutput<'_, std::ffi::c_int> for () {\n    #[inline]\n    fn convert(self, _: Python<'_>) -> PyResult<std::ffi::c_int> {\n        Ok(0)\n    }\n}\n\nimpl IntoPyCallbackOutput<'_, std::ffi::c_int> for bool {\n    #[inline]\n    fn convert(self, _: Python<'_>) -> PyResult<std::ffi::c_int> {\n        Ok(self as c_int)\n    }\n}\n\nimpl IntoPyCallbackOutput<'_, ()> for () {\n    #[inline]\n    fn convert(self, _: Python<'_>) -> PyResult<()> {\n        Ok(())\n    }\n}\n\nimpl IntoPyCallbackOutput<'_, ffi::Py_ssize_t> for usize {\n    #[inline]\n    fn convert(self, _py: Python<'_>) -> PyResult<ffi::Py_ssize_t> {\n        self.try_into().map_err(|_err| PyOverflowError::new_err(()))\n    }\n}\n\n// Converters needed for `#[pyproto]` implementations\n\nimpl IntoPyCallbackOutput<'_, bool> for bool {\n    #[inline]\n    fn convert(self, _: Python<'_>) -> PyResult<bool> {\n        Ok(self)\n    }\n}\n\nimpl IntoPyCallbackOutput<'_, usize> for usize {\n    #[inline]\n    fn convert(self, _: Python<'_>) -> PyResult<usize> {\n        Ok(self)\n    }\n}\n\nimpl<'py, T> IntoPyCallbackOutput<'py, Py<PyAny>> for T\nwhere\n    T: IntoPyObject<'py>,\n{\n    #[inline]\n    fn convert(self, py: Python<'py>) -> PyResult<Py<PyAny>> {\n        self.into_pyobject(py)\n            .map(BoundObject::into_any)\n            .map(BoundObject::unbind)\n            .map_err(Into::into)\n    }\n}\n\npub trait WrappingCastTo<T>: wrapping_cast_to::Sealed<T> {\n    fn wrapping_cast(self) -> T;\n}\n\n/// Seals `WrappingCastTo` so that types outside PyO3 cannot implement it.\nmod wrapping_cast_to {\n    pub trait Sealed<T> {}\n}\n\nmacro_rules! wrapping_cast {\n    ($from:ty, $to:ty) => {\n        impl WrappingCastTo<$to> for $from {\n            #[inline]\n            fn wrapping_cast(self) -> $to {\n                self as $to\n            }\n        }\n        impl wrapping_cast_to::Sealed<$to> for $from {}\n    };\n}\nwrapping_cast!(u8, Py_hash_t);\nwrapping_cast!(u16, Py_hash_t);\nwrapping_cast!(u32, Py_hash_t);\nwrapping_cast!(usize, Py_hash_t);\nwrapping_cast!(u64, Py_hash_t);\nwrapping_cast!(i8, Py_hash_t);\nwrapping_cast!(i16, Py_hash_t);\nwrapping_cast!(i32, Py_hash_t);\nwrapping_cast!(isize, Py_hash_t);\nwrapping_cast!(i64, Py_hash_t);\n\npub struct HashCallbackOutput(Py_hash_t);\n\nimpl IntoPyCallbackOutput<'_, Py_hash_t> for HashCallbackOutput {\n    #[inline]\n    fn convert(self, _py: Python<'_>) -> PyResult<Py_hash_t> {\n        let hash = self.0;\n        if hash == -1 {\n            Ok(-2)\n        } else {\n            Ok(hash)\n        }\n    }\n}\n\nimpl<T> IntoPyCallbackOutput<'_, HashCallbackOutput> for T\nwhere\n    T: WrappingCastTo<Py_hash_t>,\n{\n    #[inline]\n    fn convert(self, _py: Python<'_>) -> PyResult<HashCallbackOutput> {\n        Ok(HashCallbackOutput(self.wrapping_cast()))\n    }\n}\n\n#[doc(hidden)]\n#[inline]\npub fn convert<'py, T, U>(py: Python<'py>, value: T) -> PyResult<U>\nwhere\n    T: IntoPyCallbackOutput<'py, U>,\n{\n    value.convert(py)\n}\n"
  },
  {
    "path": "src/impl_/concat.rs",
    "content": "/// Calculates the total byte length of all byte pieces in the array.\n///\n/// This is a useful utility in order to determine the size needed for the constant\n/// `combine` function.\npub const fn combined_len(pieces: &[&[u8]]) -> usize {\n    let mut len = 0;\n    let mut pieces_idx = 0;\n    while pieces_idx < pieces.len() {\n        len += pieces[pieces_idx].len();\n        pieces_idx += 1;\n    }\n    len\n}\n\n/// Combines all bytes pieces into a single byte array.\n///\n/// `out` should be a buffer at the correct size of `combined_len(pieces)`, else this will panic.\nconst fn combine(pieces: &[&[u8]], mut out: &mut [u8]) {\n    let mut pieces_idx = 0;\n    while pieces_idx < pieces.len() {\n        let piece = pieces[pieces_idx];\n        slice_copy_from_slice(out, piece);\n        // using split_at_mut because range indexing not yet supported in const fn\n        out = out.split_at_mut(piece.len()).1;\n        pieces_idx += 1;\n    }\n    // should be no trailing buffer\n    assert!(out.is_empty(), \"output buffer too large\");\n}\n\n/// Wrapper around `combine` which has a const generic parameter, this is going to be more codegen\n/// at compile time (?)\npub const fn combine_to_array<const LEN: usize>(pieces: &[&[u8]]) -> [u8; LEN] {\n    let mut out: [u8; LEN] = [0u8; LEN];\n    combine(pieces, &mut out);\n    out\n}\n\n/// Replacement for `slice::copy_from_slice`, which is const from 1.87\npub(crate) const fn slice_copy_from_slice(out: &mut [u8], src: &[u8]) {\n    let mut i = 0;\n    while i < src.len() {\n        out[i] = src[i];\n        i += 1;\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_combined_len() {\n        let pieces: [&[u8]; 3] = [b\"foo\", b\"bar\", b\"baz\"];\n        assert_eq!(combined_len(&pieces), 9);\n        let empty: [&[u8]; 0] = [];\n        assert_eq!(combined_len(&empty), 0);\n    }\n\n    #[test]\n    fn test_combine_to_array() {\n        let pieces: [&[u8]; 2] = [b\"foo\", b\"bar\"];\n        let combined = combine_to_array::<6>(&pieces);\n        assert_eq!(&combined, b\"foobar\");\n    }\n\n    #[test]\n    #[should_panic(expected = \"index out of bounds\")]\n    fn test_combine_to_array_buffer_too_small() {\n        let pieces: [&[u8]; 2] = [b\"foo\", b\"bar\"];\n        // Intentionally wrong length\n        let _ = combine_to_array::<5>(&pieces);\n    }\n\n    #[test]\n    #[should_panic(expected = \"output buffer too large\")]\n    fn test_combine_to_array_buffer_too_big() {\n        let pieces: [&[u8]; 2] = [b\"foo\", b\"bar\"];\n        // Intentionally wrong length\n        let _ = combine_to_array::<10>(&pieces);\n    }\n}\n"
  },
  {
    "path": "src/impl_/coroutine.rs",
    "content": "use std::future::Future;\n\nuse crate::{\n    coroutine::{cancel::ThrowCallback, Coroutine},\n    instance::Bound,\n    types::PyString,\n    Py, PyAny, PyResult, Python,\n};\n\npub fn new_coroutine<'py, F>(\n    name: &Bound<'py, PyString>,\n    qualname_prefix: Option<&'static str>,\n    throw_callback: Option<ThrowCallback>,\n    future: F,\n) -> Coroutine\nwhere\n    F: Future<Output = PyResult<Py<PyAny>>> + Send + 'static,\n{\n    Coroutine::new(Some(name.clone()), qualname_prefix, throw_callback, future)\n}\n\n/// Handle which assumes that the coroutine is attached to the thread. Unlike `Python<'_>`, this is `Send`.\npub struct AssumeAttachedInCoroutine(());\n\nimpl AssumeAttachedInCoroutine {\n    /// Safety: this should only be used inside a future passed to `new_coroutine`, where the coroutine is\n    /// guaranteed to be attached to the thread when polled.\n    pub unsafe fn new() -> Self {\n        Self(())\n    }\n\n    pub fn py(&self) -> Python<'_> {\n        // Safety: this type holds the invariant that the thread is attached\n        unsafe { Python::assume_attached() }\n    }\n}\n"
  },
  {
    "path": "src/impl_/deprecated.rs",
    "content": "pub struct HasAutomaticFromPyObject<const IS_CLONE: bool> {}\r\n\r\nimpl HasAutomaticFromPyObject<true> {\r\n    #[deprecated(\r\n        since = \"0.28.0\",\r\n        note = \"The `FromPyObject` implementation for `#[pyclass]` types which implement `Clone` is changing to an opt-in option. Use `#[pyclass(from_py_object)]` to opt-in to the `FromPyObject` derive now, or `#[pyclass(skip_from_py_object)]` to skip the `FromPyObject` implementation.\"\r\n    )]\r\n    pub const MSG: () = ();\r\n}\r\n\r\nimpl HasAutomaticFromPyObject<false> {\r\n    pub const MSG: () = ();\r\n}\r\n"
  },
  {
    "path": "src/impl_/exceptions.rs",
    "content": "use crate::{sync::PyOnceLock, types::PyType, Bound, Py, Python};\n\npub struct ImportedExceptionTypeObject {\n    imported_value: PyOnceLock<Py<PyType>>,\n    module: &'static str,\n    name: &'static str,\n}\n\nimpl ImportedExceptionTypeObject {\n    pub const fn new(module: &'static str, name: &'static str) -> Self {\n        Self {\n            imported_value: PyOnceLock::new(),\n            module,\n            name,\n        }\n    }\n\n    pub fn get<'py>(&self, py: Python<'py>) -> &Bound<'py, PyType> {\n        self.imported_value\n            .import(py, self.module, self.name)\n            .unwrap_or_else(|e| {\n                panic!(\n                    \"failed to import exception {}.{}: {}\",\n                    self.module, self.name, e\n                )\n            })\n    }\n}\n"
  },
  {
    "path": "src/impl_/extract_argument.rs",
    "content": "use std::ptr::NonNull;\n\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_union, PyStaticExpr};\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::types::PyNone;\n#[cfg(any(Py_3_10, not(Py_LIMITED_API), feature = \"experimental-inspect\"))]\nuse crate::types::PyString;\nuse crate::{\n    exceptions::PyTypeError,\n    ffi,\n    pyclass::boolean_struct::False,\n    types::{any::PyAnyMethods, dict::PyDictMethods, tuple::PyTupleMethods, PyDict, PyTuple},\n    Borrowed, Bound, CastError, FromPyObject, PyAny, PyClass, PyClassGuard, PyClassGuardMut, PyErr,\n    PyResult, PyTypeCheck, Python,\n};\n\n/// Helper type used to keep implementation more concise.\n///\n/// (Function argument extraction borrows input arguments.)\ntype PyArg<'py> = Borrowed<'py, 'py, PyAny>;\n\n/// Seals `PyFunctionArgument` so that types outside PyO3 cannot implement it.\n///\n/// The public API is `FromPyObject`.\nmod function_argument {\n    use crate::{\n        impl_::extract_argument::PyFunctionArgument, pyclass::boolean_struct::False, FromPyObject,\n        PyClass, PyTypeCheck,\n    };\n\n    pub trait Sealed<const IMPLEMENTS_FROMPYOBJECT: bool> {}\n    impl<'a, 'py, T: FromPyObject<'a, 'py>> Sealed<true> for T {}\n    impl<'py, T: PyTypeCheck + 'py> Sealed<false> for &'_ crate::Bound<'py, T> {}\n    impl<'a, 'holder, 'py, T: PyFunctionArgument<'a, 'holder, 'py, false>> Sealed<false> for Option<T> {}\n    #[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\n    impl Sealed<false> for &'_ str {}\n    impl<T: PyClass> Sealed<false> for &'_ T {}\n    impl<T: PyClass<Frozen = False>> Sealed<false> for &'_ mut T {}\n}\n\n/// A trait which is used to help PyO3 macros extract function arguments.\n///\n/// `#[pyclass]` structs need to extract as `PyRef<T>` and `PyRefMut<T>`\n/// wrappers rather than extracting `&T` and `&mut T` directly. The `Holder` type is used\n/// to hold these temporary wrappers - the way the macro is constructed, these wrappers\n/// will be dropped as soon as the pyfunction call ends.\n///\n/// There exists a trivial blanket implementation for `T: FromPyObject` with `Holder = ()`.\n///\n/// The const generic arg `IMPLEMENTS_FROMPYOBJECT` allows for const generic specialization of\n/// some additional types which don't implement `FromPyObject`, such as `&T` for `#[pyclass]` types.\n/// All types should only implement this trait once; either by the `FromPyObject` blanket or one\n/// of the specialized implementations which needs a `Holder`.\n#[diagnostic::on_unimplemented(\n    message = \"`{Self}` cannot be used as a Python function argument\",\n    note = \"implement `FromPyObject` to enable using `{Self}` as a function argument\",\n    note = \"`Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]`\"\n)]\npub trait PyFunctionArgument<'a, 'holder, 'py, const IMPLEMENTS_FROMPYOBJECT: bool>:\n    Sized + function_argument::Sealed<IMPLEMENTS_FROMPYOBJECT>\n{\n    type Holder: FunctionArgumentHolder;\n    type Error: Into<PyErr>;\n\n    /// Provides the type hint information for which Python types are allowed.\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr;\n\n    fn extract(\n        obj: Borrowed<'a, 'py, PyAny>,\n        holder: &'holder mut Self::Holder,\n    ) -> Result<Self, Self::Error>;\n}\n\nimpl<'a, 'py, T> PyFunctionArgument<'a, '_, 'py, true> for T\nwhere\n    T: FromPyObject<'a, 'py>,\n{\n    type Holder = ();\n    type Error = T::Error;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = T::INPUT_TYPE;\n\n    #[inline]\n    fn extract(obj: Borrowed<'a, 'py, PyAny>, _: &'_ mut ()) -> Result<Self, Self::Error> {\n        obj.extract()\n    }\n}\n\nimpl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false>\n    for &'holder Bound<'py, T>\nwhere\n    T: PyTypeCheck,\n{\n    type Holder = Option<Borrowed<'a, 'py, T>>;\n    type Error = CastError<'a, 'py>;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    #[inline]\n    fn extract(\n        obj: Borrowed<'a, 'py, PyAny>,\n        holder: &'holder mut Self::Holder,\n    ) -> Result<Self, Self::Error> {\n        Ok(holder.insert(obj.cast()?))\n    }\n}\n\n/// Allow `Option<T>` to be a function argument also for types which don't implement `FromPyObject`\nimpl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option<T>\nwhere\n    T: PyFunctionArgument<'a, 'holder, 'py, false>,\n{\n    type Holder = T::Holder;\n    type Error = T::Error;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_union!(T::INPUT_TYPE, PyNone::TYPE_HINT);\n\n    #[inline]\n    fn extract(\n        obj: Borrowed<'a, 'py, PyAny>,\n        holder: &'holder mut T::Holder,\n    ) -> Result<Self, Self::Error> {\n        if obj.is_none() {\n            Ok(None)\n        } else {\n            Ok(Some(T::extract(obj, holder)?))\n        }\n    }\n}\n\n#[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\nimpl<'a, 'holder, 'py> PyFunctionArgument<'a, 'holder, 'py, false> for &'holder str {\n    type Holder = Option<std::borrow::Cow<'a, str>>;\n    type Error = <std::borrow::Cow<'a, str> as FromPyObject<'a, 'py>>::Error;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    #[inline]\n    fn extract(\n        obj: Borrowed<'a, 'py, PyAny>,\n        holder: &'holder mut Option<std::borrow::Cow<'a, str>>,\n    ) -> PyResult<Self> {\n        Ok(holder.insert(obj.extract()?))\n    }\n}\n\n/// Seals `FunctionArgumentHolder` so that types outside PyO3 cannot implement it.\nmod function_argument_holder {\n    pub trait Sealed {}\n\n    impl Sealed for () {}\n    impl<T> Sealed for Option<T> {}\n}\n\n/// Trait for types which can be a function argument holder - they should\n/// to be able to const-initialize to an empty value.\npub trait FunctionArgumentHolder: Sized + function_argument_holder::Sealed {\n    const INIT: Self;\n}\n\nimpl FunctionArgumentHolder for () {\n    const INIT: Self = ();\n}\n\nimpl<T> FunctionArgumentHolder for Option<T> {\n    const INIT: Self = None;\n}\n\nimpl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T {\n    type Holder = ::std::option::Option<PyClassGuard<'a, T>>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    #[inline]\n    fn extract(obj: Borrowed<'a, '_, PyAny>, holder: &'holder mut Self::Holder) -> PyResult<Self> {\n        extract_pyclass_ref(obj, holder)\n    }\n}\n\nimpl<'a, 'holder, T: PyClass<Frozen = False>> PyFunctionArgument<'a, 'holder, '_, false>\n    for &'holder mut T\n{\n    type Holder = ::std::option::Option<PyClassGuardMut<'a, T>>;\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    #[inline]\n    fn extract(obj: Borrowed<'a, '_, PyAny>, holder: &'holder mut Self::Holder) -> PyResult<Self> {\n        extract_pyclass_ref_mut(obj, holder)\n    }\n}\n\n#[inline]\npub fn extract_pyclass_ref<'a, 'holder, T: PyClass>(\n    obj: Borrowed<'a, '_, PyAny>,\n    holder: &'holder mut Option<PyClassGuard<'a, T>>,\n) -> PyResult<&'holder T> {\n    Ok(&*holder.insert(PyClassGuard::try_borrow_from_borrowed(obj.cast()?)?))\n}\n\n#[inline]\npub fn extract_pyclass_ref_mut<'a, 'holder, T: PyClass<Frozen = False>>(\n    obj: Borrowed<'a, '_, PyAny>,\n    holder: &'holder mut Option<PyClassGuardMut<'a, T>>,\n) -> PyResult<&'holder mut T> {\n    Ok(&mut *holder.insert(PyClassGuardMut::try_borrow_mut_from_borrowed(obj.cast()?)?))\n}\n\n/// The standard implementation of how PyO3 extracts a `#[pyfunction]` or `#[pymethod]` function argument.\npub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>(\n    obj: Borrowed<'a, 'py, PyAny>,\n    holder: &'holder mut T::Holder,\n    arg_name: &str,\n) -> PyResult<T>\nwhere\n    T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>,\n{\n    match PyFunctionArgument::extract(obj, holder) {\n        Ok(value) => Ok(value),\n        Err(e) => Err(argument_extraction_error(obj.py(), arg_name, e.into())),\n    }\n}\n\n/// Alternative to [`extract_argument`] used when the argument has a default value provided by an annotation.\npub fn extract_argument_with_default<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>(\n    obj: Option<Borrowed<'a, 'py, PyAny>>,\n    holder: &'holder mut T::Holder,\n    arg_name: &str,\n    default: fn() -> T,\n) -> PyResult<T>\nwhere\n    T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>,\n{\n    match obj {\n        Some(obj) => extract_argument(obj, holder, arg_name),\n        None => Ok(default()),\n    }\n}\n\n/// Alternative to [`extract_argument`] used when the argument has a `#[pyo3(from_py_with)]` annotation.\npub fn from_py_with<'a, 'py, T>(\n    obj: &'a Bound<'py, PyAny>,\n    arg_name: &str,\n    extractor: fn(&'a Bound<'py, PyAny>) -> PyResult<T>,\n) -> PyResult<T> {\n    match extractor(obj) {\n        Ok(value) => Ok(value),\n        Err(e) => Err(argument_extraction_error(obj.py(), arg_name, e)),\n    }\n}\n\n/// Alternative to [`extract_argument`] used when the argument has a `#[pyo3(from_py_with)]` annotation and also a default value.\npub fn from_py_with_with_default<'a, 'py, T>(\n    obj: Option<&'a Bound<'py, PyAny>>,\n    arg_name: &str,\n    extractor: fn(&'a Bound<'py, PyAny>) -> PyResult<T>,\n    default: fn() -> T,\n) -> PyResult<T> {\n    match obj {\n        Some(obj) => from_py_with(obj, arg_name, extractor),\n        None => Ok(default()),\n    }\n}\n\n/// Adds the argument name to the error message of an error which occurred during argument extraction.\n///\n/// Only modifies TypeError. (Cannot guarantee all exceptions have constructors from\n/// single string.)\n#[cold]\npub fn argument_extraction_error(py: Python<'_>, arg_name: &str, error: PyErr) -> PyErr {\n    if let Ok(msg) = crate::py_format!(py, \"while processing '{arg_name}'\") {\n        let _ = error\n            .value(py)\n            .call_method1(crate::intern!(py, \"add_note\"), (msg,));\n    };\n    error\n}\n\n/// Unwraps the Option<&PyAny> produced by the FunctionDescription `extract_arguments_` methods.\n/// They check if required methods are all provided.\n///\n/// # Safety\n/// `argument` must not be `None`\n#[inline]\npub unsafe fn unwrap_required_argument<'a, 'py>(\n    argument: Option<Borrowed<'a, 'py, PyAny>>,\n) -> Borrowed<'a, 'py, PyAny> {\n    match argument {\n        Some(value) => value,\n        #[cfg(debug_assertions)]\n        None => unreachable!(\"required method argument was not extracted\"),\n        // SAFETY: invariant of calling this function. Enforced by the macros.\n        #[cfg(not(debug_assertions))]\n        None => unsafe { std::hint::unreachable_unchecked() },\n    }\n}\n\n/// Variant of above used with `from_py_with` extractors on required arguments.\n#[inline]\npub unsafe fn unwrap_required_argument_bound<'a, 'py>(\n    argument: Option<&'a Bound<'py, PyAny>>,\n) -> &'a Bound<'py, PyAny> {\n    match argument {\n        Some(value) => value,\n        #[cfg(debug_assertions)]\n        None => unreachable!(\"required method argument was not extracted\"),\n        // SAFETY: invariant of calling this function. Enforced by the macros.\n        #[cfg(not(debug_assertions))]\n        None => unsafe { std::hint::unreachable_unchecked() },\n    }\n}\n\n/// Cast a raw `*mut ffi::PyObject` to a `PyArg`. This is used to access safer PyO3\n/// APIs with the assumption that the borrowed argument is valid for the lifetime `'py`.\n///\n/// This has the effect of limiting the lifetime of function arguments to `'py`, i.e.\n/// avoiding accidentally creating `'static` lifetimes from raw pointers.\n///\n/// # Safety\n/// - `raw_arg` must be a valid `*mut ffi::PyObject` for the lifetime `'py`.\n/// - `raw_arg` must not be NULL.\n#[inline]\npub unsafe fn cast_function_argument<'py>(\n    py: Python<'py>,\n    raw_arg: *mut ffi::PyObject,\n) -> PyArg<'py> {\n    // Safety: caller upholds the invariants\n    unsafe { Borrowed::from_ptr_unchecked(py, raw_arg) }\n}\n\n/// Cast a `NonNull<ffi::PyObject>` to a `PyArg`. This is used to access safer PyO3\n/// APIs with the assumption that the borrowed argument is valid for the lifetime `'py`.\n///\n/// This has the effect of limiting the lifetime of function arguments to `'py`, i.e.\n/// avoiding accidentally creating `'static` lifetimes from raw pointers.\n///\n/// # Safety\n/// - `raw_arg` must be a valid `NonNull<ffi::PyObject>` for the lifetime `'py`.\n#[inline]\npub unsafe fn cast_non_null_function_argument<'py>(\n    py: Python<'py>,\n    raw_arg: NonNull<ffi::PyObject>,\n) -> PyArg<'py> {\n    // Safety: caller upholds the invariants\n    unsafe { Borrowed::from_non_null(py, raw_arg) }\n}\n\n/// As above, but for optional arguments which may be NULL.\n///\n/// # Safety\n/// - `raw_arg` must be a valid `*mut ffi::PyObject` for the lifetime `'py`, or NULL.\n#[inline]\npub unsafe fn cast_optional_function_argument<'py>(\n    py: Python<'py>,\n    raw_arg: *mut ffi::PyObject,\n) -> Option<PyArg<'py>> {\n    // Safety: caller upholds the invariants\n    unsafe { Borrowed::from_ptr_or_opt(py, raw_arg) }\n}\n\npub struct KeywordOnlyParameterDescription {\n    pub name: &'static str,\n    pub required: bool,\n}\n\n/// Function argument specification for a `#[pyfunction]` or `#[pymethod]`.\npub struct FunctionDescription {\n    pub cls_name: Option<&'static str>,\n    pub func_name: &'static str,\n    pub positional_parameter_names: &'static [&'static str],\n    pub positional_only_parameters: usize,\n    pub required_positional_parameters: usize,\n    pub keyword_only_parameters: &'static [KeywordOnlyParameterDescription],\n}\n\nimpl FunctionDescription {\n    fn full_name(&self) -> String {\n        if let Some(cls_name) = self.cls_name {\n            format!(\"{}.{}()\", cls_name, self.func_name)\n        } else {\n            format!(\"{}()\", self.func_name)\n        }\n    }\n\n    /// Equivalent of `extract_arguments_tuple_dict` which uses the Python C-API \"fastcall\" convention.\n    ///\n    /// # Safety\n    /// - `args` must be a pointer to a C-style array of valid `ffi::PyObject` pointers, or NULL.\n    /// - `kwnames` must be a pointer to a PyTuple, or NULL.\n    /// - `nargs + kwnames.len()` is the total length of the `args` array.\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    pub unsafe fn extract_arguments_fastcall<'py, V, K>(\n        &self,\n        py: Python<'py>,\n        args: *const *mut ffi::PyObject,\n        nargs: ffi::Py_ssize_t,\n        kwnames: *mut ffi::PyObject,\n        output: &mut [Option<PyArg<'py>>],\n    ) -> PyResult<(V::Varargs, K::Varkeywords)>\n    where\n        V: VarargsHandler<'py>,\n        K: VarkeywordsHandler<'py>,\n    {\n        let num_positional_parameters = self.positional_parameter_names.len();\n\n        debug_assert!(nargs >= 0);\n        debug_assert!(self.positional_only_parameters <= num_positional_parameters);\n        debug_assert!(self.required_positional_parameters <= num_positional_parameters);\n        debug_assert_eq!(\n            output.len(),\n            num_positional_parameters + self.keyword_only_parameters.len()\n        );\n\n        // Handle positional arguments\n        // Safety:\n        //  - Option<PyArg> has the same memory layout as `*mut ffi::PyObject`\n        //  - we both have the GIL and can borrow these input references for the `'py` lifetime.\n        let args: *const Option<PyArg<'py>> = args.cast();\n        let positional_args_provided = nargs as usize;\n        let remaining_positional_args = if args.is_null() {\n            debug_assert_eq!(positional_args_provided, 0);\n            &[]\n        } else {\n            // Can consume at most the number of positional parameters in the function definition,\n            // the rest are varargs.\n            let positional_args_to_consume =\n                num_positional_parameters.min(positional_args_provided);\n            let (positional_parameters, remaining) = unsafe {\n                std::slice::from_raw_parts(args, positional_args_provided)\n                    .split_at(positional_args_to_consume)\n            };\n            output[..positional_args_to_consume].copy_from_slice(positional_parameters);\n            remaining\n        };\n        let varargs = V::handle_varargs_fastcall(py, remaining_positional_args, self)?;\n\n        // Handle keyword arguments\n        let mut varkeywords = K::Varkeywords::default();\n\n        // Safety: kwnames is known to be a pointer to a tuple, or null\n        //  - we both have the GIL and can borrow this input reference for the `'py` lifetime.\n        let kwnames: Option<Borrowed<'_, '_, PyTuple>> = unsafe {\n            Borrowed::from_ptr_or_opt(py, kwnames).map(|kwnames| kwnames.cast_unchecked())\n        };\n        if let Some(kwnames) = kwnames {\n            let kwargs = unsafe {\n                ::std::slice::from_raw_parts(\n                    // Safety: PyArg has the same memory layout as `*mut ffi::PyObject`\n                    args.offset(nargs).cast::<PyArg<'py>>(),\n                    kwnames.len(),\n                )\n            };\n\n            self.handle_kwargs::<K, _>(\n                kwnames.iter_borrowed().zip(kwargs.iter().copied()),\n                &mut varkeywords,\n                num_positional_parameters,\n                output,\n            )?\n        }\n\n        // Once all inputs have been processed, check that all required arguments have been provided.\n\n        self.ensure_no_missing_required_positional_arguments(output, positional_args_provided)?;\n        self.ensure_no_missing_required_keyword_arguments(output)?;\n\n        Ok((varargs, varkeywords))\n    }\n\n    /// Extracts the `args` and `kwargs` provided into `output`, according to this function\n    /// definition.\n    ///\n    /// `output` must have the same length as this function has positional and keyword-only\n    /// parameters (as per the `positional_parameter_names` and `keyword_only_parameters`\n    /// respectively).\n    ///\n    /// Unexpected, duplicate or invalid arguments will cause this function to return `TypeError`.\n    ///\n    /// # Safety\n    /// - `args` must be a pointer to a PyTuple.\n    /// - `kwargs` must be a pointer to a PyDict, or NULL.\n    pub unsafe fn extract_arguments_tuple_dict<'py, V, K>(\n        &self,\n        py: Python<'py>,\n        args: *mut ffi::PyObject,\n        kwargs: *mut ffi::PyObject,\n        output: &mut [Option<PyArg<'py>>],\n    ) -> PyResult<(V::Varargs, K::Varkeywords)>\n    where\n        V: VarargsHandler<'py>,\n        K: VarkeywordsHandler<'py>,\n    {\n        // Safety:\n        //  - `args` is known to be a tuple\n        //  - `kwargs` is known to be a dict or null\n        //  - we both have the GIL and can borrow these input references for the `'py` lifetime.\n        let args: Borrowed<'py, 'py, PyTuple> =\n            unsafe { Borrowed::from_ptr(py, args).cast_unchecked::<PyTuple>() };\n        let kwargs: Option<Borrowed<'py, 'py, PyDict>> =\n            unsafe { Borrowed::from_ptr_or_opt(py, kwargs).map(|kwargs| kwargs.cast_unchecked()) };\n\n        let num_positional_parameters = self.positional_parameter_names.len();\n\n        debug_assert!(self.positional_only_parameters <= num_positional_parameters);\n        debug_assert!(self.required_positional_parameters <= num_positional_parameters);\n        debug_assert_eq!(\n            output.len(),\n            num_positional_parameters + self.keyword_only_parameters.len()\n        );\n\n        // Copy positional arguments into output\n        for (i, arg) in args\n            .iter_borrowed()\n            .take(num_positional_parameters)\n            .enumerate()\n        {\n            output[i] = Some(arg);\n        }\n\n        // If any arguments remain, push them to varargs (if possible) or error\n        let varargs = V::handle_varargs_tuple(&args, self)?;\n\n        // Handle keyword arguments\n        let mut varkeywords = K::Varkeywords::default();\n        if let Some(kwargs) = kwargs {\n            self.handle_kwargs::<K, _>(\n                unsafe { kwargs.iter_borrowed() },\n                &mut varkeywords,\n                num_positional_parameters,\n                output,\n            )?\n        }\n\n        // Once all inputs have been processed, check that all required arguments have been provided.\n\n        self.ensure_no_missing_required_positional_arguments(output, args.len())?;\n        self.ensure_no_missing_required_keyword_arguments(output)?;\n\n        Ok((varargs, varkeywords))\n    }\n\n    #[inline]\n    fn handle_kwargs<'py, K, I>(\n        &self,\n        kwargs: I,\n        varkeywords: &mut K::Varkeywords,\n        num_positional_parameters: usize,\n        output: &mut [Option<PyArg<'py>>],\n    ) -> PyResult<()>\n    where\n        K: VarkeywordsHandler<'py>,\n        I: IntoIterator<Item = (PyArg<'py>, PyArg<'py>)>,\n    {\n        debug_assert_eq!(\n            num_positional_parameters,\n            self.positional_parameter_names.len()\n        );\n        debug_assert_eq!(\n            output.len(),\n            num_positional_parameters + self.keyword_only_parameters.len()\n        );\n        let mut positional_only_keyword_arguments = Vec::new();\n        for (kwarg_name_py, value) in kwargs {\n            // Safety: All keyword arguments should be UTF-8 strings, but if it's not, `.to_str()`\n            // will return an error anyway.\n            #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n            let kwarg_name = unsafe { kwarg_name_py.cast_unchecked::<PyString>() }.to_str();\n\n            #[cfg(all(not(Py_3_10), Py_LIMITED_API))]\n            let kwarg_name = kwarg_name_py.extract::<crate::pybacked::PyBackedStr>();\n\n            if let Ok(kwarg_name_owned) = kwarg_name {\n                #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n                let kwarg_name = kwarg_name_owned;\n                #[cfg(all(not(Py_3_10), Py_LIMITED_API))]\n                let kwarg_name: &str = &kwarg_name_owned;\n\n                // Try to place parameter in keyword only parameters\n                if let Some(i) = self.find_keyword_parameter_in_keyword_only(kwarg_name) {\n                    if output[i + num_positional_parameters]\n                        .replace(value)\n                        .is_some()\n                    {\n                        return Err(self.multiple_values_for_argument(kwarg_name));\n                    }\n                    continue;\n                }\n\n                // Repeat for positional parameters\n                if let Some(i) = self.find_keyword_parameter_in_positional(kwarg_name) {\n                    if i < self.positional_only_parameters {\n                        // If accepting **kwargs, then it's allowed for the name of the\n                        // kwarg to conflict with a positional-only argument - the value\n                        // will go into **kwargs anyway.\n                        if K::handle_varkeyword(varkeywords, kwarg_name_py, value, self).is_err() {\n                            positional_only_keyword_arguments.push(kwarg_name_owned);\n                        }\n                    } else if output[i].replace(value).is_some() {\n                        return Err(self.multiple_values_for_argument(kwarg_name));\n                    }\n                    continue;\n                }\n            };\n\n            K::handle_varkeyword(varkeywords, kwarg_name_py, value, self)?\n        }\n\n        if !positional_only_keyword_arguments.is_empty() {\n            #[cfg(all(not(Py_3_10), Py_LIMITED_API))]\n            let positional_only_keyword_arguments: Vec<_> = positional_only_keyword_arguments\n                .iter()\n                .map(std::ops::Deref::deref)\n                .collect();\n            return Err(self.positional_only_keyword_arguments(&positional_only_keyword_arguments));\n        }\n\n        Ok(())\n    }\n\n    #[inline]\n    fn find_keyword_parameter_in_positional(&self, kwarg_name: &str) -> Option<usize> {\n        self.positional_parameter_names\n            .iter()\n            .position(|&param_name| param_name == kwarg_name)\n    }\n\n    #[inline]\n    fn find_keyword_parameter_in_keyword_only(&self, kwarg_name: &str) -> Option<usize> {\n        // Compare the keyword name against each parameter in turn. This is exactly the same method\n        // which CPython uses to map keyword names. Although it's O(num_parameters), the number of\n        // parameters is expected to be small so it's not worth constructing a mapping.\n        self.keyword_only_parameters\n            .iter()\n            .position(|param_desc| param_desc.name == kwarg_name)\n    }\n\n    #[inline]\n    fn ensure_no_missing_required_positional_arguments(\n        &self,\n        output: &[Option<PyArg<'_>>],\n        positional_args_provided: usize,\n    ) -> PyResult<()> {\n        if positional_args_provided < self.required_positional_parameters {\n            for out in &output[positional_args_provided..self.required_positional_parameters] {\n                if out.is_none() {\n                    return Err(self.missing_required_positional_arguments(output));\n                }\n            }\n        }\n        Ok(())\n    }\n\n    #[inline]\n    fn ensure_no_missing_required_keyword_arguments(\n        &self,\n        output: &[Option<PyArg<'_>>],\n    ) -> PyResult<()> {\n        let keyword_output = &output[self.positional_parameter_names.len()..];\n        for (param, out) in self.keyword_only_parameters.iter().zip(keyword_output) {\n            if param.required && out.is_none() {\n                return Err(self.missing_required_keyword_arguments(keyword_output));\n            }\n        }\n        Ok(())\n    }\n\n    #[cold]\n    fn too_many_positional_arguments(&self, args_provided: usize) -> PyErr {\n        let was = if args_provided == 1 { \"was\" } else { \"were\" };\n        let msg = if self.required_positional_parameters != self.positional_parameter_names.len() {\n            format!(\n                \"{} takes from {} to {} positional arguments but {} {} given\",\n                self.full_name(),\n                self.required_positional_parameters,\n                self.positional_parameter_names.len(),\n                args_provided,\n                was\n            )\n        } else {\n            format!(\n                \"{} takes {} positional arguments but {} {} given\",\n                self.full_name(),\n                self.positional_parameter_names.len(),\n                args_provided,\n                was\n            )\n        };\n        PyTypeError::new_err(msg)\n    }\n\n    #[cold]\n    fn multiple_values_for_argument(&self, argument: &str) -> PyErr {\n        PyTypeError::new_err(format!(\n            \"{} got multiple values for argument '{}'\",\n            self.full_name(),\n            argument\n        ))\n    }\n\n    #[cold]\n    fn unexpected_keyword_argument(&self, argument: PyArg<'_>) -> PyErr {\n        PyTypeError::new_err(format!(\n            \"{} got an unexpected keyword argument '{}'\",\n            self.full_name(),\n            argument.as_any()\n        ))\n    }\n\n    #[cold]\n    fn positional_only_keyword_arguments(&self, parameter_names: &[&str]) -> PyErr {\n        let mut msg = format!(\n            \"{} got some positional-only arguments passed as keyword arguments: \",\n            self.full_name()\n        );\n        push_parameter_list(&mut msg, parameter_names);\n        PyTypeError::new_err(msg)\n    }\n\n    #[cold]\n    fn missing_required_arguments(&self, argument_type: &str, parameter_names: &[&str]) -> PyErr {\n        let arguments = if parameter_names.len() == 1 {\n            \"argument\"\n        } else {\n            \"arguments\"\n        };\n        let mut msg = format!(\n            \"{} missing {} required {} {}: \",\n            self.full_name(),\n            parameter_names.len(),\n            argument_type,\n            arguments,\n        );\n        push_parameter_list(&mut msg, parameter_names);\n        PyTypeError::new_err(msg)\n    }\n\n    #[cold]\n    fn missing_required_keyword_arguments(&self, keyword_outputs: &[Option<PyArg<'_>>]) -> PyErr {\n        debug_assert_eq!(self.keyword_only_parameters.len(), keyword_outputs.len());\n\n        let missing_keyword_only_arguments: Vec<_> = self\n            .keyword_only_parameters\n            .iter()\n            .zip(keyword_outputs)\n            .filter_map(|(keyword_desc, out)| {\n                if keyword_desc.required && out.is_none() {\n                    Some(keyword_desc.name)\n                } else {\n                    None\n                }\n            })\n            .collect();\n\n        debug_assert!(!missing_keyword_only_arguments.is_empty());\n        self.missing_required_arguments(\"keyword\", &missing_keyword_only_arguments)\n    }\n\n    #[cold]\n    fn missing_required_positional_arguments(&self, output: &[Option<PyArg<'_>>]) -> PyErr {\n        let missing_positional_arguments: Vec<_> = self\n            .positional_parameter_names\n            .iter()\n            .take(self.required_positional_parameters)\n            .zip(output)\n            .filter_map(|(param, out)| if out.is_none() { Some(*param) } else { None })\n            .collect();\n\n        debug_assert!(!missing_positional_arguments.is_empty());\n        self.missing_required_arguments(\"positional\", &missing_positional_arguments)\n    }\n}\n\n/// Seals `VarargsHandler` so that types outside PyO3 cannot implement it.\nmod varargs_handler {\n    use crate::impl_::extract_argument::{NoVarargs, TupleVarargs};\n\n    pub trait Sealed {}\n\n    impl Sealed for NoVarargs {}\n    impl Sealed for TupleVarargs {}\n}\n\n/// A trait used to control whether to accept varargs in FunctionDescription::extract_argument_(method) functions.\npub trait VarargsHandler<'py>: varargs_handler::Sealed {\n    type Varargs;\n    /// Called by `FunctionDescription::extract_arguments_fastcall` with any additional arguments.\n    fn handle_varargs_fastcall(\n        py: Python<'py>,\n        varargs: &[Option<PyArg<'py>>],\n        function_description: &FunctionDescription,\n    ) -> PyResult<Self::Varargs>;\n    /// Called by `FunctionDescription::extract_arguments_tuple_dict` with the original tuple.\n    ///\n    /// Additional arguments are those in the tuple slice starting from `function_description.positional_parameter_names.len()`.\n    fn handle_varargs_tuple(\n        args: &Bound<'py, PyTuple>,\n        function_description: &FunctionDescription,\n    ) -> PyResult<Self::Varargs>;\n}\n\n/// Marker struct which indicates varargs are not allowed.\npub struct NoVarargs;\n\nimpl<'py> VarargsHandler<'py> for NoVarargs {\n    type Varargs = ();\n\n    #[inline]\n    fn handle_varargs_fastcall(\n        _py: Python<'py>,\n        varargs: &[Option<PyArg<'py>>],\n        function_description: &FunctionDescription,\n    ) -> PyResult<Self::Varargs> {\n        let extra_arguments = varargs.len();\n        if extra_arguments > 0 {\n            return Err(function_description.too_many_positional_arguments(\n                function_description.positional_parameter_names.len() + extra_arguments,\n            ));\n        }\n        Ok(())\n    }\n\n    #[inline]\n    fn handle_varargs_tuple(\n        args: &Bound<'py, PyTuple>,\n        function_description: &FunctionDescription,\n    ) -> PyResult<Self::Varargs> {\n        let positional_parameter_count = function_description.positional_parameter_names.len();\n        let provided_args_count = args.len();\n        if provided_args_count <= positional_parameter_count {\n            Ok(())\n        } else {\n            Err(function_description.too_many_positional_arguments(provided_args_count))\n        }\n    }\n}\n\n/// Marker struct which indicates varargs should be collected into a `PyTuple`.\npub struct TupleVarargs;\n\nimpl<'py> VarargsHandler<'py> for TupleVarargs {\n    type Varargs = Bound<'py, PyTuple>;\n    #[inline]\n    fn handle_varargs_fastcall(\n        py: Python<'py>,\n        varargs: &[Option<PyArg<'py>>],\n        _function_description: &FunctionDescription,\n    ) -> PyResult<Self::Varargs> {\n        PyTuple::new(py, varargs)\n    }\n\n    #[inline]\n    fn handle_varargs_tuple(\n        args: &Bound<'py, PyTuple>,\n        function_description: &FunctionDescription,\n    ) -> PyResult<Self::Varargs> {\n        let positional_parameters = function_description.positional_parameter_names.len();\n        Ok(args.get_slice(positional_parameters, args.len()))\n    }\n}\n\n/// Seals `VarkeywordsHandler` so that types outside PyO3 cannot implement it.\nmod varkeywords_halder {\n    use crate::impl_::extract_argument::{DictVarkeywords, NoVarkeywords};\n\n    pub trait Sealed {}\n\n    impl Sealed for DictVarkeywords {}\n    impl Sealed for NoVarkeywords {}\n}\n\n/// A trait used to control whether to accept varkeywords in FunctionDescription::extract_argument_(method) functions.\npub trait VarkeywordsHandler<'py>: varkeywords_halder::Sealed {\n    type Varkeywords: Default;\n    fn handle_varkeyword(\n        varkeywords: &mut Self::Varkeywords,\n        name: PyArg<'py>,\n        value: PyArg<'py>,\n        function_description: &FunctionDescription,\n    ) -> PyResult<()>;\n}\n\n/// Marker struct which indicates unknown keywords are not permitted.\npub struct NoVarkeywords;\n\nimpl<'py> VarkeywordsHandler<'py> for NoVarkeywords {\n    type Varkeywords = ();\n    #[inline]\n    fn handle_varkeyword(\n        _varkeywords: &mut Self::Varkeywords,\n        name: PyArg<'py>,\n        _value: PyArg<'py>,\n        function_description: &FunctionDescription,\n    ) -> PyResult<()> {\n        Err(function_description.unexpected_keyword_argument(name))\n    }\n}\n\n/// Marker struct which indicates unknown keywords should be collected into a `PyDict`.\npub struct DictVarkeywords;\n\nimpl<'py> VarkeywordsHandler<'py> for DictVarkeywords {\n    type Varkeywords = Option<Bound<'py, PyDict>>;\n    #[inline]\n    fn handle_varkeyword(\n        varkeywords: &mut Self::Varkeywords,\n        name: PyArg<'py>,\n        value: PyArg<'py>,\n        _function_description: &FunctionDescription,\n    ) -> PyResult<()> {\n        varkeywords\n            .get_or_insert_with(|| PyDict::new(name.py()))\n            .set_item(name, value)\n    }\n}\n\nfn push_parameter_list(msg: &mut String, parameter_names: &[&str]) {\n    let len = parameter_names.len();\n    for (i, parameter) in parameter_names.iter().enumerate() {\n        if i != 0 {\n            if len > 2 {\n                msg.push(',');\n            }\n\n            if i == len - 1 {\n                msg.push_str(\" and \")\n            } else {\n                msg.push(' ')\n            }\n        }\n\n        msg.push('\\'');\n        msg.push_str(parameter);\n        msg.push('\\'');\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::{IntoPyDict, PyTuple};\n    use crate::Python;\n\n    use super::{push_parameter_list, FunctionDescription, NoVarargs, NoVarkeywords};\n\n    #[test]\n    fn unexpected_keyword_argument() {\n        let function_description = FunctionDescription {\n            cls_name: None,\n            func_name: \"example\",\n            positional_parameter_names: &[],\n            positional_only_parameters: 0,\n            required_positional_parameters: 0,\n            keyword_only_parameters: &[],\n        };\n\n        Python::attach(|py| {\n            let args = PyTuple::empty(py);\n            let kwargs = [(\"foo\", 0u8)].into_py_dict(py).unwrap();\n            let err = unsafe {\n                function_description\n                    .extract_arguments_tuple_dict::<NoVarargs, NoVarkeywords>(\n                        py,\n                        args.as_ptr(),\n                        kwargs.as_ptr(),\n                        &mut [],\n                    )\n                    .unwrap_err()\n            };\n            assert_eq!(\n                err.to_string(),\n                \"TypeError: example() got an unexpected keyword argument 'foo'\"\n            );\n        })\n    }\n\n    #[test]\n    fn keyword_not_string() {\n        let function_description = FunctionDescription {\n            cls_name: None,\n            func_name: \"example\",\n            positional_parameter_names: &[],\n            positional_only_parameters: 0,\n            required_positional_parameters: 0,\n            keyword_only_parameters: &[],\n        };\n\n        Python::attach(|py| {\n            let args = PyTuple::empty(py);\n            let kwargs = [(1u8, 1u8)].into_py_dict(py).unwrap();\n            let err = unsafe {\n                function_description\n                    .extract_arguments_tuple_dict::<NoVarargs, NoVarkeywords>(\n                        py,\n                        args.as_ptr(),\n                        kwargs.as_ptr(),\n                        &mut [],\n                    )\n                    .unwrap_err()\n            };\n            assert_eq!(\n                err.to_string(),\n                \"TypeError: example() got an unexpected keyword argument '1'\"\n            );\n        })\n    }\n\n    #[test]\n    fn missing_required_arguments() {\n        let function_description = FunctionDescription {\n            cls_name: None,\n            func_name: \"example\",\n            positional_parameter_names: &[\"foo\", \"bar\"],\n            positional_only_parameters: 0,\n            required_positional_parameters: 2,\n            keyword_only_parameters: &[],\n        };\n\n        Python::attach(|py| {\n            let args = PyTuple::empty(py);\n            let mut output = [None, None];\n            let err = unsafe {\n                function_description.extract_arguments_tuple_dict::<NoVarargs, NoVarkeywords>(\n                    py,\n                    args.as_ptr(),\n                    std::ptr::null_mut(),\n                    &mut output,\n                )\n            }\n            .unwrap_err();\n            assert_eq!(\n                err.to_string(),\n                \"TypeError: example() missing 2 required positional arguments: 'foo' and 'bar'\"\n            );\n        })\n    }\n\n    #[test]\n    fn push_parameter_list_empty() {\n        let mut s = String::new();\n        push_parameter_list(&mut s, &[]);\n        assert_eq!(&s, \"\");\n    }\n\n    #[test]\n    fn push_parameter_list_one() {\n        let mut s = String::new();\n        push_parameter_list(&mut s, &[\"a\"]);\n        assert_eq!(&s, \"'a'\");\n    }\n\n    #[test]\n    fn push_parameter_list_two() {\n        let mut s = String::new();\n        push_parameter_list(&mut s, &[\"a\", \"b\"]);\n        assert_eq!(&s, \"'a' and 'b'\");\n    }\n\n    #[test]\n    fn push_parameter_list_three() {\n        let mut s = String::new();\n        push_parameter_list(&mut s, &[\"a\", \"b\", \"c\"]);\n        assert_eq!(&s, \"'a', 'b', and 'c'\");\n    }\n\n    #[test]\n    fn push_parameter_list_four() {\n        let mut s = String::new();\n        push_parameter_list(&mut s, &[\"a\", \"b\", \"c\", \"d\"]);\n        assert_eq!(&s, \"'a', 'b', 'c', and 'd'\");\n    }\n}\n"
  },
  {
    "path": "src/impl_/freelist.rs",
    "content": "//! Support for [free allocation lists][1].\n//!\n//! This can improve performance for types that are often created and deleted in quick succession.\n//!\n//! Rather than implementing this manually,\n//! implement it by annotating a struct with `#[pyclass(freelist = N)]`,\n//! where `N` is the size of the freelist.\n//!\n//! [1]: https://en.wikipedia.org/wiki/Free_list\n\nuse crate::ffi;\nuse std::mem;\n\n/// Represents a slot of a [`PyObjectFreeList`].\nenum PyObjectSlot {\n    /// A free slot.\n    Empty,\n    /// An allocated slot.\n    Filled(*mut ffi::PyObject),\n}\n\n// safety: access is guarded by a per-pyclass mutex\nunsafe impl Send for PyObjectSlot {}\n\n/// A free allocation list for PyObject ffi pointers.\n///\n/// See [the parent module](crate::impl_::freelist) for more details.\npub struct PyObjectFreeList {\n    entries: Box<[PyObjectSlot]>,\n    split: usize,\n    capacity: usize,\n}\n\nimpl PyObjectFreeList {\n    /// Creates a new `PyObjectFreeList` instance with specified capacity.\n    pub fn with_capacity(capacity: usize) -> PyObjectFreeList {\n        let entries = (0..capacity)\n            .map(|_| PyObjectSlot::Empty)\n            .collect::<Box<[_]>>();\n\n        PyObjectFreeList {\n            entries,\n            split: 0,\n            capacity,\n        }\n    }\n\n    /// Pops the first non empty item.\n    pub fn pop(&mut self) -> Option<*mut ffi::PyObject> {\n        let idx = self.split;\n        if idx == 0 {\n            None\n        } else {\n            match mem::replace(&mut self.entries[idx - 1], PyObjectSlot::Empty) {\n                PyObjectSlot::Filled(v) => {\n                    self.split = idx - 1;\n                    Some(v)\n                }\n                _ => panic!(\"PyObjectFreeList is corrupt\"),\n            }\n        }\n    }\n\n    /// Inserts a value into the list. Returns `Some(val)` if the `PyObjectFreeList` is full.\n    pub fn insert(&mut self, val: *mut ffi::PyObject) -> Option<*mut ffi::PyObject> {\n        let next = self.split + 1;\n        if next < self.capacity {\n            self.entries[self.split] = PyObjectSlot::Filled(val);\n            self.split = next;\n            None\n        } else {\n            Some(val)\n        }\n    }\n}\n"
  },
  {
    "path": "src/impl_/frompyobject.rs",
    "content": "use crate::types::any::PyAnyMethods;\nuse crate::Bound;\nuse crate::{exceptions::PyTypeError, FromPyObject, PyAny, PyErr, PyResult, Python};\n\n#[cold]\npub fn failed_to_extract_enum(\n    py: Python<'_>,\n    type_name: &str,\n    variant_names: &[&str],\n    error_names: &[&str],\n    errors: &[PyErr],\n) -> PyErr {\n    // TODO maybe use ExceptionGroup on Python 3.11+ ?\n    let mut err_msg = format!(\n        \"failed to extract enum {} ('{}')\",\n        type_name,\n        error_names.join(\" | \")\n    );\n    for ((variant_name, error_name), error) in variant_names.iter().zip(error_names).zip(errors) {\n        use std::fmt::Write;\n        write!(\n            &mut err_msg,\n            \"\\n- variant {variant_name} ({error_name}): {error_msg}\",\n            variant_name = variant_name,\n            error_name = error_name,\n            error_msg = extract_traceback(py, error.clone_ref(py)),\n        )\n        .unwrap();\n    }\n    PyTypeError::new_err(err_msg)\n}\n\n/// Flattens a chain of errors into a single string.\nfn extract_traceback(py: Python<'_>, mut error: PyErr) -> String {\n    use std::fmt::Write;\n\n    let mut error_msg = error.to_string();\n    while let Some(cause) = error.cause(py) {\n        write!(&mut error_msg, \", caused by {cause}\").unwrap();\n        error = cause\n    }\n    error_msg\n}\n\npub fn extract_struct_field<'a, 'py, T>(\n    obj: &'a Bound<'py, PyAny>,\n    struct_name: &str,\n    field_name: &str,\n) -> PyResult<T>\nwhere\n    T: FromPyObject<'a, 'py>,\n{\n    match obj.extract() {\n        Ok(value) => Ok(value),\n        Err(err) => Err(failed_to_extract_struct_field(\n            obj.py(),\n            err.into(),\n            struct_name,\n            field_name,\n        )),\n    }\n}\n\npub fn extract_struct_field_with<'a, 'py, T>(\n    extractor: fn(&'a Bound<'py, PyAny>) -> PyResult<T>,\n    obj: &'a Bound<'py, PyAny>,\n    struct_name: &str,\n    field_name: &str,\n) -> PyResult<T> {\n    match extractor(obj) {\n        Ok(value) => Ok(value),\n        Err(err) => Err(failed_to_extract_struct_field(\n            obj.py(),\n            err,\n            struct_name,\n            field_name,\n        )),\n    }\n}\n\n#[cold]\nfn failed_to_extract_struct_field(\n    py: Python<'_>,\n    inner_err: PyErr,\n    struct_name: &str,\n    field_name: &str,\n) -> PyErr {\n    let new_err = PyTypeError::new_err(format!(\n        \"failed to extract field {struct_name}.{field_name}\"\n    ));\n    new_err.set_cause(py, ::std::option::Option::Some(inner_err));\n    new_err\n}\n\npub fn extract_tuple_struct_field<'a, 'py, T>(\n    obj: &'a Bound<'py, PyAny>,\n    struct_name: &str,\n    index: usize,\n) -> PyResult<T>\nwhere\n    T: FromPyObject<'a, 'py>,\n{\n    match obj.extract() {\n        Ok(value) => Ok(value),\n        Err(err) => Err(failed_to_extract_tuple_struct_field(\n            obj.py(),\n            err.into(),\n            struct_name,\n            index,\n        )),\n    }\n}\n\npub fn extract_tuple_struct_field_with<'a, 'py, T>(\n    extractor: fn(&'a Bound<'py, PyAny>) -> PyResult<T>,\n    obj: &'a Bound<'py, PyAny>,\n    struct_name: &str,\n    index: usize,\n) -> PyResult<T> {\n    match extractor(obj) {\n        Ok(value) => Ok(value),\n        Err(err) => Err(failed_to_extract_tuple_struct_field(\n            obj.py(),\n            err,\n            struct_name,\n            index,\n        )),\n    }\n}\n\n#[cold]\nfn failed_to_extract_tuple_struct_field(\n    py: Python<'_>,\n    inner_err: PyErr,\n    struct_name: &str,\n    index: usize,\n) -> PyErr {\n    let new_err = PyTypeError::new_err(format!(\"failed to extract field {struct_name}.{index}\"));\n    new_err.set_cause(py, ::std::option::Option::Some(inner_err));\n    new_err\n}\n"
  },
  {
    "path": "src/impl_/introspection.rs",
    "content": "use crate::conversion::IntoPyObject;\nuse crate::inspect::PyStaticExpr;\n\n/// Seals `PyReturnType` so that types outside PyO3 cannot implement it.\nmod return_type {\n    use crate::{impl_::introspection::PyReturnType, IntoPyObject};\n\n    pub trait Sealed {}\n\n    impl<'a, T: IntoPyObject<'a>> Sealed for T {}\n    impl<T: PyReturnType, E> Sealed for Result<T, E> {}\n}\n\n/// Trait to guess a function Python return type\n///\n/// It is useful to properly get the return type `T` when the Rust implementation returns e.g. `PyResult<T>`\npub trait PyReturnType: return_type::Sealed {\n    /// The function return type\n    const OUTPUT_TYPE: PyStaticExpr;\n}\n\nimpl<'a, T: IntoPyObject<'a>> PyReturnType for T {\n    const OUTPUT_TYPE: PyStaticExpr = T::OUTPUT_TYPE;\n}\n\nimpl<T: PyReturnType, E> PyReturnType for Result<T, E> {\n    const OUTPUT_TYPE: PyStaticExpr = T::OUTPUT_TYPE;\n}\n\n#[repr(C)]\npub struct SerializedIntrospectionFragment<const LEN: usize> {\n    pub length: u32,\n    pub fragment: [u8; LEN],\n}\n\n/// Escapes a string to be valid JSON. Does not add quotes around it\n///\n/// Returns the number of written bytes\npub const fn escape_json_string(input: &str, output: &mut [u8]) -> usize {\n    let input = input.as_bytes();\n    let mut input_i = 0;\n    let mut output_i = 0;\n    while input_i < input.len() {\n        match input[input_i] {\n            b'\\\\' => {\n                output[output_i] = b'\\\\';\n                output_i += 1;\n                output[output_i] = b'\\\\';\n                output_i += 1;\n            }\n            b'\"' => {\n                output[output_i] = b'\\\\';\n                output_i += 1;\n                output[output_i] = b'\"';\n                output_i += 1;\n            }\n            0x08 => {\n                output[output_i] = b'\\\\';\n                output_i += 1;\n                output[output_i] = b'b';\n                output_i += 1;\n            }\n            0x0C => {\n                output[output_i] = b'\\\\';\n                output_i += 1;\n                output[output_i] = b'f';\n                output_i += 1;\n            }\n            b'\\n' => {\n                output[output_i] = b'\\\\';\n                output_i += 1;\n                output[output_i] = b'n';\n                output_i += 1;\n            }\n            b'\\r' => {\n                output[output_i] = b'\\\\';\n                output_i += 1;\n                output[output_i] = b'r';\n                output_i += 1;\n            }\n            b'\\t' => {\n                output[output_i] = b'\\\\';\n                output_i += 1;\n                output[output_i] = b't';\n                output_i += 1;\n            }\n            c @ 0..32 => {\n                output[output_i] = b'\\\\';\n                output_i += 1;\n                output[output_i] = b'u';\n                output_i += 1;\n                output[output_i] = b'0';\n                output_i += 1;\n                output[output_i] = b'0';\n                output_i += 1;\n                output[output_i] = b'0' + (c / 16);\n                output_i += 1;\n                let remainer = c % 16;\n                output[output_i] = if remainer >= 10 {\n                    b'a' + remainer - 10\n                } else {\n                    b'0' + remainer\n                };\n                output_i += 1;\n            }\n            c => {\n                output[output_i] = c;\n                output_i += 1;\n            }\n        }\n        input_i += 1;\n    }\n    output_i\n}\n\n/// Number of bytes written by [`escape_json_string`]\npub const fn escaped_json_string_len(input: &str) -> usize {\n    let input = input.as_bytes();\n    let mut len = 0;\n    let mut i = 0;\n    while i < input.len() {\n        len += match input[i] {\n            b'\\\\' | b'\"' | 0x08 | 0x0C | b'\\n' | b'\\r' | b'\\t' => 2,\n            0..32 => 6,\n            _ => 1,\n        };\n        i += 1;\n    }\n    len\n}\n"
  },
  {
    "path": "src/impl_/panic.rs",
    "content": "/// Type which will panic if dropped.\n///\n/// If this is dropped during a panic, this will cause an abort.\n///\n/// Use this to avoid letting unwinds cross through the FFI boundary, which is UB.\npub struct PanicTrap {\n    msg: &'static str,\n}\n\nimpl PanicTrap {\n    #[inline]\n    pub const fn new(msg: &'static str) -> Self {\n        Self { msg }\n    }\n\n    #[inline]\n    pub const fn disarm(self) {\n        std::mem::forget(self)\n    }\n}\n\nimpl Drop for PanicTrap {\n    fn drop(&mut self) {\n        // Panic here will abort the process, assuming in an unwind.\n        panic!(\"{}\", self.msg)\n    }\n}\n"
  },
  {
    "path": "src/impl_/pycell.rs",
    "content": "//! Externally-accessible implementation of pycell\npub use crate::pycell::impl_::{\n    GetBorrowChecker, PyClassMutability, PyClassObjectBase, PyClassObjectBaseLayout,\n    PyStaticClassObject, PyVariableClassObject, PyVariableClassObjectBase,\n};\n"
  },
  {
    "path": "src/impl_/pyclass/assertions.rs",
    "content": "/// Helper function that can be used at compile time to emit a diagnostic if\n/// the type does not implement `Send` or `Sync` when it should; the mere act\n/// of invoking this function will cause the diagnostic to be emitted if needed.\npub const fn assert_pyclass_send_sync<T>()\nwhere\n    T: Send + Sync,\n{\n}\n\n#[track_caller]\n#[allow(clippy::assertions_on_constants, reason = \"invoked by a proc macro\")]\npub const fn assert_dict_supported() {\n    assert!(\n        cfg!(any(not(Py_LIMITED_API), Py_3_9)),\n        \"`dict` requires Python >= 3.9 when using the `abi3` feature\"\n    );\n}\n\n#[track_caller]\n#[allow(clippy::assertions_on_constants, reason = \"invoked by a proc macro\")]\npub const fn assert_weakref_supported() {\n    assert!(\n        cfg!(any(not(Py_LIMITED_API), Py_3_9)),\n        \"`weakref` requires Python >= 3.9 when using the `abi3` feature\"\n    )\n}\n\n#[track_caller]\n#[allow(clippy::assertions_on_constants, reason = \"invoked by a proc macro\")]\npub const fn assert_immutable_type_supported() {\n    assert!(\n        cfg!(any(all(Py_3_10, not(Py_LIMITED_API)), Py_3_14)),\n        \"`immutable_type` requires Python >= 3.10 (or >= 3.14 when using the `abi3` feature)\"\n    );\n}\n\nmod tests {\n    #[cfg(feature = \"macros\")]\n    #[test]\n    fn test_assert_pyclass_send_sync() {\n        #[crate::pyclass(crate = \"crate\")]\n        struct MyClass {}\n\n        super::assert_pyclass_send_sync::<MyClass>();\n    }\n}\n"
  },
  {
    "path": "src/impl_/pyclass/doc.rs",
    "content": "use std::{ffi::CStr, marker::PhantomData};\n\nuse crate::{impl_::pyclass::PyClassImpl, PyClass};\n\n/// Trait implemented by classes with a known text signature for instantiation.\n///\n/// This is implemented by the `#[pymethods]` macro when handling expansion for a\n/// `#[new]` method.\npub trait PyClassNewTextSignature {\n    const TEXT_SIGNATURE: &'static str;\n}\n\n/// Type which uses specialization on impl blocks to facilitate generating the documentation for a\n/// `#[pyclass]` type.\n///\n/// At the moment, this is only used to help lift the `TEXT_SIGNATURE` constant to compile time\n/// providing a base case and a specialized implementation when the signature is known at compile time.\n///\n/// In the future when const eval is more advanced, it will probably be possible to format the whole\n/// class docstring at compile time as part of this type instead of in macro expansion.\npub struct PyClassDocGenerator<\n    ClassT: PyClass,\n    // switch to determine if a signature for class instantiation is known\n    const HAS_NEW_TEXT_SIGNATURE: bool,\n>(PhantomData<ClassT>);\n\nimpl<ClassT: PyClass + PyClassNewTextSignature> PyClassDocGenerator<ClassT, true> {\n    pub const DOC_PIECES: &'static [&'static [u8]] = &[\n        <ClassT as PyClass>::NAME.as_bytes(),\n        ClassT::TEXT_SIGNATURE.as_bytes(),\n        b\"\\n--\\n\\n\",\n        <ClassT as PyClassImpl>::RAW_DOC.to_bytes_with_nul(),\n    ];\n}\n\nimpl<ClassT: PyClass> PyClassDocGenerator<ClassT, false> {\n    pub const DOC_PIECES: &'static [&'static [u8]] =\n        &[<ClassT as PyClassImpl>::RAW_DOC.to_bytes_with_nul()];\n}\n\n/// Casts bytes to a CStr, ensuring they are valid.\npub const fn doc_bytes_as_cstr(bytes: &'static [u8]) -> &'static ::std::ffi::CStr {\n    match CStr::from_bytes_with_nul(bytes) {\n        Ok(cstr) => cstr,\n        #[cfg(not(from_bytes_with_nul_error))] // MSRV 1.86\n        Err(_) => panic!(\"invalid pyclass doc\"),\n        #[cfg(from_bytes_with_nul_error)]\n        // This case may happen if the user provides an invalid docstring\n        Err(std::ffi::FromBytesWithNulError::InteriorNul { .. }) => {\n            panic!(\"pyclass doc contains nul bytes\")\n        }\n        // This case shouldn't happen using the macro machinery as long as `PyClassDocGenerator`\n        // uses the RAW_DOC as the final piece, which is nul terminated.\n        #[cfg(from_bytes_with_nul_error)]\n        Err(std::ffi::FromBytesWithNulError::NotNulTerminated) => {\n            panic!(\"pyclass doc expected to be nul terminated\")\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    #[cfg(feature = \"macros\")]\n    fn test_doc_generator() {\n        use crate::impl_::concat::{combine_to_array, combined_len};\n\n        /// A dummy class with signature.\n        #[crate::pyclass(crate = \"crate\")]\n        struct MyClass;\n\n        #[crate::pymethods(crate = \"crate\")]\n        impl MyClass {\n            #[new]\n            fn new(x: i32, y: i32) -> Self {\n                let _ = (x, y); // suppress unused variable warnings\n                MyClass\n            }\n        }\n\n        // simulate what the macro is doing\n        const PIECES: &[&[u8]] = PyClassDocGenerator::<MyClass, true>::DOC_PIECES;\n        assert_eq!(\n            &combine_to_array::<{ combined_len(PIECES) }>(PIECES),\n            b\"MyClass(x, y)\\n--\\n\\nA dummy class with signature.\\0\"\n        );\n\n        // simulate if the macro detected no text signature\n        const PIECES_WITHOUT_SIGNATURE: &[&[u8]] =\n            PyClassDocGenerator::<MyClass, false>::DOC_PIECES;\n        assert_eq!(\n            &combine_to_array::<{ combined_len(PIECES_WITHOUT_SIGNATURE) }>(\n                PIECES_WITHOUT_SIGNATURE\n            ),\n            b\"A dummy class with signature.\\0\"\n        );\n    }\n\n    #[test]\n    fn test_doc_bytes_as_cstr() {\n        let cstr = doc_bytes_as_cstr(b\"MyClass\\0\");\n        assert_eq!(cstr, c\"MyClass\");\n    }\n\n    #[test]\n    #[cfg(from_bytes_with_nul_error)]\n    #[should_panic(expected = \"pyclass doc contains nul bytes\")]\n    fn test_doc_bytes_as_cstr_central_nul() {\n        doc_bytes_as_cstr(b\"MyClass\\0Foo\");\n    }\n\n    #[test]\n    #[cfg(from_bytes_with_nul_error)]\n    #[should_panic(expected = \"pyclass doc expected to be nul terminated\")]\n    fn test_doc_bytes_as_cstr_not_nul_terminated() {\n        doc_bytes_as_cstr(b\"MyClass\");\n    }\n}\n"
  },
  {
    "path": "src/impl_/pyclass/lazy_type_object.rs",
    "content": "use std::{\n    ffi::CStr,\n    marker::PhantomData,\n    thread::{self, ThreadId},\n};\n\n#[cfg(Py_3_14)]\nuse crate::err::error_on_minusone;\n#[allow(deprecated)]\nuse crate::sync::GILOnceCell;\n#[cfg(Py_3_14)]\nuse crate::types::PyTypeMethods;\nuse crate::{\n    exceptions::PyRuntimeError,\n    ffi,\n    impl_::pymethods::PyMethodDefType,\n    pyclass::{create_type_object, PyClassTypeObject},\n    types::PyType,\n    Bound, Py, PyAny, PyClass, PyErr, PyResult, Python,\n};\n\nuse std::sync::Mutex;\n\nuse super::PyClassItemsIter;\n\n/// Lazy type object for PyClass.\n#[doc(hidden)]\npub struct LazyTypeObject<T>(LazyTypeObjectInner, PhantomData<T>);\n\n// Non-generic inner of LazyTypeObject to keep code size down\nstruct LazyTypeObjectInner {\n    #[allow(deprecated)]\n    value: GILOnceCell<PyClassTypeObject>,\n    // Threads which have begun initialization of the `tp_dict`. Used for\n    // reentrant initialization detection.\n    initializing_threads: Mutex<Vec<ThreadId>>,\n    #[allow(deprecated)]\n    fully_initialized_type: GILOnceCell<Py<PyType>>,\n}\n\nimpl<T> LazyTypeObject<T> {\n    /// Creates an uninitialized `LazyTypeObject`.\n    #[allow(clippy::new_without_default)]\n    pub const fn new() -> Self {\n        LazyTypeObject(\n            LazyTypeObjectInner {\n                #[allow(deprecated)]\n                value: GILOnceCell::new(),\n                initializing_threads: Mutex::new(Vec::new()),\n                #[allow(deprecated)]\n                fully_initialized_type: GILOnceCell::new(),\n            },\n            PhantomData,\n        )\n    }\n}\n\nimpl<T: PyClass> LazyTypeObject<T> {\n    /// Gets the type object contained by this `LazyTypeObject`, initializing it if needed.\n    #[inline]\n    pub fn get_or_try_init<'py>(&self, py: Python<'py>) -> PyResult<&Bound<'py, PyType>> {\n        if let Some(type_object) = self.0.fully_initialized_type.get(py) {\n            // Fast path\n            return Ok(type_object.bind(py));\n        }\n\n        self.try_init(py)\n    }\n\n    #[cold]\n    fn try_init<'py>(&self, py: Python<'py>) -> PyResult<&Bound<'py, PyType>> {\n        self.0.get_or_try_init(\n            py,\n            create_type_object::<T>,\n            <T as PyClass>::NAME,\n            T::items_iter(),\n        )\n    }\n}\n\nimpl LazyTypeObjectInner {\n    // Uses dynamically dispatched fn(Python<'py>) -> PyResult<Py<PyType>\n    // so that this code is only instantiated once, instead of for every T\n    // like the generic LazyTypeObject<T> methods above.\n    fn get_or_try_init<'py>(\n        &self,\n        py: Python<'py>,\n        init: fn(Python<'py>) -> PyResult<PyClassTypeObject>,\n        name: &str,\n        items_iter: PyClassItemsIter,\n    ) -> PyResult<&Bound<'py, PyType>> {\n        (|| -> PyResult<_> {\n            let PyClassTypeObject {\n                type_object,\n                is_immutable_type,\n                ..\n            } = self.value.get_or_try_init(py, || init(py))?;\n            let type_object = type_object.bind(py);\n            self.ensure_init(type_object, *is_immutable_type, name, items_iter)?;\n            Ok(type_object)\n        })()\n        .map_err(|err| {\n            wrap_in_runtime_error(\n                py,\n                err,\n                format!(\"An error occurred while initializing class {name}\"),\n            )\n        })\n    }\n\n    fn ensure_init(\n        &self,\n        type_object: &Bound<'_, PyType>,\n        #[allow(unused_variables)] is_immutable_type: bool,\n        name: &str,\n        items_iter: PyClassItemsIter,\n    ) -> PyResult<()> {\n        let py = type_object.py();\n\n        // We might want to fill the `tp_dict` with python instances of `T`\n        // itself. In order to do so, we must first initialize the type object\n        // with an empty `tp_dict`: now we can create instances of `T`.\n        //\n        // Then we fill the `tp_dict`. Multiple threads may try to fill it at\n        // the same time, but only one of them will succeed.\n        //\n        // More importantly, if a thread is performing initialization of the\n        // `tp_dict`, it can still request the type object through `get_or_init`,\n        // but the `tp_dict` may appear empty of course.\n\n        if self.fully_initialized_type.get(py).is_some() {\n            // `tp_dict` is already filled: ok.\n            return Ok(());\n        }\n\n        let thread_id = thread::current().id();\n        {\n            let mut threads = self.initializing_threads.lock().unwrap();\n            if threads.contains(&thread_id) {\n                // Reentrant call: just return the type object, even if the\n                // `tp_dict` is not filled yet.\n                return Ok(());\n            }\n            threads.push(thread_id);\n        }\n\n        struct InitializationGuard<'a> {\n            initializing_threads: &'a Mutex<Vec<ThreadId>>,\n            thread_id: ThreadId,\n        }\n        impl Drop for InitializationGuard<'_> {\n            fn drop(&mut self) {\n                let mut threads = self.initializing_threads.lock().unwrap();\n                threads.retain(|id| *id != self.thread_id);\n            }\n        }\n\n        let guard = InitializationGuard {\n            initializing_threads: &self.initializing_threads,\n            thread_id,\n        };\n\n        // Pre-compute the class attribute objects: this can temporarily\n        // release the GIL since we're calling into arbitrary user code. It\n        // means that another thread can continue the initialization in the\n        // meantime: at worst, we'll just make a useless computation.\n        let mut items = vec![];\n        for class_items in items_iter {\n            for method in class_items.methods {\n                if let PyMethodDefType::ClassAttribute(attr) = method {\n                    match (attr.meth)(py) {\n                        Ok(val) => items.push((attr.name, val)),\n                        Err(err) => {\n                            return Err(wrap_in_runtime_error(\n                                py,\n                                err,\n                                format!(\n                                    \"An error occurred while initializing `{}.{}`\",\n                                    name,\n                                    attr.name.to_str().unwrap()\n                                ),\n                            ))\n                        }\n                    }\n                }\n            }\n        }\n\n        // Now we hold the GIL and we can assume it won't be released until we\n        // return from the function.\n        let result = self.fully_initialized_type.get_or_try_init(py, move || {\n            initialize_tp_dict(py, type_object.as_ptr(), items)?;\n            #[cfg(Py_3_14)]\n            if is_immutable_type {\n                // freeze immutable types after __dict__ is initialized\n                let res = unsafe { ffi::PyType_Freeze(type_object.as_type_ptr()) };\n                error_on_minusone(py, res)?;\n            }\n            #[cfg(all(Py_3_10, not(Py_LIMITED_API), not(Py_3_14)))]\n            if is_immutable_type {\n                use crate::types::PyTypeMethods as _;\n                #[cfg(not(Py_GIL_DISABLED))]\n                unsafe {\n                    (*type_object.as_type_ptr()).tp_flags |= ffi::Py_TPFLAGS_IMMUTABLETYPE\n                };\n                #[cfg(Py_GIL_DISABLED)]\n                unsafe {\n                    (*type_object.as_type_ptr()).tp_flags.fetch_or(\n                        ffi::Py_TPFLAGS_IMMUTABLETYPE,\n                        std::sync::atomic::Ordering::Relaxed,\n                    )\n                };\n                unsafe { ffi::PyType_Modified(type_object.as_type_ptr()) };\n            }\n\n            // Initialization successfully complete, can clear the thread list.\n            // (No further calls to get_or_init() will try to init, on any thread.)\n            let mut threads = {\n                drop(guard);\n                self.initializing_threads.lock().unwrap()\n            };\n            threads.clear();\n            Ok(type_object.clone().unbind())\n        });\n\n        if let Err(err) = result {\n            return Err(wrap_in_runtime_error(\n                py,\n                err,\n                format!(\"An error occurred while initializing `{name}.__dict__`\"),\n            ));\n        }\n\n        Ok(())\n    }\n}\n\nfn initialize_tp_dict(\n    py: Python<'_>,\n    type_object: *mut ffi::PyObject,\n    items: Vec<(&'static CStr, Py<PyAny>)>,\n) -> PyResult<()> {\n    // We hold the GIL: the dictionary update can be considered atomic from\n    // the POV of other threads.\n    for (key, val) in items {\n        crate::err::error_on_minusone(py, unsafe {\n            ffi::PyObject_SetAttrString(type_object, key.as_ptr(), val.into_ptr())\n        })?;\n    }\n    Ok(())\n}\n\n// This is necessary for making static `LazyTypeObject`s\nunsafe impl<T> Sync for LazyTypeObject<T> {}\n\n/// Used in the macro-expanded implementation of `type_object_raw` for `#[pyclass]` types\n#[cold]\npub fn type_object_init_failed(py: Python<'_>, err: PyErr, type_name: &str) -> ! {\n    err.write_unraisable(py, None);\n    panic!(\"failed to create type object for `{type_name}`\")\n}\n\n#[cold]\nfn wrap_in_runtime_error(py: Python<'_>, err: PyErr, message: String) -> PyErr {\n    let runtime_err = PyRuntimeError::new_err(message);\n    runtime_err.set_cause(py, Some(err));\n    runtime_err\n}\n"
  },
  {
    "path": "src/impl_/pyclass/probes.rs",
    "content": "use std::marker::PhantomData;\n\nuse crate::conversion::IntoPyObject;\nuse crate::impl_::pyclass::PyClassBaseType;\nuse crate::impl_::pyclass_init::PyNativeTypeInitializer;\nuse crate::{FromPyObject, Py, PyClass, PyClassInitializer};\n\n/// Trait used to combine with zero-sized types to calculate at compile time\n/// some property of a type.\n///\n/// The trick uses the fact that an associated constant has higher priority\n/// than a trait constant, so we can use the trait to define the false case.\n///\n/// The true case is defined in the zero-sized type's impl block, which is\n/// gated on some property like trait bound or only being implemented\n/// for fixed concrete types.\npub trait Probe: probe::Sealed {\n    const VALUE: bool = false;\n}\n\n/// Seals `Probe` so that types outside PyO3 cannot implement it.\nmod probe {\n    pub trait Sealed {}\n}\n\nmacro_rules! probe {\n    ($name:ident) => {\n        pub struct $name<T>(PhantomData<T>);\n        impl<T> Probe for $name<T> {}\n        impl<T> probe::Sealed for $name<T> {}\n    };\n}\n\nprobe!(IsPyT);\n\nimpl<T> IsPyT<Py<T>> {\n    pub const VALUE: bool = true;\n}\n\nprobe!(IsIntoPyObjectRef);\n\nimpl<'a, 'py, T: 'a> IsIntoPyObjectRef<T>\nwhere\n    &'a T: IntoPyObject<'py>,\n{\n    pub const VALUE: bool = true;\n}\n\nprobe!(IsIntoPyObject);\n\nimpl<'py, T> IsIntoPyObject<T>\nwhere\n    T: IntoPyObject<'py>,\n{\n    pub const VALUE: bool = true;\n}\n\nprobe!(IsSend);\n\nimpl<T: Send> IsSend<T> {\n    pub const VALUE: bool = true;\n}\n\nprobe!(IsSync);\n\nimpl<T: Sync> IsSync<T> {\n    pub const VALUE: bool = true;\n}\n\nprobe!(IsFromPyObject);\n\nimpl<'a, 'py, T> IsFromPyObject<T>\nwhere\n    T: FromPyObject<'a, 'py>,\n{\n    pub const VALUE: bool = true;\n}\n\nprobe!(HasNewTextSignature);\n\nimpl<T: super::doc::PyClassNewTextSignature> HasNewTextSignature<T> {\n    pub const VALUE: bool = true;\n}\n\nprobe!(IsClone);\n\nimpl<T: Clone> IsClone<T> {\n    pub const VALUE: bool = true;\n}\n\nprobe!(IsReturningEmptyTuple);\n\nimpl IsReturningEmptyTuple<()> {\n    pub const VALUE: bool = true;\n}\n\nimpl<E> IsReturningEmptyTuple<Result<(), E>> {\n    pub const VALUE: bool = true;\n}\n\nprobe!(IsPyClass);\n\nimpl<T> IsPyClass<T>\nwhere\n    T: PyClass,\n{\n    pub const VALUE: bool = true;\n}\n\nimpl<T, E> IsPyClass<Result<T, E>>\nwhere\n    T: PyClass,\n{\n    pub const VALUE: bool = true;\n}\n\nprobe!(IsInitializerTuple);\n\nimpl<S, B> IsInitializerTuple<(S, B)>\nwhere\n    S: PyClass<BaseType = B>,\n    B: PyClass + PyClassBaseType<Initializer = PyClassInitializer<B>>,\n    B::BaseType: PyClassBaseType<Initializer = PyNativeTypeInitializer<B::BaseType>>,\n{\n    pub const VALUE: bool = true;\n}\nimpl<S, B, E> IsInitializerTuple<Result<(S, B), E>>\nwhere\n    S: PyClass<BaseType = B>,\n    B: PyClass + PyClassBaseType<Initializer = PyClassInitializer<B>>,\n    B::BaseType: PyClassBaseType<Initializer = PyNativeTypeInitializer<B::BaseType>>,\n{\n    pub const VALUE: bool = true;\n}\n\n#[cfg(test)]\nmacro_rules! value_of {\n    ($probe:ident, $ty:ty) => {{\n        #[allow(unused_imports)] // probe trait not used if VALUE is true\n        use crate::impl_::pyclass::Probe as _;\n        $probe::<$ty>::VALUE\n    }};\n}\n\n#[cfg(test)]\npub(crate) use value_of;\n"
  },
  {
    "path": "src/impl_/pyclass.rs",
    "content": "use crate::{\n    exceptions::{PyAttributeError, PyNotImplementedError, PyRuntimeError},\n    ffi,\n    ffi_ptr_ext::FfiPtrExt,\n    impl_::{\n        freelist::PyObjectFreeList,\n        pycell::{GetBorrowChecker, PyClassMutability, PyClassObjectBaseLayout},\n        pyclass_init::PyObjectInit,\n        pymethods::{PyGetterDef, PyMethodDefType},\n    },\n    pycell::{impl_::PyClassObjectLayout, PyBorrowError},\n    types::{any::PyAnyMethods, PyBool},\n    Borrowed, IntoPyObject, IntoPyObjectExt, Py, PyAny, PyClass, PyClassGuard, PyErr, PyResult,\n    PyTypeCheck, PyTypeInfo, Python,\n};\nuse std::{\n    ffi::CStr,\n    marker::PhantomData,\n    os::raw::{c_int, c_void},\n    ptr::{self, NonNull},\n    sync::Mutex,\n    thread,\n};\n\nmod assertions;\npub mod doc;\nmod lazy_type_object;\n#[macro_use]\nmod probes;\n\npub use assertions::*;\npub use lazy_type_object::{type_object_init_failed, LazyTypeObject};\npub use probes::*;\n\n/// Gets the offset of the dictionary from the start of the object in bytes.\n#[inline]\npub const fn dict_offset<T: PyClass>() -> PyObjectOffset {\n    <T as PyClassImpl>::Layout::DICT_OFFSET\n}\n\n/// Gets the offset of the weakref list from the start of the object in bytes.\n#[inline]\npub const fn weaklist_offset<T: PyClass>() -> PyObjectOffset {\n    <T as PyClassImpl>::Layout::WEAKLIST_OFFSET\n}\n\nmod sealed {\n    pub trait Sealed {}\n\n    impl Sealed for super::PyClassDummySlot {}\n    impl Sealed for super::PyClassDictSlot {}\n    impl Sealed for super::PyClassWeakRefSlot {}\n    impl Sealed for super::ThreadCheckerImpl {}\n    impl Sealed for super::NoopThreadChecker {}\n}\n\n/// Represents the `__dict__` field for `#[pyclass]`.\npub trait PyClassDict: sealed::Sealed {\n    /// Initial form of a [PyObject](crate::ffi::PyObject) `__dict__` reference.\n    const INIT: Self;\n    /// Empties the dictionary of its key-value pairs.\n    #[inline]\n    fn clear_dict(&mut self, _py: Python<'_>) {}\n}\n\n/// Represents the `__weakref__` field for `#[pyclass]`.\npub trait PyClassWeakRef: sealed::Sealed {\n    /// Initializes a `weakref` instance.\n    const INIT: Self;\n    /// Clears the weak references to the given object.\n    ///\n    /// # Safety\n    /// - `_obj` must be a pointer to the pyclass instance which contains `self`.\n    /// - The GIL must be held.\n    #[inline]\n    unsafe fn clear_weakrefs(&mut self, _obj: *mut ffi::PyObject, _py: Python<'_>) {}\n}\n\n/// Zero-sized dummy field.\npub struct PyClassDummySlot;\n\nimpl PyClassDict for PyClassDummySlot {\n    const INIT: Self = PyClassDummySlot;\n}\n\nimpl PyClassWeakRef for PyClassDummySlot {\n    const INIT: Self = PyClassDummySlot;\n}\n\n/// Actual dict field, which holds the pointer to `__dict__`.\n///\n/// `#[pyclass(dict)]` automatically adds this.\n#[repr(transparent)]\npub struct PyClassDictSlot(*mut ffi::PyObject);\n\nimpl PyClassDict for PyClassDictSlot {\n    const INIT: Self = Self(std::ptr::null_mut());\n    #[inline]\n    fn clear_dict(&mut self, _py: Python<'_>) {\n        if !self.0.is_null() {\n            unsafe { ffi::PyDict_Clear(self.0) }\n        }\n    }\n}\n\n/// Actual weakref field, which holds the pointer to `__weakref__`.\n///\n/// `#[pyclass(weakref)]` automatically adds this.\n#[repr(transparent)]\npub struct PyClassWeakRefSlot(*mut ffi::PyObject);\n\nimpl PyClassWeakRef for PyClassWeakRefSlot {\n    const INIT: Self = Self(std::ptr::null_mut());\n    #[inline]\n    unsafe fn clear_weakrefs(&mut self, obj: *mut ffi::PyObject, _py: Python<'_>) {\n        if !self.0.is_null() {\n            unsafe { ffi::PyObject_ClearWeakRefs(obj) }\n        }\n    }\n}\n\n/// This type is used as a \"dummy\" type on which dtolnay specializations are\n/// applied to apply implementations from `#[pymethods]`\npub struct PyClassImplCollector<T>(PhantomData<T>);\n\nimpl<T> PyClassImplCollector<T> {\n    pub fn new() -> Self {\n        Self(PhantomData)\n    }\n}\n\nimpl<T> Default for PyClassImplCollector<T> {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\nimpl<T> Clone for PyClassImplCollector<T> {\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<T> Copy for PyClassImplCollector<T> {}\n\npub struct PyClassItems {\n    pub methods: &'static [PyMethodDefType],\n    pub slots: &'static [ffi::PyType_Slot],\n}\n\n// Allow PyClassItems in statics\nunsafe impl Sync for PyClassItems {}\n\n/// Implements the underlying functionality of `#[pyclass]`, assembled by various proc macros.\n///\n/// Users are discouraged from implementing this trait manually; it is a PyO3 implementation detail\n/// and may be changed at any time.\npub trait PyClassImpl: Sized + 'static {\n    /// Module which the class will be associated with.\n    ///\n    /// (Currently defaults to `builtins` if unset, this will likely be improved in the future, it\n    /// may also be removed when passing module objects in class init.)\n    const MODULE: Option<&'static str>;\n\n    /// #[pyclass(subclass)]\n    const IS_BASETYPE: bool = false;\n\n    /// #[pyclass(extends=...)]\n    const IS_SUBCLASS: bool = false;\n\n    /// #[pyclass(mapping)]\n    const IS_MAPPING: bool = false;\n\n    /// #[pyclass(sequence)]\n    const IS_SEQUENCE: bool = false;\n\n    /// #[pyclass(immutable_type)]\n    const IS_IMMUTABLE_TYPE: bool = false;\n\n    /// Description of how this class is laid out in memory\n    type Layout: PyClassObjectLayout<Self>;\n\n    /// Base class\n    type BaseType: PyTypeInfo + PyClassBaseType;\n\n    /// Immutable or mutable\n    type PyClassMutability: PyClassMutability + GetBorrowChecker<Self>;\n\n    /// Specify this class has `#[pyclass(dict)]` or not.\n    type Dict: PyClassDict;\n\n    /// Specify this class has `#[pyclass(weakref)]` or not.\n    type WeakRef: PyClassWeakRef;\n\n    /// The closest native ancestor. This is `PyAny` by default, and when you declare\n    /// `#[pyclass(extends=PyDict)]`, it's `PyDict`.\n    type BaseNativeType: PyTypeInfo;\n\n    /// This handles following two situations:\n    /// 1. In case `T` is `Send`, stub `ThreadChecker` is used and does nothing.\n    ///    This implementation is used by default. Compile fails if `T: !Send`.\n    /// 2. In case `T` is `!Send`, `ThreadChecker` panics when `T` is accessed by another thread.\n    ///    This implementation is used when `#[pyclass(unsendable)]` is given.\n    ///    Panicking makes it safe to expose `T: !Send` to the Python interpreter, where all objects\n    ///    can be accessed by multiple threads by `threading` module.\n    type ThreadChecker: PyClassThreadChecker<Self>;\n\n    #[cfg(feature = \"multiple-pymethods\")]\n    type Inventory: PyClassInventory;\n\n    /// Docstring for the class provided on the struct or enum.\n    ///\n    /// This is exposed for `PyClassDocGenerator` to use as a docstring piece.\n    const RAW_DOC: &'static CStr;\n\n    /// Fully rendered class doc, including the `text_signature` if a constructor is defined.\n    ///\n    /// This is constructed at compile-time with const specialization via the proc macros with help\n    /// from the PyClassDocGenerator` type.\n    const DOC: &'static CStr;\n\n    fn items_iter() -> PyClassItemsIter;\n\n    /// Used to provide the __dictoffset__ slot\n    /// (equivalent to [tp_dictoffset](https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_dictoffset))\n    #[inline]\n    fn dict_offset() -> Option<PyObjectOffset> {\n        None\n    }\n\n    /// Used to provide the __weaklistoffset__ slot\n    /// (equivalent to [tp_weaklistoffset](https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_weaklistoffset)\n    #[inline]\n    fn weaklist_offset() -> Option<PyObjectOffset> {\n        None\n    }\n\n    fn lazy_type_object() -> &'static LazyTypeObject<Self>;\n}\n\n/// Iterator used to process all class items during type instantiation.\npub struct PyClassItemsIter {\n    /// Iteration state\n    idx: usize,\n    /// Items from the `#[pyclass]` macro\n    pyclass_items: &'static PyClassItems,\n    /// Items from the `#[pymethods]` macro\n    #[cfg(not(feature = \"multiple-pymethods\"))]\n    pymethods_items: &'static PyClassItems,\n    /// Items from the `#[pymethods]` macro with inventory\n    #[cfg(feature = \"multiple-pymethods\")]\n    pymethods_items: Box<dyn Iterator<Item = &'static PyClassItems>>,\n}\n\nimpl PyClassItemsIter {\n    pub fn new(\n        pyclass_items: &'static PyClassItems,\n        #[cfg(not(feature = \"multiple-pymethods\"))] pymethods_items: &'static PyClassItems,\n        #[cfg(feature = \"multiple-pymethods\")] pymethods_items: Box<\n            dyn Iterator<Item = &'static PyClassItems>,\n        >,\n    ) -> Self {\n        Self {\n            idx: 0,\n            pyclass_items,\n            pymethods_items,\n        }\n    }\n}\n\nimpl Iterator for PyClassItemsIter {\n    type Item = &'static PyClassItems;\n\n    #[cfg(not(feature = \"multiple-pymethods\"))]\n    fn next(&mut self) -> Option<Self::Item> {\n        match self.idx {\n            0 => {\n                self.idx += 1;\n                Some(self.pyclass_items)\n            }\n            1 => {\n                self.idx += 1;\n                Some(self.pymethods_items)\n            }\n            // Termination clause\n            _ => None,\n        }\n    }\n\n    #[cfg(feature = \"multiple-pymethods\")]\n    fn next(&mut self) -> Option<Self::Item> {\n        match self.idx {\n            0 => {\n                self.idx += 1;\n                Some(self.pyclass_items)\n            }\n            // Termination clause\n            _ => self.pymethods_items.next(),\n        }\n    }\n}\n\n// Traits describing known special methods.\n\nmacro_rules! slot_fragment_trait {\n    ($trait_name:ident, $($default_method:tt)*) => {\n        #[allow(non_camel_case_types, reason = \"to match Python dunder names\")]\n        pub trait $trait_name<T>: Sized {\n            $($default_method)*\n        }\n\n        impl<T> $trait_name<T> for &'_ PyClassImplCollector<T> {}\n    }\n}\n\nslot_fragment_trait! {\n    PyClass__getattribute__SlotFragment,\n\n    /// # Safety: _slf and _attr must be valid non-null Python objects\n    #[inline]\n    unsafe fn __getattribute__(\n        self,\n        py: Python<'_>,\n        slf: *mut ffi::PyObject,\n        attr: *mut ffi::PyObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        let res = unsafe { ffi::PyObject_GenericGetAttr(slf, attr) };\n        if res.is_null() {\n            Err(PyErr::fetch(py))\n        } else {\n            Ok(res)\n        }\n    }\n}\n\nslot_fragment_trait! {\n    PyClass__getattr__SlotFragment,\n\n    /// # Safety: _slf and _attr must be valid non-null Python objects\n    #[inline]\n    unsafe fn __getattr__(\n        self,\n        py: Python<'_>,\n        _slf: *mut ffi::PyObject,\n        attr: *mut ffi::PyObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        Err(PyErr::new::<PyAttributeError, _>(\n            // SAFETY: caller has upheld the safety contract\n            (unsafe { attr.assume_borrowed_unchecked(py) }.to_owned().unbind(),)\n        ))\n    }\n}\n\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! generate_pyclass_getattro_slot {\n    ($cls:ty) => {{\n        unsafe fn slot_impl(\n            py: $crate::Python<'_>,\n            _slf: *mut $crate::ffi::PyObject,\n            attr: *mut $crate::ffi::PyObject,\n        ) -> $crate::PyResult<*mut $crate::ffi::PyObject> {\n            use ::std::result::Result::*;\n            use $crate::impl_::pyclass::*;\n            let collector = PyClassImplCollector::<$cls>::new();\n\n            // Strategy:\n            // - Try __getattribute__ first. Its default is PyObject_GenericGetAttr.\n            // - If it returns a result, use it.\n            // - If it fails with AttributeError, try __getattr__.\n            // - If it fails otherwise, reraise.\n            match unsafe { collector.__getattribute__(py, _slf, attr) } {\n                Ok(obj) => Ok(obj),\n                Err(e) if e.is_instance_of::<$crate::exceptions::PyAttributeError>(py) => unsafe {\n                    collector.__getattr__(py, _slf, attr)\n                },\n                Err(e) => Err(e),\n            }\n        }\n\n        $crate::ffi::PyType_Slot {\n            slot: $crate::ffi::Py_tp_getattro,\n            pfunc: $crate::impl_::trampoline::get_trampoline_function!(getattrofunc, slot_impl)\n                as $crate::ffi::getattrofunc as _,\n        }\n    }};\n}\n\npub use generate_pyclass_getattro_slot;\n\n/// Macro which expands to three items\n/// - Trait for a __setitem__ dunder\n/// - Trait for the corresponding __delitem__ dunder\n/// - A macro which will use dtolnay specialisation to generate the shared slot for the two dunders\nmacro_rules! define_pyclass_setattr_slot {\n    (\n        $set_trait:ident,\n        $del_trait:ident,\n        $set:ident,\n        $del:ident,\n        $set_error:expr,\n        $del_error:expr,\n        $generate_macro:ident,\n        $slot:ident,\n        $func_ty:ident,\n    ) => {\n        slot_fragment_trait! {\n            $set_trait,\n\n            /// # Safety: _slf and _attr must be valid non-null Python objects\n            #[inline]\n            unsafe fn $set(\n                self,\n                _py: Python<'_>,\n                _slf: *mut ffi::PyObject,\n                _attr: *mut ffi::PyObject,\n                _value: NonNull<ffi::PyObject>,\n            ) -> PyResult<()> {\n                $set_error\n            }\n        }\n\n        slot_fragment_trait! {\n            $del_trait,\n\n            /// # Safety: _slf and _attr must be valid non-null Python objects\n            #[inline]\n            unsafe fn $del(\n                self,\n                _py: Python<'_>,\n                _slf: *mut ffi::PyObject,\n                _attr: *mut ffi::PyObject,\n            ) -> PyResult<()> {\n                $del_error\n            }\n        }\n\n        #[doc(hidden)]\n        #[macro_export]\n        macro_rules! $generate_macro {\n            ($cls:ty) => {{\n                unsafe fn slot_impl(\n                    py: $crate::Python<'_>,\n                    _slf: *mut $crate::ffi::PyObject,\n                    attr: *mut $crate::ffi::PyObject,\n                    value: *mut $crate::ffi::PyObject,\n                ) -> $crate::PyResult<::std::ffi::c_int> {\n                    use ::std::option::Option::*;\n                    use $crate::impl_::callback::IntoPyCallbackOutput;\n                    use $crate::impl_::pyclass::*;\n                    let collector = PyClassImplCollector::<$cls>::new();\n                    if let Some(value) = ::std::ptr::NonNull::new(value) {\n                        unsafe { collector.$set(py, _slf, attr, value).convert(py) }\n                    } else {\n                        unsafe { collector.$del(py, _slf, attr).convert(py) }\n                    }\n                }\n\n                $crate::ffi::PyType_Slot {\n                    slot: $crate::ffi::$slot,\n                    pfunc: $crate::impl_::trampoline::get_trampoline_function!(\n                        setattrofunc,\n                        slot_impl\n                    ) as $crate::ffi::$func_ty as _,\n                }\n            }};\n        }\n        pub use $generate_macro;\n    };\n}\n\ndefine_pyclass_setattr_slot! {\n    PyClass__setattr__SlotFragment,\n    PyClass__delattr__SlotFragment,\n    __setattr__,\n    __delattr__,\n    Err(PyAttributeError::new_err(\"can't set attribute\")),\n    Err(PyAttributeError::new_err(\"can't delete attribute\")),\n    generate_pyclass_setattr_slot,\n    Py_tp_setattro,\n    setattrofunc,\n}\n\ndefine_pyclass_setattr_slot! {\n    PyClass__set__SlotFragment,\n    PyClass__delete__SlotFragment,\n    __set__,\n    __delete__,\n    Err(PyNotImplementedError::new_err(\"can't set descriptor\")),\n    Err(PyNotImplementedError::new_err(\"can't delete descriptor\")),\n    generate_pyclass_setdescr_slot,\n    Py_tp_descr_set,\n    descrsetfunc,\n}\n\ndefine_pyclass_setattr_slot! {\n    PyClass__setitem__SlotFragment,\n    PyClass__delitem__SlotFragment,\n    __setitem__,\n    __delitem__,\n    Err(PyNotImplementedError::new_err(\"can't set item\")),\n    Err(PyNotImplementedError::new_err(\"can't delete item\")),\n    generate_pyclass_setitem_slot,\n    Py_mp_ass_subscript,\n    objobjargproc,\n}\n\n/// Macro which expands to three items\n/// - Trait for a lhs dunder e.g. __add__\n/// - Trait for the corresponding rhs e.g. __radd__\n/// - A macro which will use dtolnay specialisation to generate the shared slot for the two dunders\nmacro_rules! define_pyclass_binary_operator_slot {\n    (\n        $lhs_trait:ident,\n        $rhs_trait:ident,\n        $lhs:ident,\n        $rhs:ident,\n        $generate_macro:ident,\n        $slot:ident,\n    ) => {\n        slot_fragment_trait! {\n            $lhs_trait,\n\n            /// # Safety: _slf and _other must be valid non-null Python objects\n            #[inline]\n            unsafe fn $lhs(\n                self,\n                py: Python<'_>,\n                _slf: *mut ffi::PyObject,\n                _other: *mut ffi::PyObject,\n            ) -> PyResult<*mut ffi::PyObject> {\n                Ok(py.NotImplemented().into_ptr())\n            }\n        }\n\n        slot_fragment_trait! {\n            $rhs_trait,\n\n            /// # Safety: _slf and _other must be valid non-null Python objects\n            #[inline]\n            unsafe fn $rhs(\n                self,\n                py: Python<'_>,\n                _slf: *mut ffi::PyObject,\n                _other: *mut ffi::PyObject,\n            ) -> PyResult<*mut ffi::PyObject> {\n                Ok(py.NotImplemented().into_ptr())\n            }\n        }\n\n        #[doc(hidden)]\n        #[macro_export]\n        macro_rules! $generate_macro {\n            ($cls:ty) => {{\n                unsafe fn slot_impl(\n                    py: $crate::Python<'_>,\n                    _slf: *mut $crate::ffi::PyObject,\n                    _other: *mut $crate::ffi::PyObject,\n                ) -> $crate::PyResult<*mut $crate::ffi::PyObject> {\n                    use $crate::impl_::pyclass::*;\n                    let collector = PyClassImplCollector::<$cls>::new();\n                    let lhs_result = unsafe { collector.$lhs(py, _slf, _other) }?;\n                    if lhs_result == unsafe { $crate::ffi::Py_NotImplemented() } {\n                        unsafe { $crate::ffi::Py_DECREF(lhs_result) };\n                        unsafe { collector.$rhs(py, _other, _slf) }\n                    } else {\n                        ::std::result::Result::Ok(lhs_result)\n                    }\n                }\n\n                $crate::ffi::PyType_Slot {\n                    slot: $crate::ffi::$slot,\n                    pfunc: $crate::impl_::trampoline::get_trampoline_function!(\n                        binaryfunc, slot_impl\n                    ) as $crate::ffi::binaryfunc as _,\n                }\n            }};\n        }\n        pub use $generate_macro;\n    };\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__add__SlotFragment,\n    PyClass__radd__SlotFragment,\n    __add__,\n    __radd__,\n    generate_pyclass_add_slot,\n    Py_nb_add,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__sub__SlotFragment,\n    PyClass__rsub__SlotFragment,\n    __sub__,\n    __rsub__,\n    generate_pyclass_sub_slot,\n    Py_nb_subtract,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__mul__SlotFragment,\n    PyClass__rmul__SlotFragment,\n    __mul__,\n    __rmul__,\n    generate_pyclass_mul_slot,\n    Py_nb_multiply,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__mod__SlotFragment,\n    PyClass__rmod__SlotFragment,\n    __mod__,\n    __rmod__,\n    generate_pyclass_mod_slot,\n    Py_nb_remainder,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__divmod__SlotFragment,\n    PyClass__rdivmod__SlotFragment,\n    __divmod__,\n    __rdivmod__,\n    generate_pyclass_divmod_slot,\n    Py_nb_divmod,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__lshift__SlotFragment,\n    PyClass__rlshift__SlotFragment,\n    __lshift__,\n    __rlshift__,\n    generate_pyclass_lshift_slot,\n    Py_nb_lshift,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__rshift__SlotFragment,\n    PyClass__rrshift__SlotFragment,\n    __rshift__,\n    __rrshift__,\n    generate_pyclass_rshift_slot,\n    Py_nb_rshift,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__and__SlotFragment,\n    PyClass__rand__SlotFragment,\n    __and__,\n    __rand__,\n    generate_pyclass_and_slot,\n    Py_nb_and,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__or__SlotFragment,\n    PyClass__ror__SlotFragment,\n    __or__,\n    __ror__,\n    generate_pyclass_or_slot,\n    Py_nb_or,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__xor__SlotFragment,\n    PyClass__rxor__SlotFragment,\n    __xor__,\n    __rxor__,\n    generate_pyclass_xor_slot,\n    Py_nb_xor,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__matmul__SlotFragment,\n    PyClass__rmatmul__SlotFragment,\n    __matmul__,\n    __rmatmul__,\n    generate_pyclass_matmul_slot,\n    Py_nb_matrix_multiply,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__truediv__SlotFragment,\n    PyClass__rtruediv__SlotFragment,\n    __truediv__,\n    __rtruediv__,\n    generate_pyclass_truediv_slot,\n    Py_nb_true_divide,\n}\n\ndefine_pyclass_binary_operator_slot! {\n    PyClass__floordiv__SlotFragment,\n    PyClass__rfloordiv__SlotFragment,\n    __floordiv__,\n    __rfloordiv__,\n    generate_pyclass_floordiv_slot,\n    Py_nb_floor_divide,\n}\n\nslot_fragment_trait! {\n    PyClass__pow__SlotFragment,\n\n    /// # Safety: _slf and _other must be valid non-null Python objects\n    #[inline]\n    unsafe fn __pow__(\n        self,\n        py: Python<'_>,\n        _slf: *mut ffi::PyObject,\n        _other: *mut ffi::PyObject,\n        _mod: *mut ffi::PyObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        Ok(py.NotImplemented().into_ptr())\n    }\n}\n\nslot_fragment_trait! {\n    PyClass__rpow__SlotFragment,\n\n    /// # Safety: _slf and _other must be valid non-null Python objects\n    #[inline]\n    unsafe fn __rpow__(\n        self,\n        py: Python<'_>,\n        _slf: *mut ffi::PyObject,\n        _other: *mut ffi::PyObject,\n        _mod: *mut ffi::PyObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        Ok(py.NotImplemented().into_ptr())\n    }\n}\n\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! generate_pyclass_pow_slot {\n    ($cls:ty) => {{\n        fn slot_impl(\n            py: $crate::Python<'_>,\n            _slf: *mut $crate::ffi::PyObject,\n            _other: *mut $crate::ffi::PyObject,\n            _mod: *mut $crate::ffi::PyObject,\n        ) -> $crate::PyResult<*mut $crate::ffi::PyObject> {\n            use $crate::impl_::pyclass::*;\n            let collector = PyClassImplCollector::<$cls>::new();\n            let lhs_result = unsafe { collector.__pow__(py, _slf, _other, _mod) }?;\n            if lhs_result == unsafe { $crate::ffi::Py_NotImplemented() } {\n                unsafe { $crate::ffi::Py_DECREF(lhs_result) };\n                unsafe { collector.__rpow__(py, _other, _slf, _mod) }\n            } else {\n                ::std::result::Result::Ok(lhs_result)\n            }\n        }\n\n        $crate::ffi::PyType_Slot {\n            slot: $crate::ffi::Py_nb_power,\n            pfunc: $crate::impl_::trampoline::get_trampoline_function!(ternaryfunc, slot_impl)\n                as $crate::ffi::ternaryfunc as _,\n        }\n    }};\n}\npub use generate_pyclass_pow_slot;\n\nslot_fragment_trait! {\n    PyClass__lt__SlotFragment,\n\n    /// # Safety: _slf and _other must be valid non-null Python objects\n    #[inline]\n    unsafe fn __lt__(\n        self,\n        py: Python<'_>,\n        _slf: *mut ffi::PyObject,\n        _other: *mut ffi::PyObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        Ok(py.NotImplemented().into_ptr())\n    }\n}\n\nslot_fragment_trait! {\n    PyClass__le__SlotFragment,\n\n    /// # Safety: _slf and _other must be valid non-null Python objects\n    #[inline]\n    unsafe fn __le__(\n        self,\n        py: Python<'_>,\n        _slf: *mut ffi::PyObject,\n        _other: *mut ffi::PyObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        Ok(py.NotImplemented().into_ptr())\n    }\n}\n\nslot_fragment_trait! {\n    PyClass__eq__SlotFragment,\n\n    /// # Safety: _slf and _other must be valid non-null Python objects\n    #[inline]\n    unsafe fn __eq__(\n        self,\n        py: Python<'_>,\n        _slf: *mut ffi::PyObject,\n        _other: *mut ffi::PyObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        Ok(py.NotImplemented().into_ptr())\n    }\n}\n\nslot_fragment_trait! {\n    PyClass__ne__SlotFragment,\n\n    /// # Safety: _slf and _other must be valid non-null Python objects\n    #[inline]\n    unsafe fn __ne__(\n        self,\n        py: Python<'_>,\n        slf: *mut ffi::PyObject,\n        other: *mut ffi::PyObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        // By default `__ne__` will try `__eq__` and invert the result\n        let slf = unsafe { Borrowed::from_ptr(py, slf)};\n        let other = unsafe { Borrowed::from_ptr(py, other)};\n        slf.eq(other).map(|is_eq| PyBool::new(py, !is_eq).to_owned().into_ptr())\n    }\n}\n\nslot_fragment_trait! {\n    PyClass__gt__SlotFragment,\n\n    /// # Safety: _slf and _other must be valid non-null Python objects\n    #[inline]\n    unsafe fn __gt__(\n        self,\n        py: Python<'_>,\n        _slf: *mut ffi::PyObject,\n        _other: *mut ffi::PyObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        Ok(py.NotImplemented().into_ptr())\n    }\n}\n\nslot_fragment_trait! {\n    PyClass__ge__SlotFragment,\n\n    /// # Safety: _slf and _other must be valid non-null Python objects\n    #[inline]\n    unsafe fn __ge__(\n        self,\n        py: Python<'_>,\n        _slf: *mut ffi::PyObject,\n        _other: *mut ffi::PyObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        Ok(py.NotImplemented().into_ptr())\n    }\n}\n\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! generate_pyclass_richcompare_slot {\n    ($cls:ty) => {{\n        #[allow(unknown_lints, non_local_definitions)]\n        impl $cls {\n            #[expect(non_snake_case)]\n            unsafe fn __pymethod___richcmp____(\n                py: $crate::Python<'_>,\n                slf: *mut $crate::ffi::PyObject,\n                other: *mut $crate::ffi::PyObject,\n                op: ::std::ffi::c_int,\n            ) -> $crate::PyResult<*mut $crate::ffi::PyObject> {\n                use $crate::class::basic::CompareOp;\n                use $crate::impl_::pyclass::*;\n                let collector = PyClassImplCollector::<$cls>::new();\n                match CompareOp::from_raw(op).expect(\"invalid compareop\") {\n                    CompareOp::Lt => unsafe { collector.__lt__(py, slf, other) },\n                    CompareOp::Le => unsafe { collector.__le__(py, slf, other) },\n                    CompareOp::Eq => unsafe { collector.__eq__(py, slf, other) },\n                    CompareOp::Ne => unsafe { collector.__ne__(py, slf, other) },\n                    CompareOp::Gt => unsafe { collector.__gt__(py, slf, other) },\n                    CompareOp::Ge => unsafe { collector.__ge__(py, slf, other) },\n                }\n            }\n        }\n        $crate::ffi::PyType_Slot {\n            slot: $crate::ffi::Py_tp_richcompare,\n            pfunc: {\n                type Cls = $cls; // `get_trampoline_function` doesn't accept $cls directly\n                $crate::impl_::trampoline::get_trampoline_function!(\n                    richcmpfunc,\n                    Cls::__pymethod___richcmp____\n                ) as $crate::ffi::richcmpfunc as _\n            },\n        }\n    }};\n}\npub use generate_pyclass_richcompare_slot;\n\n/// Implements a freelist.\n///\n/// Do not implement this trait manually. Instead, use `#[pyclass(freelist = N)]`\n/// on a Rust struct to implement it.\npub trait PyClassWithFreeList: PyClass {\n    fn get_free_list(py: Python<'_>) -> &'static Mutex<PyObjectFreeList>;\n}\n\n/// Implementation of tp_alloc for `freelist` classes.\n///\n/// # Safety\n/// - `subtype` must be a valid pointer to the type object of T or a subclass.\n/// - The calling thread must be attached to the interpreter\npub unsafe extern \"C\" fn alloc_with_freelist<T: PyClassWithFreeList>(\n    subtype: *mut ffi::PyTypeObject,\n    nitems: ffi::Py_ssize_t,\n) -> *mut ffi::PyObject {\n    let py = unsafe { Python::assume_attached() };\n\n    #[cfg(not(Py_3_8))]\n    unsafe {\n        bpo_35810_workaround(py, subtype)\n    };\n\n    let self_type = T::type_object_raw(py);\n    // If this type is a variable type or the subtype is not equal to this type, we cannot use the\n    // freelist\n    if nitems == 0 && ptr::eq(subtype, self_type) {\n        let mut free_list = T::get_free_list(py).lock().unwrap();\n        if let Some(obj) = free_list.pop() {\n            drop(free_list);\n            unsafe { ffi::PyObject_Init(obj, subtype) };\n            return obj as _;\n        }\n    }\n\n    unsafe { ffi::PyType_GenericAlloc(subtype, nitems) }\n}\n\n/// Implementation of tp_free for `freelist` classes.\n///\n/// # Safety\n/// - `obj` must be a valid pointer to an instance of T (not a subclass).\n/// - The calling thread must be attached to the interpreter\npub unsafe extern \"C\" fn free_with_freelist<T: PyClassWithFreeList>(obj: *mut c_void) {\n    let obj = obj as *mut ffi::PyObject;\n    unsafe {\n        debug_assert_eq!(\n            T::type_object_raw(Python::assume_attached()),\n            ffi::Py_TYPE(obj)\n        );\n        let mut free_list = T::get_free_list(Python::assume_attached()).lock().unwrap();\n        if let Some(obj) = free_list.insert(obj) {\n            drop(free_list);\n            let ty = ffi::Py_TYPE(obj);\n\n            // Deduce appropriate inverse of PyType_GenericAlloc\n            let free = if ffi::PyType_IS_GC(ty) != 0 {\n                ffi::PyObject_GC_Del\n            } else {\n                ffi::PyObject_Free\n            };\n            free(obj as *mut c_void);\n\n            #[cfg(Py_3_8)]\n            if ffi::PyType_HasFeature(ty, ffi::Py_TPFLAGS_HEAPTYPE) != 0 {\n                ffi::Py_DECREF(ty as *mut ffi::PyObject);\n            }\n        }\n    }\n}\n\n/// Workaround for Python issue 35810; no longer necessary in Python 3.8\n#[inline]\n#[cfg(not(Py_3_8))]\nunsafe fn bpo_35810_workaround(py: Python<'_>, ty: *mut ffi::PyTypeObject) {\n    #[cfg(Py_LIMITED_API)]\n    {\n        // Must check version at runtime for abi3 wheels - they could run against a higher version\n        // than the build config suggests.\n        use crate::sync::PyOnceLock;\n        static IS_PYTHON_3_8: PyOnceLock<bool> = PyOnceLock::new();\n\n        if *IS_PYTHON_3_8.get_or_init(py, || py.version_info() >= (3, 8)) {\n            // No fix needed - the wheel is running on a sufficiently new interpreter.\n            return;\n        }\n    }\n    #[cfg(not(Py_LIMITED_API))]\n    {\n        // suppress unused variable warning\n        let _ = py;\n    }\n\n    unsafe { ffi::Py_INCREF(ty as *mut ffi::PyObject) };\n}\n\n/// Method storage for `#[pyclass]`.\n///\n/// Implementation detail. Only to be used through our proc macro code.\n/// Allows arbitrary `#[pymethod]` blocks to submit their methods,\n/// which are eventually collected by `#[pyclass]`.\n#[cfg(feature = \"multiple-pymethods\")]\npub trait PyClassInventory: inventory::Collect {\n    /// Returns the items for a single `#[pymethods] impl` block\n    fn items(&'static self) -> &'static PyClassItems;\n}\n\n// Items from #[pymethods] if not using inventory.\n#[cfg(not(feature = \"multiple-pymethods\"))]\npub trait PyMethods<T> {\n    fn py_methods(self) -> &'static PyClassItems;\n}\n\n#[cfg(not(feature = \"multiple-pymethods\"))]\nimpl<T> PyMethods<T> for &'_ PyClassImplCollector<T> {\n    fn py_methods(self) -> &'static PyClassItems {\n        &PyClassItems {\n            methods: &[],\n            slots: &[],\n        }\n    }\n}\n\n// Thread checkers\n\n#[doc(hidden)]\npub trait PyClassThreadChecker<T>: Sized + sealed::Sealed {\n    fn ensure(&self);\n    fn check(&self) -> bool;\n    fn can_drop(&self, py: Python<'_>) -> bool;\n    fn new() -> Self;\n}\n\n/// Default thread checker for `#[pyclass]`.\n#[doc(hidden)]\npub struct NoopThreadChecker;\n\nimpl<T> PyClassThreadChecker<T> for NoopThreadChecker {\n    fn ensure(&self) {}\n    fn check(&self) -> bool {\n        true\n    }\n    fn can_drop(&self, _py: Python<'_>) -> bool {\n        true\n    }\n    #[inline]\n    fn new() -> Self {\n        NoopThreadChecker\n    }\n}\n\n/// Thread checker for `#[pyclass(unsendable)]` types.\n/// Panics when the value is accessed by another thread.\n#[doc(hidden)]\npub struct ThreadCheckerImpl(thread::ThreadId);\n\nimpl ThreadCheckerImpl {\n    fn ensure(&self, type_name: &'static str) {\n        assert_eq!(\n            thread::current().id(),\n            self.0,\n            \"{type_name} is unsendable, but sent to another thread\"\n        );\n    }\n\n    fn check(&self) -> bool {\n        thread::current().id() == self.0\n    }\n\n    fn can_drop(&self, py: Python<'_>, type_name: &'static str) -> bool {\n        if thread::current().id() != self.0 {\n            PyRuntimeError::new_err(format!(\n                \"{type_name} is unsendable, but is being dropped on another thread\"\n            ))\n            .write_unraisable(py, None);\n            return false;\n        }\n\n        true\n    }\n}\n\nimpl<T> PyClassThreadChecker<T> for ThreadCheckerImpl {\n    fn ensure(&self) {\n        self.ensure(std::any::type_name::<T>());\n    }\n    fn check(&self) -> bool {\n        self.check()\n    }\n    fn can_drop(&self, py: Python<'_>) -> bool {\n        self.can_drop(py, std::any::type_name::<T>())\n    }\n    fn new() -> Self {\n        ThreadCheckerImpl(thread::current().id())\n    }\n}\n\n/// Trait denoting that this class is suitable to be used as a base type for PyClass.\n#[cfg_attr(\n    Py_LIMITED_API,\n    diagnostic::on_unimplemented(\n        message = \"pyclass `{Self}` cannot be subclassed\",\n        label = \"required for `#[pyclass(extends={Self})]`\",\n        note = \"`{Self}` must have `#[pyclass(subclass)]` to be eligible for subclassing\",\n        note = \"with the `abi3` feature enabled, PyO3 does not support subclassing native types\",\n    )\n)]\n#[cfg_attr(\n    not(Py_LIMITED_API),\n    diagnostic::on_unimplemented(\n        message = \"pyclass `{Self}` cannot be subclassed\",\n        label = \"required for `#[pyclass(extends={Self})]`\",\n        note = \"`{Self}` must have `#[pyclass(subclass)]` to be eligible for subclassing\",\n    )\n)]\npub trait PyClassBaseType: Sized {\n    type LayoutAsBase: PyClassObjectBaseLayout<Self>;\n    type BaseNativeType;\n    type Initializer: PyObjectInit<Self>;\n    type PyClassMutability: PyClassMutability;\n    /// The type of object layout to use for ancestors or descendants of this type.\n    type Layout<T: PyClassImpl>;\n}\n\n/// Implementation of tp_dealloc for pyclasses without gc\npub(crate) unsafe extern \"C\" fn tp_dealloc<T: PyClass>(obj: *mut ffi::PyObject) {\n    unsafe { crate::impl_::trampoline::dealloc(obj, <T as PyClassImpl>::Layout::tp_dealloc) }\n}\n\n/// Implementation of tp_dealloc for pyclasses with gc\npub(crate) unsafe extern \"C\" fn tp_dealloc_with_gc<T: PyClass>(obj: *mut ffi::PyObject) {\n    #[cfg(not(PyPy))]\n    unsafe {\n        ffi::PyObject_GC_UnTrack(obj.cast());\n    }\n    unsafe { crate::impl_::trampoline::dealloc(obj, <T as PyClassImpl>::Layout::tp_dealloc) }\n}\n\npub(crate) unsafe extern \"C\" fn get_sequence_item_from_mapping(\n    obj: *mut ffi::PyObject,\n    index: ffi::Py_ssize_t,\n) -> *mut ffi::PyObject {\n    let index = unsafe { ffi::PyLong_FromSsize_t(index) };\n    if index.is_null() {\n        return std::ptr::null_mut();\n    }\n    let result = unsafe { ffi::PyObject_GetItem(obj, index) };\n    unsafe { ffi::Py_DECREF(index) };\n    result\n}\n\npub(crate) unsafe extern \"C\" fn assign_sequence_item_from_mapping(\n    obj: *mut ffi::PyObject,\n    index: ffi::Py_ssize_t,\n    value: *mut ffi::PyObject,\n) -> c_int {\n    unsafe {\n        let index = ffi::PyLong_FromSsize_t(index);\n        if index.is_null() {\n            return -1;\n        }\n        let result = if value.is_null() {\n            ffi::PyObject_DelItem(obj, index)\n        } else {\n            ffi::PyObject_SetItem(obj, index, value)\n        };\n        ffi::Py_DECREF(index);\n        result\n    }\n}\n\n/// Offset of a field within a PyObject in bytes.\n#[derive(Debug, Clone, Copy)]\npub enum PyObjectOffset {\n    /// An offset relative to the start of the object\n    Absolute(ffi::Py_ssize_t),\n    /// An offset relative to the start of the subclass-specific data.\n    /// Only allowed when basicsize is negative (which is only allowed for python >=3.12).\n    /// <https://docs.python.org/3.12/c-api/structures.html#c.Py_RELATIVE_OFFSET>\n    #[cfg(Py_3_12)]\n    Relative(ffi::Py_ssize_t),\n}\n\nimpl std::ops::Add<usize> for PyObjectOffset {\n    type Output = PyObjectOffset;\n\n    fn add(self, rhs: usize) -> Self::Output {\n        // Py_ssize_t may not be equal to isize on all platforms\n        #[allow(clippy::useless_conversion)]\n        let rhs: ffi::Py_ssize_t = rhs.try_into().expect(\"offset should fit in Py_ssize_t\");\n\n        match self {\n            PyObjectOffset::Absolute(offset) => PyObjectOffset::Absolute(offset + rhs),\n            #[cfg(Py_3_12)]\n            PyObjectOffset::Relative(offset) => PyObjectOffset::Relative(offset + rhs),\n        }\n    }\n}\n\n/// Type which uses specialization on impl blocks to determine how to read a field from a Rust pyclass\n/// as part of a `#[pyo3(get)]` annotation.\npub struct PyClassGetterGenerator<\n    // structural information about the field: class type, field type, offset of the field within\n    // the class struct\n    ClassT: PyClass,\n    FieldT,\n    const OFFSET: usize,\n    // additional metadata about the field which is used to switch between different implementations\n    // at compile time\n    const IS_PY_T: bool,\n    const IMPLEMENTS_INTOPYOBJECT_REF: bool,\n    const IMPLEMENTS_INTOPYOBJECT: bool,\n>(PhantomData<(ClassT, FieldT)>);\n\nimpl<\n        ClassT: PyClass,\n        FieldT,\n        const OFFSET: usize,\n        const IS_PY_T: bool,\n        const IMPLEMENTS_INTOPYOBJECT_REF: bool,\n        const IMPLEMENTS_INTOPYOBJECT: bool,\n    >\n    PyClassGetterGenerator<\n        ClassT,\n        FieldT,\n        OFFSET,\n        IS_PY_T,\n        IMPLEMENTS_INTOPYOBJECT_REF,\n        IMPLEMENTS_INTOPYOBJECT,\n    >\n{\n    /// Safety: constructing this type requires that there exists a value of type FieldT\n    /// at the calculated offset within the type ClassT.\n    pub const unsafe fn new() -> Self {\n        Self(PhantomData)\n    }\n}\n\nimpl<\n        ClassT: PyClass,\n        U: PyTypeCheck,\n        const OFFSET: usize,\n        const IMPLEMENTS_INTOPYOBJECT_REF: bool,\n        const IMPLEMENTS_INTOPYOBJECT: bool,\n    >\n    PyClassGetterGenerator<\n        ClassT,\n        Py<U>,\n        OFFSET,\n        true,\n        IMPLEMENTS_INTOPYOBJECT_REF,\n        IMPLEMENTS_INTOPYOBJECT,\n    >\n{\n    /// `Py<T>` fields have a potential optimization to use Python's \"struct members\" to read\n    /// the field directly from the struct, rather than using a getter function.\n    ///\n    /// This is the most efficient operation the Python interpreter could possibly do to\n    /// read a field, but it's only possible for us to allow this for frozen classes.\n    pub const fn generate(\n        &self,\n        name: &'static CStr,\n        doc: Option<&'static CStr>,\n    ) -> PyMethodDefType {\n        use crate::pyclass::boolean_struct::private::Boolean;\n        if ClassT::Frozen::VALUE {\n            let (offset, flags) = match <ClassT as PyClassImpl>::Layout::CONTENTS_OFFSET {\n                PyObjectOffset::Absolute(offset) => (offset, ffi::Py_READONLY),\n                #[cfg(Py_3_12)]\n                PyObjectOffset::Relative(offset) => {\n                    (offset, ffi::Py_READONLY | ffi::Py_RELATIVE_OFFSET)\n                }\n            };\n\n            PyMethodDefType::StructMember(ffi::PyMemberDef {\n                name: name.as_ptr(),\n                type_code: ffi::Py_T_OBJECT_EX,\n                offset: offset + OFFSET as ffi::Py_ssize_t,\n                flags,\n                doc: if let Some(doc) = doc {\n                    doc.as_ptr()\n                } else {\n                    ptr::null()\n                },\n            })\n        } else {\n            PyMethodDefType::Getter(PyGetterDef {\n                name,\n                meth: pyo3_get_value_into_pyobject_ref::<ClassT, Py<U>, OFFSET>,\n                doc,\n            })\n        }\n    }\n}\n\n/// Field is not `Py<T>`; try to use `IntoPyObject` for `&T` (preferred over `ToPyObject`) to avoid\n/// potentially expensive clones of containers like `Vec`\nimpl<ClassT, FieldT, const OFFSET: usize, const IMPLEMENTS_INTOPYOBJECT: bool>\n    PyClassGetterGenerator<ClassT, FieldT, OFFSET, false, true, IMPLEMENTS_INTOPYOBJECT>\nwhere\n    ClassT: PyClass,\n    for<'a, 'py> &'a FieldT: IntoPyObject<'py>,\n{\n    pub const fn generate(\n        &self,\n        name: &'static CStr,\n        doc: Option<&'static CStr>,\n    ) -> PyMethodDefType {\n        PyMethodDefType::Getter(PyGetterDef {\n            name,\n            meth: pyo3_get_value_into_pyobject_ref::<ClassT, FieldT, OFFSET>,\n            doc,\n        })\n    }\n}\n\n#[diagnostic::on_unimplemented(\n    message = \"`{Self}` cannot be converted to a Python object\",\n    label = \"required by `#[pyo3(get)]` to create a readable property from a field of type `{Self}`\",\n    note = \"implement `IntoPyObject` for `&{Self}` or `IntoPyObject + Clone` for `{Self}` to define the conversion\"\n)]\npub trait PyO3GetField<'py>: IntoPyObject<'py> + Clone {}\nimpl<'py, T> PyO3GetField<'py> for T where T: IntoPyObject<'py> + Clone {}\n\n/// Base case attempts to use IntoPyObject + Clone\nimpl<ClassT: PyClass, FieldT, const OFFSET: usize, const IMPLEMENTS_INTOPYOBJECT: bool>\n    PyClassGetterGenerator<ClassT, FieldT, OFFSET, false, false, IMPLEMENTS_INTOPYOBJECT>\n{\n    pub const fn generate(&self, name: &'static CStr, doc: Option<&'static CStr>) -> PyMethodDefType\n    // The bound goes here rather than on the block so that this impl is always available\n    // if no specialization is used instead\n    where\n        for<'py> FieldT: PyO3GetField<'py>,\n    {\n        PyMethodDefType::Getter(PyGetterDef {\n            name,\n            meth: pyo3_get_value_into_pyobject::<ClassT, FieldT, OFFSET>,\n            doc,\n        })\n    }\n}\n\n/// ensures `obj` is not mutably aliased\n#[inline]\nunsafe fn ensure_no_mutable_alias<'a, ClassT: PyClass>(\n    _py: Python<'_>,\n    obj: &'a NonNull<ffi::PyObject>,\n) -> Result<PyClassGuard<'a, ClassT>, PyBorrowError> {\n    unsafe { PyClassGuard::try_borrow(NonNull::from(obj).cast::<Py<ClassT>>().as_ref()) }\n}\n\n/// Gets a field value from a pyclass and produces a python value using `IntoPyObject` for `&FieldT`\n///\n/// # Safety\n/// - `obj` must be a valid pointer to an instance of `ClassT`\n/// - there must be a value of type `FieldT` at the calculated offset within `ClassT`\nunsafe fn pyo3_get_value_into_pyobject_ref<ClassT, FieldT, const OFFSET: usize>(\n    py: Python<'_>,\n    obj: NonNull<ffi::PyObject>,\n) -> PyResult<*mut ffi::PyObject>\nwhere\n    ClassT: PyClass,\n    for<'a, 'py> &'a FieldT: IntoPyObject<'py>,\n{\n    /// Inner function to convert the field value at the given offset\n    ///\n    /// # Safety\n    /// - mutable aliasing is prevented by the caller\n    /// - value of type `FieldT` must exist at the given offset within obj\n    unsafe fn inner<FieldT>(\n        py: Python<'_>,\n        obj: NonNull<()>,\n        offset: usize,\n    ) -> PyResult<*mut ffi::PyObject>\n    where\n        for<'a, 'py> &'a FieldT: IntoPyObject<'py>,\n    {\n        // SAFETY: caller upholds safety invariants\n        let value = unsafe { obj.byte_add(offset).cast::<FieldT>().as_ref() };\n        value.into_py_any(py).map(Py::into_ptr)\n    }\n\n    // SAFETY: `obj` is a valid pointer to `ClassT`\n    let _holder = unsafe { ensure_no_mutable_alias::<ClassT>(py, &obj)? };\n    let class_ptr = obj.cast::<<ClassT as PyClassImpl>::Layout>();\n    let class_obj = unsafe { class_ptr.as_ref() };\n\n    // SAFETY: _holder prevents mutable aliasing, caller upholds other safety invariants\n    unsafe { inner::<FieldT>(py, NonNull::from(class_obj.contents()).cast(), OFFSET) }\n}\n\n/// Gets a field value from a pyclass and produces a python value using `IntoPyObject` for `FieldT`,\n/// after cloning the value.\n///\n/// # Safety\n/// - `obj` must be a valid pointer to an instance of `ClassT`\n/// - there must be a value of type `FieldT` at the calculated offset within `ClassT`\nunsafe fn pyo3_get_value_into_pyobject<ClassT, FieldT, const OFFSET: usize>(\n    py: Python<'_>,\n    obj: NonNull<ffi::PyObject>,\n) -> PyResult<*mut ffi::PyObject>\nwhere\n    ClassT: PyClass,\n    for<'py> FieldT: IntoPyObject<'py> + Clone,\n{\n    /// Inner function to convert the field value at the given offset\n    ///\n    /// # Safety\n    /// - mutable aliasing is prevented by the caller\n    /// - value of type `FieldT` must exist at the given offset within obj\n    unsafe fn inner<FieldT>(\n        py: Python<'_>,\n        obj: NonNull<()>,\n        offset: usize,\n    ) -> PyResult<*mut ffi::PyObject>\n    where\n        for<'py> FieldT: IntoPyObject<'py> + Clone,\n    {\n        // SAFETY: caller upholds safety invariants\n        let value = unsafe { obj.byte_add(offset).cast::<FieldT>().as_ref() };\n        value.clone().into_py_any(py).map(Py::into_ptr)\n    }\n\n    // SAFETY: `obj` is a valid pointer to `ClassT`\n    let _holder = unsafe { ensure_no_mutable_alias::<ClassT>(py, &obj)? };\n    let class_ptr = obj.cast::<<ClassT as PyClassImpl>::Layout>();\n    let class_obj = unsafe { class_ptr.as_ref() };\n\n    // SAFETY: _holder prevents mutable aliasing, caller upholds other safety invariants\n    unsafe { inner::<FieldT>(py, NonNull::from(class_obj.contents()).cast(), OFFSET) }\n}\n\npub struct ConvertField<\n    const IMPLEMENTS_INTOPYOBJECT_REF: bool,\n    const IMPLEMENTS_INTOPYOBJECT: bool,\n>;\n\nimpl<const IMPLEMENTS_INTOPYOBJECT: bool> ConvertField<true, IMPLEMENTS_INTOPYOBJECT> {\n    #[inline]\n    pub fn convert_field<'a, 'py, T>(obj: &'a T, py: Python<'py>) -> PyResult<Py<PyAny>>\n    where\n        &'a T: IntoPyObject<'py>,\n    {\n        obj.into_py_any(py)\n    }\n}\n\nimpl<const IMPLEMENTS_INTOPYOBJECT: bool> ConvertField<false, IMPLEMENTS_INTOPYOBJECT> {\n    #[inline]\n    pub fn convert_field<'py, T>(obj: &T, py: Python<'py>) -> PyResult<Py<PyAny>>\n    where\n        T: PyO3GetField<'py>,\n    {\n        obj.clone().into_py_any(py)\n    }\n}\n\npub trait ExtractPyClassWithClone {}\n\n#[cfg(test)]\n#[cfg(feature = \"macros\")]\nmod tests {\n    use crate::pycell::impl_::PyClassObjectContents;\n\n    use super::*;\n    use std::mem::offset_of;\n\n    #[test]\n    fn get_py_for_frozen_class() {\n        #[crate::pyclass(crate = \"crate\", frozen)]\n        struct FrozenClass {\n            #[pyo3(get)]\n            value: Py<PyAny>,\n        }\n\n        let mut methods = Vec::new();\n        let mut slots = Vec::new();\n\n        for items in FrozenClass::items_iter() {\n            methods.extend_from_slice(items.methods);\n            slots.extend_from_slice(items.slots);\n        }\n\n        assert_eq!(methods.len(), 1);\n        assert!(slots.is_empty());\n\n        match methods.first() {\n            Some(PyMethodDefType::StructMember(member)) => {\n                assert_eq!(unsafe { CStr::from_ptr(member.name) }, c\"value\");\n                assert_eq!(member.type_code, ffi::Py_T_OBJECT_EX);\n                #[repr(C)]\n                struct ExpectedLayout {\n                    ob_base: ffi::PyObject,\n                    contents: PyClassObjectContents<FrozenClass>,\n                }\n                assert_eq!(\n                    member.offset,\n                    (offset_of!(ExpectedLayout, contents) + offset_of!(FrozenClass, value))\n                        as ffi::Py_ssize_t\n                );\n                assert_eq!(member.flags, ffi::Py_READONLY);\n            }\n            _ => panic!(\"Expected a StructMember\"),\n        }\n    }\n\n    #[test]\n    fn get_py_for_non_frozen_class() {\n        #[crate::pyclass(crate = \"crate\")]\n        struct FrozenClass {\n            #[pyo3(get)]\n            value: Py<PyAny>,\n        }\n\n        let mut methods = Vec::new();\n        let mut slots = Vec::new();\n\n        for items in FrozenClass::items_iter() {\n            methods.extend_from_slice(items.methods);\n            slots.extend_from_slice(items.slots);\n        }\n\n        assert_eq!(methods.len(), 1);\n        assert!(slots.is_empty());\n\n        match methods.first() {\n            Some(PyMethodDefType::Getter(getter)) => {\n                assert_eq!(getter.name, c\"value\");\n                assert_eq!(getter.doc, None);\n                // tests for the function pointer are in test_getter_setter.py\n            }\n            _ => panic!(\"Expected a StructMember\"),\n        }\n    }\n\n    #[test]\n    fn test_field_getter_generator() {\n        #[crate::pyclass(crate = \"crate\")]\n        struct MyClass {\n            my_field: i32,\n        }\n\n        const FIELD_OFFSET: usize = offset_of!(MyClass, my_field);\n\n        // generate for a non-py field using IntoPyObject for &i32\n        // SAFETY: offset is correct\n        let generator = unsafe {\n            PyClassGetterGenerator::<MyClass, i32, FIELD_OFFSET, false, true, false>::new()\n        };\n        let PyMethodDefType::Getter(def) = generator.generate(c\"my_field\", Some(c\"My field doc\"))\n        else {\n            panic!(\"Expected a Getter\");\n        };\n\n        assert_eq!(def.name, c\"my_field\");\n        assert_eq!(def.doc, Some(c\"My field doc\"));\n\n        #[cfg(fn_ptr_eq)]\n        {\n            use crate::impl_::pymethods::Getter;\n\n            assert!(std::ptr::fn_addr_eq(\n                def.meth,\n                pyo3_get_value_into_pyobject_ref::<MyClass, i32, FIELD_OFFSET> as Getter\n            ));\n        }\n\n        // generate for a field via `IntoPyObject` + `Clone`\n        // SAFETY: offset is correct\n        let generator = unsafe {\n            PyClassGetterGenerator::<MyClass, String, FIELD_OFFSET, false, false, true>::new()\n        };\n        let PyMethodDefType::Getter(def) = generator.generate(c\"my_field\", Some(c\"My field doc\"))\n        else {\n            panic!(\"Expected a Getter\");\n        };\n        assert_eq!(def.name, c\"my_field\");\n        assert_eq!(def.doc, Some(c\"My field doc\"));\n\n        #[cfg(fn_ptr_eq)]\n        {\n            use crate::impl_::pymethods::Getter;\n\n            assert!(std::ptr::fn_addr_eq(\n                def.meth,\n                pyo3_get_value_into_pyobject::<MyClass, String, FIELD_OFFSET> as Getter\n            ));\n        }\n    }\n\n    #[test]\n    fn test_field_getter_generator_py_field_frozen() {\n        #[crate::pyclass(crate = \"crate\", frozen)]\n        struct MyClass {\n            my_field: Py<PyAny>,\n        }\n\n        const FIELD_OFFSET: usize = offset_of!(MyClass, my_field);\n        // SAFETY: offset is correct\n        let generator = unsafe {\n            PyClassGetterGenerator::<MyClass, Py<PyAny>, FIELD_OFFSET, true, true, true>::new()\n        };\n        let PyMethodDefType::StructMember(def) =\n            generator.generate(c\"my_field\", Some(c\"My field doc\"))\n        else {\n            panic!(\"Expected a StructMember\");\n        };\n        // SAFETY: def.name originated from a CStr\n        assert_eq!(unsafe { CStr::from_ptr(def.name) }, c\"my_field\");\n        // SAFETY: def.doc originated from a CStr\n        assert_eq!(unsafe { CStr::from_ptr(def.doc) }, c\"My field doc\");\n        assert_eq!(def.type_code, ffi::Py_T_OBJECT_EX);\n        #[allow(irrefutable_let_patterns)]\n        let PyObjectOffset::Absolute(contents_offset) =\n            <MyClass as PyClassImpl>::Layout::CONTENTS_OFFSET\n        else {\n            panic!()\n        };\n        assert_eq!(\n            def.offset,\n            contents_offset + FIELD_OFFSET as ffi::Py_ssize_t\n        );\n        assert_eq!(def.flags, ffi::Py_READONLY);\n    }\n\n    #[test]\n    fn test_field_getter_generator_py_field_non_frozen() {\n        #[crate::pyclass(crate = \"crate\")]\n        struct MyClass {\n            my_field: Py<PyAny>,\n        }\n\n        const FIELD_OFFSET: usize = offset_of!(MyClass, my_field);\n        // SAFETY: offset is correct\n        let generator = unsafe {\n            PyClassGetterGenerator::<MyClass, Py<PyAny>, FIELD_OFFSET, true, true, true>::new()\n        };\n        let PyMethodDefType::Getter(def) = generator.generate(c\"my_field\", Some(c\"My field doc\"))\n        else {\n            panic!(\"Expected a Getter\");\n        };\n        assert_eq!(def.name, c\"my_field\");\n        assert_eq!(def.doc, Some(c\"My field doc\"));\n\n        #[cfg(fn_ptr_eq)]\n        {\n            use crate::impl_::pymethods::Getter;\n\n            assert!(std::ptr::fn_addr_eq(\n                def.meth,\n                pyo3_get_value_into_pyobject_ref::<MyClass, Py<PyAny>, FIELD_OFFSET> as Getter\n            ));\n        }\n    }\n}\n"
  },
  {
    "path": "src/impl_/pyclass_init.rs",
    "content": "//! Contains initialization utilities for `#[pyclass]`.\nuse crate::exceptions::PyTypeError;\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::impl_::pyclass::PyClassBaseType;\nuse crate::internal::get_slot::TP_NEW;\nuse crate::types::{PyTuple, PyType};\nuse crate::{ffi, PyClass, PyClassInitializer, PyErr, PyResult, Python};\nuse crate::{ffi::PyTypeObject, sealed::Sealed, type_object::PyTypeInfo};\nuse std::marker::PhantomData;\n\n/// Initializer for Python types.\n///\n/// This trait is intended to use internally for distinguishing `#[pyclass]` and\n/// Python native types.\npub trait PyObjectInit<T>: Sized + Sealed {\n    /// # Safety\n    /// - `subtype` must be a valid pointer to a type object of T or a subclass.\n    unsafe fn into_new_object(\n        self,\n        py: Python<'_>,\n        subtype: *mut PyTypeObject,\n    ) -> PyResult<*mut ffi::PyObject>;\n}\n\n/// Initializer for Python native types, like `PyDict`.\npub struct PyNativeTypeInitializer<T: PyTypeInfo>(pub PhantomData<T>);\n\nimpl<T: PyTypeInfo> PyObjectInit<T> for PyNativeTypeInitializer<T> {\n    unsafe fn into_new_object(\n        self,\n        py: Python<'_>,\n        subtype: *mut PyTypeObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        unsafe fn inner(\n            py: Python<'_>,\n            type_ptr: *mut PyTypeObject,\n            subtype: *mut PyTypeObject,\n        ) -> PyResult<*mut ffi::PyObject> {\n            let tp_new = unsafe {\n                type_ptr\n                    .cast::<ffi::PyObject>()\n                    .assume_borrowed_unchecked(py)\n                    .cast_unchecked::<PyType>()\n                    .get_slot(TP_NEW)\n                    .ok_or_else(|| PyTypeError::new_err(\"base type without tp_new\"))?\n            };\n\n            // TODO: make it possible to provide real arguments to the base tp_new\n            let obj = unsafe { tp_new(subtype, PyTuple::empty(py).as_ptr(), std::ptr::null_mut()) };\n            if obj.is_null() {\n                Err(PyErr::fetch(py))\n            } else {\n                Ok(obj)\n            }\n        }\n        unsafe { inner(py, T::type_object_raw(py), subtype) }\n    }\n}\n\npub trait PyClassInit<'py, const IS_PYCLASS: bool, const IS_INITIALIZER_TUPLE: bool> {\n    fn init(\n        self,\n        cls: crate::Borrowed<'_, 'py, crate::types::PyType>,\n    ) -> PyResult<crate::Bound<'py, crate::PyAny>>;\n}\n\nimpl<'py, T> PyClassInit<'py, false, false> for T\nwhere\n    T: crate::IntoPyObject<'py>,\n{\n    fn init(\n        self,\n        cls: crate::Borrowed<'_, 'py, crate::types::PyType>,\n    ) -> PyResult<crate::Bound<'py, crate::PyAny>> {\n        self.into_pyobject(cls.py())\n            .map(crate::BoundObject::into_any)\n            .map(crate::BoundObject::into_bound)\n            .map_err(Into::into)\n    }\n}\n\nimpl<'py, T> PyClassInit<'py, true, false> for T\nwhere\n    T: crate::PyClass,\n    T::BaseType:\n        super::pyclass::PyClassBaseType<Initializer = PyNativeTypeInitializer<T::BaseType>>,\n{\n    fn init(\n        self,\n        cls: crate::Borrowed<'_, 'py, crate::types::PyType>,\n    ) -> PyResult<crate::Bound<'py, crate::PyAny>> {\n        PyClassInitializer::from(self).init(cls)\n    }\n}\n\nimpl<'py, T, E, const IS_PYCLASS: bool, const IS_INITIALIZER_TUPLE: bool>\n    PyClassInit<'py, IS_PYCLASS, IS_INITIALIZER_TUPLE> for Result<T, E>\nwhere\n    T: PyClassInit<'py, IS_PYCLASS, IS_INITIALIZER_TUPLE>,\n    E: Into<PyErr>,\n{\n    fn init(\n        self,\n        cls: crate::Borrowed<'_, 'py, crate::types::PyType>,\n    ) -> PyResult<crate::Bound<'py, crate::PyAny>> {\n        self.map_err(Into::into)?.init(cls)\n    }\n}\n\nimpl<'py, T> PyClassInit<'py, false, false> for PyClassInitializer<T>\nwhere\n    T: PyClass,\n{\n    fn init(\n        self,\n        cls: crate::Borrowed<'_, 'py, crate::types::PyType>,\n    ) -> PyResult<crate::Bound<'py, crate::PyAny>> {\n        unsafe {\n            self.create_class_object_of_type(cls.py(), cls.as_ptr().cast())\n                .map(crate::Bound::into_any)\n        }\n    }\n}\n\nimpl<'py, S, B> PyClassInit<'py, false, true> for (S, B)\nwhere\n    S: PyClass<BaseType = B>,\n    B: PyClass + PyClassBaseType<Initializer = PyClassInitializer<B>>,\n    B::BaseType: PyClassBaseType<Initializer = PyNativeTypeInitializer<B::BaseType>>,\n{\n    fn init(\n        self,\n        cls: crate::Borrowed<'_, 'py, crate::types::PyType>,\n    ) -> PyResult<crate::Bound<'py, crate::PyAny>> {\n        let (sub, base) = self;\n        PyClassInitializer::from(base).add_subclass(sub).init(cls)\n    }\n}\n"
  },
  {
    "path": "src/impl_/pyfunction.rs",
    "content": "use std::cell::UnsafeCell;\n\nuse crate::{\n    ffi,\n    ffi_ptr_ext::FfiPtrExt,\n    py_result_ext::PyResultExt,\n    types::{PyCFunction, PyModule, PyModuleMethods},\n    Borrowed, Bound, PyResult, Python,\n};\n\npub use crate::impl_::pymethods::PyMethodDef;\n\n/// Wrapper around `ffi::PyMethodDef` suitable to use as a static variable for `#[pyfunction]` values.\n///\n/// The `UnsafeCell` is used because the Python interpreter consumes these as `*mut ffi::PyMethodDef`.\npub struct PyFunctionDef(UnsafeCell<ffi::PyMethodDef>);\n\n// Safety: contents are only ever used by the Python interpreter, which uses global statics in this way.\nunsafe impl Sync for PyFunctionDef {}\n\nimpl PyFunctionDef {\n    pub const fn new(def: ffi::PyMethodDef) -> Self {\n        Self(UnsafeCell::new(def))\n    }\n\n    pub const fn from_method_def(def: PyMethodDef) -> Self {\n        Self::new(def.into_raw())\n    }\n\n    pub(crate) fn create_py_c_function<'py>(\n        &'static self,\n        py: Python<'py>,\n        module: Option<&Bound<'py, PyModule>>,\n    ) -> PyResult<Bound<'py, PyCFunction>> {\n        // Safety: self is static\n        unsafe { create_py_c_function(py, self.0.get(), module) }\n    }\n}\n\n/// Trait to enable the use of `wrap_pyfunction` with both `Python` and `PyModule`,\n/// and also to infer the return type of either `&'py PyCFunction` or `Bound<'py, PyCFunction>`.\npub trait WrapPyFunctionArg<'py, T>: wrap_pyfunctionarg::Sealed {\n    fn wrap_pyfunction(self, function_def: &'static PyFunctionDef) -> PyResult<T>;\n}\n\n/// Seals `WrapPyFunctionArg` so that types outside PyO3 cannot implement it.\nmod wrap_pyfunctionarg {\n    use crate::{types::PyModule, Borrowed, Bound, Python};\n\n    pub trait Sealed {}\n    impl<'py> Sealed for Bound<'py, PyModule> {}\n    impl<'py> Sealed for &Bound<'py, PyModule> {}\n    impl<'a, 'py> Sealed for Borrowed<'a, 'py, PyModule> {}\n    impl<'a, 'py> Sealed for &Borrowed<'a, 'py, PyModule> {}\n    impl<'py> Sealed for Python<'py> {}\n}\n\nimpl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Bound<'py, PyModule> {\n    fn wrap_pyfunction(\n        self,\n        function_def: &'static PyFunctionDef,\n    ) -> PyResult<Bound<'py, PyCFunction>> {\n        function_def.create_py_c_function(self.py(), Some(&self))\n    }\n}\n\nimpl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Bound<'py, PyModule> {\n    fn wrap_pyfunction(\n        self,\n        function_def: &'static PyFunctionDef,\n    ) -> PyResult<Bound<'py, PyCFunction>> {\n        function_def.create_py_c_function(self.py(), Some(self))\n    }\n}\n\nimpl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Borrowed<'_, 'py, PyModule> {\n    fn wrap_pyfunction(\n        self,\n        function_def: &'static PyFunctionDef,\n    ) -> PyResult<Bound<'py, PyCFunction>> {\n        function_def.create_py_c_function(self.py(), Some(&self))\n    }\n}\n\nimpl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for &'_ Borrowed<'_, 'py, PyModule> {\n    fn wrap_pyfunction(\n        self,\n        function_def: &'static PyFunctionDef,\n    ) -> PyResult<Bound<'py, PyCFunction>> {\n        function_def.create_py_c_function(self.py(), Some(self))\n    }\n}\n\nimpl<'py> WrapPyFunctionArg<'py, Bound<'py, PyCFunction>> for Python<'py> {\n    fn wrap_pyfunction(\n        self,\n        function_def: &'static PyFunctionDef,\n    ) -> PyResult<Bound<'py, PyCFunction>> {\n        function_def.create_py_c_function(self, None)\n    }\n}\n\n/// Creates a `PyCFunction` object from a `PyMethodDef`.\n///\n/// # Safety\n///\n/// The `method_def` pointer must be valid for the lifetime of the returned `PyCFunction`\n/// (effectively, it must be a static variable).\npub unsafe fn create_py_c_function<'py>(\n    py: Python<'py>,\n    method_def: *mut ffi::PyMethodDef,\n    module: Option<&Bound<'py, PyModule>>,\n) -> PyResult<Bound<'py, PyCFunction>> {\n    let (mod_ptr, module_name) = if let Some(m) = module {\n        let mod_ptr = m.as_ptr();\n        (mod_ptr, Some(m.name()?))\n    } else {\n        (std::ptr::null_mut(), None)\n    };\n\n    let module_name_ptr = module_name\n        .as_ref()\n        .map_or(std::ptr::null_mut(), Bound::as_ptr);\n\n    unsafe {\n        ffi::PyCFunction_NewEx(method_def, mod_ptr, module_name_ptr)\n            .assume_owned_or_err(py)\n            .cast_into_unchecked()\n    }\n}\n\n#[cfg(test)]\n#[cfg(feature = \"macros\")]\nmod tests {\n    #[test]\n    fn test_wrap_pyfunction_forms() {\n        use crate::types::{PyAnyMethods, PyModule};\n        use crate::{wrap_pyfunction, Python};\n\n        #[crate::pyfunction(crate = \"crate\")]\n        fn f() {}\n\n        Python::attach(|py| {\n            let module = PyModule::new(py, \"test_wrap_pyfunction_forms\").unwrap();\n\n            let func = wrap_pyfunction!(f, module.clone()).unwrap();\n            func.call0().unwrap();\n\n            let func = wrap_pyfunction!(f, &module).unwrap();\n            func.call0().unwrap();\n\n            let module_borrowed = module.as_borrowed();\n\n            let func = wrap_pyfunction!(f, module_borrowed).unwrap();\n            func.call0().unwrap();\n\n            let func = wrap_pyfunction!(f, &module_borrowed).unwrap();\n            func.call0().unwrap();\n\n            let func = wrap_pyfunction!(f, py).unwrap();\n            func.call0().unwrap();\n        });\n    }\n}\n"
  },
  {
    "path": "src/impl_/pymethods.rs",
    "content": "use crate::exceptions::PyStopAsyncIteration;\nuse crate::impl_::callback::IntoPyCallbackOutput;\nuse crate::impl_::panic::PanicTrap;\nuse crate::impl_::pycell::PyClassObjectBaseLayout;\nuse crate::internal::get_slot::{get_slot, TP_BASE, TP_CLEAR, TP_TRAVERSE};\nuse crate::internal::state::ForbidAttaching;\nuse crate::pycell::impl_::{PyClassBorrowChecker as _, PyClassObjectLayout};\nuse crate::pycell::{PyBorrowError, PyBorrowMutError};\nuse crate::pyclass::boolean_struct::False;\nuse crate::types::PyType;\nuse crate::{\n    ffi, Bound, CastError, Py, PyAny, PyClass, PyClassGuard, PyClassGuardMut, PyErr, PyRef,\n    PyRefMut, PyResult, PyTraverseError, PyTypeCheck, PyVisit, Python,\n};\nuse std::ffi::CStr;\nuse std::ffi::{c_int, c_void};\nuse std::fmt;\nuse std::marker::PhantomData;\nuse std::panic::{catch_unwind, AssertUnwindSafe};\nuse std::ptr::{null_mut, NonNull};\n\nuse super::pyclass::PyClassImpl;\nuse super::trampoline;\nuse crate::internal_tricks::{clear_eq, traverse_eq};\n\n/// Python 3.8 and up - __ipow__ has modulo argument correctly populated.\n#[cfg(Py_3_8)]\n#[repr(transparent)]\npub struct IPowModulo(*mut ffi::PyObject);\n\n/// Python 3.7 and older - __ipow__ does not have modulo argument correctly populated.\n#[cfg(not(Py_3_8))]\n#[repr(transparent)]\npub struct IPowModulo(#[allow(dead_code)] std::mem::MaybeUninit<*mut ffi::PyObject>);\n\n/// Helper to use as pymethod ffi definition\n#[allow(non_camel_case_types)]\npub type ipowfunc = unsafe extern \"C\" fn(\n    arg1: *mut ffi::PyObject,\n    arg2: *mut ffi::PyObject,\n    arg3: IPowModulo,\n) -> *mut ffi::PyObject;\n\nimpl IPowModulo {\n    #[cfg(Py_3_8)]\n    #[inline]\n    pub fn as_ptr(self) -> *mut ffi::PyObject {\n        self.0\n    }\n\n    #[cfg(not(Py_3_8))]\n    #[inline]\n    pub fn as_ptr(self) -> *mut ffi::PyObject {\n        // Safety: returning a borrowed pointer to Python `None` singleton\n        unsafe { ffi::Py_None() }\n    }\n}\n\n/// `PyMethodDefType` represents different types of Python callable objects.\n/// It is used by the `#[pymethods]` attribute.\n#[derive(Copy, Clone)]\npub enum PyMethodDefType {\n    /// Represents a class method (might be `classmethod` or `staticmethod`, depends on `ml_flags`)\n    Method(PyMethodDef),\n    /// Represents class attribute, used by `#[attribute]`\n    ClassAttribute(PyClassAttributeDef),\n    /// Represents getter descriptor, used by `#[getter]`\n    Getter(PyGetterDef),\n    /// Represents setter descriptor, used by `#[setter]` and `#[deleter]`\n    Setter(PySetterDef),\n    /// Represents deleter descriptor, used by `#[deleter]`\n    Deleter(PyDeleterDef),\n    /// Represents a struct member\n    StructMember(ffi::PyMemberDef),\n}\n\n#[derive(Copy, Clone, Debug)]\npub enum PyMethodType {\n    PyCFunction(ffi::PyCFunction),\n    PyCFunctionWithKeywords(ffi::PyCFunctionWithKeywords),\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    PyCFunctionFastWithKeywords(ffi::PyCFunctionFastWithKeywords),\n}\n\npub type PyClassAttributeFactory = for<'p> fn(Python<'p>) -> PyResult<Py<PyAny>>;\n\n#[derive(Copy, Clone, Debug)]\npub struct PyMethodDef {\n    pub(crate) ml_name: &'static CStr,\n    pub(crate) ml_meth: PyMethodType,\n    pub(crate) ml_flags: c_int,\n    pub(crate) ml_doc: &'static CStr,\n}\n\n#[derive(Copy, Clone)]\npub struct PyClassAttributeDef {\n    pub(crate) name: &'static CStr,\n    pub(crate) meth: PyClassAttributeFactory,\n}\n\n#[derive(Copy, Clone)]\npub struct PyGetterDef {\n    pub(crate) name: &'static CStr,\n    pub(crate) meth: Getter,\n    pub(crate) doc: Option<&'static CStr>,\n}\n\n#[derive(Copy, Clone)]\npub struct PySetterDef {\n    pub(crate) name: &'static CStr,\n    pub(crate) meth: Setter,\n    pub(crate) doc: Option<&'static CStr>,\n}\n\n#[derive(Copy, Clone)]\npub struct PyDeleterDef {\n    pub(crate) name: &'static CStr,\n    pub(crate) meth: Deleter,\n    pub(crate) doc: Option<&'static CStr>,\n}\n\n/// Abstraction around fastcall calling convention, which is only available in Python 3.10 and up,\n/// can inline this directly into the proc macro when Python 3.10 support dropped\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n#[macro_export]\n#[doc(hidden)]\nmacro_rules! maybe_define_fastcall_function_with_keywords {\n    ($name:ident, $py:ident, $slf:ident, $args:ident, $nargs:ident, $kwargs:ident, $body:block) => {\n        #[allow(non_snake_case)]\n        unsafe fn $name<'py>(\n            $py: $crate::Python<'py>,\n            $slf: *mut $crate::ffi::PyObject,\n            $args: *const *mut $crate::ffi::PyObject,\n            $nargs: $crate::ffi::Py_ssize_t,\n            $kwargs: *mut $crate::ffi::PyObject\n        ) -> $crate::PyResult<*mut $crate::ffi::PyObject> $body\n    };\n}\n\n/// On older abi3 versions, required to use varargs calling convention\n#[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))]\n#[macro_export]\n#[doc(hidden)]\nmacro_rules! maybe_define_fastcall_function_with_keywords {\n    ($name:ident, $py:ident, $slf:ident, $args:ident, $nargs:ident, $kwargs:ident, $body:block) => {\n        #[allow(non_snake_case)]\n        unsafe fn $name<'py>(\n            $py: $crate::Python<'py>,\n            $slf: *mut $crate::ffi::PyObject,\n            $args: *mut $crate::ffi::PyObject,\n            $kwargs: *mut $crate::ffi::PyObject\n        ) -> $crate::PyResult<*mut $crate::ffi::PyObject> $body\n    };\n}\n\npub use crate::maybe_define_fastcall_function_with_keywords;\n\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n#[macro_export]\n#[doc(hidden)]\nmacro_rules! maybe_extract_arguments_fastcall {\n    ($description:ident, $py:ident, $args:ident, $nargs:ident, $kwargs:ident, $args_array:ident, $args_handler:ty, $kwargs_handler:ty) => {\n        // SAFETY: guaranteed by the proc macro that all args to extract_arguments_fastcall are valid\n        unsafe {\n            $description.extract_arguments_fastcall::<$args_handler, $kwargs_handler>(\n                $py,\n                $args,\n                $nargs,\n                $kwargs,\n                &mut $args_array,\n            )\n        }\n    };\n}\n\n#[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))]\n#[macro_export]\n#[doc(hidden)]\nmacro_rules! maybe_extract_arguments_fastcall {\n    ($description:ident, $py:ident, $args:ident, $nargs:ident, $kwargs:ident, $args_array:ident, $args_handler:ty, $kwargs_handler:ty) => {\n        // SAFETY: guaranteed by the proc macro that all args to extract_arguments_tuple_dict are valid\n        unsafe {\n            $description.extract_arguments_tuple_dict::<$args_handler, $kwargs_handler>(\n                $py,\n                $args,\n                $kwargs,\n                &mut $args_array,\n            )\n        }\n    };\n}\n\npub use crate::maybe_extract_arguments_fastcall;\n\nimpl PyMethodDef {\n    /// Define a function that takes no arguments.\n    pub const fn noargs(\n        ml_name: &'static CStr,\n        cfunction: ffi::PyCFunction,\n        ml_doc: &'static CStr,\n    ) -> Self {\n        Self {\n            ml_name,\n            ml_meth: PyMethodType::PyCFunction(cfunction),\n            ml_flags: ffi::METH_NOARGS,\n            ml_doc,\n        }\n    }\n\n    /// Define a function that takes arbitrary arguments as a tuple and dict.\n    pub const fn cfunction_with_keywords(\n        ml_name: &'static CStr,\n        cfunction: ffi::PyCFunctionWithKeywords,\n        ml_doc: &'static CStr,\n    ) -> Self {\n        Self {\n            ml_name,\n            ml_meth: PyMethodType::PyCFunctionWithKeywords(cfunction),\n            ml_flags: ffi::METH_VARARGS | ffi::METH_KEYWORDS,\n            ml_doc,\n        }\n    }\n\n    /// Define a function that takes arbitrary arguments as a C-style array and tuple of keyword arguments.\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    pub const fn fastcall_cfunction_with_keywords(\n        ml_name: &'static CStr,\n        cfunction: ffi::PyCFunctionFastWithKeywords,\n        ml_doc: &'static CStr,\n    ) -> Self {\n        Self {\n            ml_name,\n            ml_meth: PyMethodType::PyCFunctionFastWithKeywords(cfunction),\n            ml_flags: ffi::METH_FASTCALL | ffi::METH_KEYWORDS,\n            ml_doc,\n        }\n    }\n\n    /// Abstraction over fastcall to fall back to varargs on older Python versions.\n    pub const fn maybe_fastcall_cfunction_with_keywords(\n        ml_name: &'static CStr,\n        #[cfg(any(Py_3_10, not(Py_LIMITED_API)))] cfunction: ffi::PyCFunctionFastWithKeywords,\n        // on older abi3 versions, Fastcall not supported\n        #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))] cfunction: ffi::PyCFunctionWithKeywords,\n        ml_doc: &'static CStr,\n    ) -> Self {\n        #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n        {\n            Self::fastcall_cfunction_with_keywords(ml_name, cfunction, ml_doc)\n        }\n\n        #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))]\n        {\n            Self::cfunction_with_keywords(ml_name, cfunction, ml_doc)\n        }\n    }\n\n    pub const fn flags(mut self, flags: c_int) -> Self {\n        self.ml_flags |= flags;\n        self\n    }\n\n    pub const fn into_raw(self) -> ffi::PyMethodDef {\n        let meth = match self.ml_meth {\n            PyMethodType::PyCFunction(meth) => ffi::PyMethodDefPointer { PyCFunction: meth },\n            PyMethodType::PyCFunctionWithKeywords(meth) => ffi::PyMethodDefPointer {\n                PyCFunctionWithKeywords: meth,\n            },\n            #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n            PyMethodType::PyCFunctionFastWithKeywords(meth) => ffi::PyMethodDefPointer {\n                PyCFunctionFastWithKeywords: meth,\n            },\n        };\n\n        ffi::PyMethodDef {\n            ml_name: self.ml_name.as_ptr(),\n            ml_meth: meth,\n            ml_flags: self.ml_flags,\n            ml_doc: self.ml_doc.as_ptr(),\n        }\n    }\n}\n\nimpl PyClassAttributeDef {\n    /// Define a class attribute.\n    pub const fn new(name: &'static CStr, meth: PyClassAttributeFactory) -> Self {\n        Self { name, meth }\n    }\n}\n\n// Manual implementation because `Python<'_>` does not implement `Debug` and\n// trait bounds on `fn` compiler-generated derive impls are too restrictive.\nimpl fmt::Debug for PyClassAttributeDef {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"PyClassAttributeDef\")\n            .field(\"name\", &self.name)\n            .finish()\n    }\n}\n\n/// Class getter / setters\npub(crate) type Getter =\n    for<'py> unsafe fn(Python<'py>, NonNull<ffi::PyObject>) -> PyResult<*mut ffi::PyObject>;\npub(crate) type Setter = for<'py> unsafe fn(\n    Python<'py>,\n    NonNull<ffi::PyObject>,\n    NonNull<ffi::PyObject>,\n) -> PyResult<c_int>;\npub(crate) type Deleter =\n    for<'py> unsafe fn(Python<'py>, NonNull<ffi::PyObject>) -> PyResult<c_int>;\n\nimpl PyGetterDef {\n    /// Define a getter.\n    pub const fn new(name: &'static CStr, getter: Getter, doc: Option<&'static CStr>) -> Self {\n        Self {\n            name,\n            meth: getter,\n            doc,\n        }\n    }\n}\n\nimpl PySetterDef {\n    /// Define a setter.\n    pub const fn new(name: &'static CStr, setter: Setter, doc: Option<&'static CStr>) -> Self {\n        Self {\n            name,\n            meth: setter,\n            doc,\n        }\n    }\n}\n\nimpl PyDeleterDef {\n    /// Define a deleter.\n    pub const fn new(name: &'static CStr, deleter: Deleter, doc: Option<&'static CStr>) -> Self {\n        Self {\n            name,\n            meth: deleter,\n            doc,\n        }\n    }\n}\n\n/// Calls an implementation of __traverse__ for tp_traverse\n///\n/// NB cannot accept `'static` visitor, this is a sanity check below:\n///\n/// ```rust,compile_fail\n/// use pyo3::prelude::*;\n/// use pyo3::pyclass::{PyTraverseError, PyVisit};\n///\n/// #[pyclass]\n/// struct Foo;\n///\n/// #[pymethods]\n/// impl Foo {\n///     fn __traverse__(&self, _visit: PyVisit<'static>) -> Result<(), PyTraverseError> {\n///         Ok(())\n///     }\n/// }\n/// ```\n///\n/// Elided lifetime should compile ok:\n///\n/// ```rust,no_run\n/// use pyo3::prelude::*;\n/// use pyo3::pyclass::{PyTraverseError, PyVisit};\n///\n/// #[pyclass]\n/// struct Foo;\n///\n/// #[pymethods]\n/// impl Foo {\n///     fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n///         Ok(())\n///     }\n/// }\n/// ```\n#[doc(hidden)]\npub unsafe fn _call_traverse<T>(\n    slf: *mut ffi::PyObject,\n    impl_: fn(&T, PyVisit<'_>) -> Result<(), PyTraverseError>,\n    visit: ffi::visitproc,\n    arg: *mut c_void,\n    current_traverse: ffi::traverseproc,\n) -> c_int\nwhere\n    T: PyClass,\n{\n    // It is important the implementation of `__traverse__` cannot safely access the interpreter,\n    // c.f. https://github.com/PyO3/pyo3/issues/3165, and hence we do not expose our Python\n    // token to the user code and forbid safe methods for attaching.\n    // (This includes enforcing the `&self` method receiver as e.g. `PyRef<Self>` could\n    // reconstruct a Python token via `PyRef::py`.)\n    let trap = PanicTrap::new(\"uncaught panic inside __traverse__ handler\");\n    let lock = ForbidAttaching::during_traverse();\n\n    let super_retval = unsafe { call_super_traverse(slf, visit, arg, current_traverse) };\n    if super_retval != 0 {\n        return super_retval;\n    }\n\n    // SAFETY: `slf` is a valid Python object pointer to a class object of type T, and\n    // traversal is running so no mutations can occur.\n    let class_object: &<T as PyClassImpl>::Layout = unsafe { &*slf.cast() };\n\n    let retval =\n    // `#[pyclass(unsendable)]` types can only be deallocated by their own thread, so\n    // do not traverse them if not on their owning thread :(\n    if class_object.check_threadsafe().is_ok()\n    // ... and we cannot traverse a type which might be being mutated by a Rust thread\n    && class_object.borrow_checker().try_borrow().is_ok() {\n        struct TraverseGuard<'a, T: PyClassImpl>(&'a T::Layout);\n        impl<T: PyClassImpl> Drop for TraverseGuard<'_, T> {\n            fn drop(&mut self) {\n                self.0.borrow_checker().release_borrow()\n            }\n        }\n\n        // `.try_borrow()` above created a borrow, we need to release it when we're done\n        // traversing the object. This allows us to read `instance` safely.\n        let _guard = TraverseGuard::<T>(class_object);\n        let instance = unsafe {&*class_object.contents().value.get()};\n\n        let visit = PyVisit { visit, arg, _guard: PhantomData };\n\n        match catch_unwind(AssertUnwindSafe(move || impl_(instance, visit))) {\n            Ok(Ok(())) => 0,\n            Ok(Err(traverse_error)) => traverse_error.into_inner(),\n            Err(_err) => -1,\n        }\n    } else {\n        0\n    };\n\n    // Drop lock before trap just in case dropping lock panics\n    drop(lock);\n    trap.disarm();\n    retval\n}\n\n/// Call super-type traverse method, if necessary.\n///\n/// Adapted from <https://github.com/cython/cython/blob/7acfb375fb54a033f021b0982a3cd40c34fb22ac/Cython/Utility/ExtensionTypes.c#L386>\n///\n/// TODO: There are possible optimizations over looking up the base type in this way\n/// - if the base type is known in this module, can potentially look it up directly in module state\n///   (when we have it)\n/// - if the base type is a Python builtin, can jut call the C function directly\n/// - if the base type is a PyO3 type defined in the same module, can potentially do similar to\n///   tp_alloc where we solve this at compile time\nunsafe fn call_super_traverse(\n    obj: *mut ffi::PyObject,\n    visit: ffi::visitproc,\n    arg: *mut c_void,\n    current_traverse: ffi::traverseproc,\n) -> c_int {\n    // SAFETY: in this function here it's ok to work with raw type objects `ffi::Py_TYPE`\n    // because the GC is running and so\n    // - (a) we cannot do refcounting and\n    // - (b) the type of the object cannot change.\n    let mut ty = unsafe { ffi::Py_TYPE(obj) };\n    let mut traverse: Option<ffi::traverseproc>;\n\n    // First find the current type by the current_traverse function\n    loop {\n        traverse = unsafe { get_slot(ty, TP_TRAVERSE) };\n        if traverse_eq(traverse, current_traverse) {\n            break;\n        }\n        ty = unsafe { get_slot(ty, TP_BASE) };\n        if ty.is_null() {\n            // FIXME: return an error if current type not in the MRO? Should be impossible.\n            return 0;\n        }\n    }\n\n    // Get first base which has a different traverse function\n    while traverse_eq(traverse, current_traverse) {\n        ty = unsafe { get_slot(ty, TP_BASE) };\n        if ty.is_null() {\n            break;\n        }\n        traverse = unsafe { get_slot(ty, TP_TRAVERSE) };\n    }\n\n    // If we found a type with a different traverse function, call it\n    if let Some(traverse) = traverse {\n        return unsafe { traverse(obj, visit, arg) };\n    }\n\n    // FIXME same question as cython: what if the current type is not in the MRO?\n    0\n}\n\n/// Calls an implementation of __clear__ for tp_clear\npub unsafe fn _call_clear(\n    slf: *mut ffi::PyObject,\n    impl_: for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject) -> PyResult<()>,\n    current_clear: ffi::inquiry,\n) -> c_int {\n    unsafe {\n        trampoline::trampoline(move |py| {\n            let super_retval = call_super_clear(py, slf, current_clear);\n            if super_retval != 0 {\n                return Err(PyErr::fetch(py));\n            }\n            impl_(py, slf)?;\n            Ok(0)\n        })\n    }\n}\n\n/// Call super-type traverse method, if necessary.\n///\n/// Adapted from <https://github.com/cython/cython/blob/7acfb375fb54a033f021b0982a3cd40c34fb22ac/Cython/Utility/ExtensionTypes.c#L386>\n///\n/// TODO: There are possible optimizations over looking up the base type in this way\n/// - if the base type is known in this module, can potentially look it up directly in module state\n///   (when we have it)\n/// - if the base type is a Python builtin, can jut call the C function directly\n/// - if the base type is a PyO3 type defined in the same module, can potentially do similar to\n///   tp_alloc where we solve this at compile time\nunsafe fn call_super_clear(\n    py: Python<'_>,\n    obj: *mut ffi::PyObject,\n    current_clear: ffi::inquiry,\n) -> c_int {\n    let mut ty = unsafe { PyType::from_borrowed_type_ptr(py, ffi::Py_TYPE(obj)) };\n    let mut clear: Option<ffi::inquiry>;\n\n    // First find the current type by the current_clear function\n    loop {\n        clear = ty.get_slot(TP_CLEAR);\n        if clear_eq(clear, current_clear) {\n            break;\n        }\n        let base = ty.get_slot(TP_BASE);\n        if base.is_null() {\n            // FIXME: return an error if current type not in the MRO? Should be impossible.\n            return 0;\n        }\n        ty = unsafe { PyType::from_borrowed_type_ptr(py, base) };\n    }\n\n    // Get first base which has a different clear function\n    while clear_eq(clear, current_clear) {\n        let base = ty.get_slot(TP_BASE);\n        if base.is_null() {\n            break;\n        }\n        ty = unsafe { PyType::from_borrowed_type_ptr(py, base) };\n        clear = ty.get_slot(TP_CLEAR);\n    }\n\n    // If we found a type with a different clear function, call it\n    if let Some(clear) = clear {\n        return unsafe { clear(obj) };\n    }\n\n    // FIXME same question as cython: what if the current type is not in the MRO?\n    0\n}\n\n// Autoref-based specialization for handling `__next__` returning `Option`\n\npub struct IterBaseTag;\n\nimpl IterBaseTag {\n    #[inline]\n    pub fn convert<'py, Value, Target>(self, py: Python<'py>, value: Value) -> PyResult<Target>\n    where\n        Value: IntoPyCallbackOutput<'py, Target>,\n    {\n        value.convert(py)\n    }\n}\n\npub trait IterBaseKind {\n    #[inline]\n    fn iter_tag(&self) -> IterBaseTag {\n        IterBaseTag\n    }\n}\n\nimpl<Value> IterBaseKind for &Value {}\n\npub struct IterOptionTag;\n\nimpl IterOptionTag {\n    #[inline]\n    pub fn convert<'py, Value>(\n        self,\n        py: Python<'py>,\n        value: Option<Value>,\n    ) -> PyResult<*mut ffi::PyObject>\n    where\n        Value: IntoPyCallbackOutput<'py, *mut ffi::PyObject>,\n    {\n        match value {\n            Some(value) => value.convert(py),\n            None => Ok(null_mut()),\n        }\n    }\n}\n\npub trait IterOptionKind {\n    #[inline]\n    fn iter_tag(&self) -> IterOptionTag {\n        IterOptionTag\n    }\n}\n\nimpl<Value> IterOptionKind for Option<Value> {}\n\npub struct IterResultOptionTag;\n\nimpl IterResultOptionTag {\n    #[inline]\n    pub fn convert<'py, Value, Error>(\n        self,\n        py: Python<'py>,\n        value: Result<Option<Value>, Error>,\n    ) -> PyResult<*mut ffi::PyObject>\n    where\n        Value: IntoPyCallbackOutput<'py, *mut ffi::PyObject>,\n        Error: Into<PyErr>,\n    {\n        match value {\n            Ok(Some(value)) => value.convert(py),\n            Ok(None) => Ok(null_mut()),\n            Err(err) => Err(err.into()),\n        }\n    }\n}\n\npub trait IterResultOptionKind {\n    #[inline]\n    fn iter_tag(&self) -> IterResultOptionTag {\n        IterResultOptionTag\n    }\n}\n\nimpl<Value, Error> IterResultOptionKind for Result<Option<Value>, Error> {}\n\n// Autoref-based specialization for handling `__anext__` returning `Option`\n\npub struct AsyncIterBaseTag;\n\nimpl AsyncIterBaseTag {\n    #[inline]\n    pub fn convert<'py, Value, Target>(self, py: Python<'py>, value: Value) -> PyResult<Target>\n    where\n        Value: IntoPyCallbackOutput<'py, Target>,\n    {\n        value.convert(py)\n    }\n}\n\npub trait AsyncIterBaseKind {\n    #[inline]\n    fn async_iter_tag(&self) -> AsyncIterBaseTag {\n        AsyncIterBaseTag\n    }\n}\n\nimpl<Value> AsyncIterBaseKind for &Value {}\n\npub struct AsyncIterOptionTag;\n\nimpl AsyncIterOptionTag {\n    #[inline]\n    pub fn convert<'py, Value>(\n        self,\n        py: Python<'py>,\n        value: Option<Value>,\n    ) -> PyResult<*mut ffi::PyObject>\n    where\n        Value: IntoPyCallbackOutput<'py, *mut ffi::PyObject>,\n    {\n        match value {\n            Some(value) => value.convert(py),\n            None => Err(PyStopAsyncIteration::new_err(())),\n        }\n    }\n}\n\npub trait AsyncIterOptionKind {\n    #[inline]\n    fn async_iter_tag(&self) -> AsyncIterOptionTag {\n        AsyncIterOptionTag\n    }\n}\n\nimpl<Value> AsyncIterOptionKind for Option<Value> {}\n\npub struct AsyncIterResultOptionTag;\n\nimpl AsyncIterResultOptionTag {\n    #[inline]\n    pub fn convert<'py, Value, Error>(\n        self,\n        py: Python<'py>,\n        value: Result<Option<Value>, Error>,\n    ) -> PyResult<*mut ffi::PyObject>\n    where\n        Value: IntoPyCallbackOutput<'py, *mut ffi::PyObject>,\n        Error: Into<PyErr>,\n    {\n        match value {\n            Ok(Some(value)) => value.convert(py),\n            Ok(None) => Err(PyStopAsyncIteration::new_err(())),\n            Err(err) => Err(err.into()),\n        }\n    }\n}\n\npub trait AsyncIterResultOptionKind {\n    #[inline]\n    fn async_iter_tag(&self) -> AsyncIterResultOptionTag {\n        AsyncIterResultOptionTag\n    }\n}\n\nimpl<Value, Error> AsyncIterResultOptionKind for Result<Option<Value>, Error> {}\n\n/// Used in `#[classmethod]` to pass the class object to the method\n/// and also in `#[pyfunction(pass_module)]`.\n///\n/// This is a wrapper to avoid implementing `From<Bound>` for GIL Refs.\n///\n/// Once the GIL Ref API is fully removed, it should be possible to simplify\n/// this to just `&'a Bound<'py, T>` and `From` implementations.\npub struct BoundRef<'a, 'py, T>(pub &'a Bound<'py, T>);\n\nimpl<'a, 'py> BoundRef<'a, 'py, PyAny> {\n    pub unsafe fn ref_from_ptr(py: Python<'py>, ptr: &'a *mut ffi::PyObject) -> Self {\n        unsafe { BoundRef(Bound::ref_from_ptr(py, ptr)) }\n    }\n\n    pub unsafe fn ref_from_ptr_or_opt(\n        py: Python<'py>,\n        ptr: &'a *mut ffi::PyObject,\n    ) -> Option<Self> {\n        unsafe { Bound::ref_from_ptr_or_opt(py, ptr).as_ref().map(BoundRef) }\n    }\n\n    pub unsafe fn ref_from_non_null(py: Python<'py>, ptr: &'a NonNull<ffi::PyObject>) -> Self {\n        unsafe { Self(Bound::ref_from_non_null(py, ptr)) }\n    }\n\n    pub fn cast<T: PyTypeCheck>(self) -> Result<BoundRef<'a, 'py, T>, CastError<'a, 'py>> {\n        self.0.cast::<T>().map(BoundRef)\n    }\n\n    pub unsafe fn cast_unchecked<T>(self) -> BoundRef<'a, 'py, T> {\n        unsafe { BoundRef(self.0.cast_unchecked::<T>()) }\n    }\n}\n\nimpl<'a, 'py, T: PyClass> TryFrom<BoundRef<'a, 'py, T>> for PyClassGuard<'a, T> {\n    type Error = PyBorrowError;\n    #[inline]\n    fn try_from(value: BoundRef<'a, 'py, T>) -> Result<Self, Self::Error> {\n        PyClassGuard::try_borrow(value.0.as_unbound())\n    }\n}\n\nimpl<'a, 'py, T: PyClass<Frozen = False>> TryFrom<BoundRef<'a, 'py, T>> for PyClassGuardMut<'a, T> {\n    type Error = PyBorrowMutError;\n    #[inline]\n    fn try_from(value: BoundRef<'a, 'py, T>) -> Result<Self, Self::Error> {\n        PyClassGuardMut::try_borrow_mut(value.0.as_unbound())\n    }\n}\n\nimpl<'a, 'py, T: PyClass> TryFrom<BoundRef<'a, 'py, T>> for PyRef<'py, T> {\n    type Error = PyBorrowError;\n    #[inline]\n    fn try_from(value: BoundRef<'a, 'py, T>) -> Result<Self, Self::Error> {\n        PyRef::try_borrow(value.0)\n    }\n}\n\nimpl<'a, 'py, T: PyClass<Frozen = False>> TryFrom<BoundRef<'a, 'py, T>> for PyRefMut<'py, T> {\n    type Error = PyBorrowMutError;\n    #[inline]\n    fn try_from(value: BoundRef<'a, 'py, T>) -> Result<Self, Self::Error> {\n        PyRefMut::try_borrow(value.0)\n    }\n}\n\nimpl<'a, 'py, T> From<BoundRef<'a, 'py, T>> for Bound<'py, T> {\n    #[inline]\n    fn from(bound: BoundRef<'a, 'py, T>) -> Self {\n        bound.0.clone()\n    }\n}\n\nimpl<'a, 'py, T> From<BoundRef<'a, 'py, T>> for &'a Bound<'py, T> {\n    #[inline]\n    fn from(bound: BoundRef<'a, 'py, T>) -> Self {\n        bound.0\n    }\n}\n\nimpl<T> From<BoundRef<'_, '_, T>> for Py<T> {\n    #[inline]\n    fn from(bound: BoundRef<'_, '_, T>) -> Self {\n        bound.0.clone().unbind()\n    }\n}\n\nimpl<'py, T> std::ops::Deref for BoundRef<'_, 'py, T> {\n    type Target = Bound<'py, T>;\n    #[inline]\n    fn deref(&self) -> &Self::Target {\n        self.0\n    }\n}\n\npub unsafe fn tp_new_impl<'py, T, const IS_PYCLASS: bool, const IS_INITIALIZER_TUPLE: bool>(\n    py: Python<'py>,\n    obj: T,\n    cls: *mut ffi::PyTypeObject,\n) -> PyResult<*mut ffi::PyObject>\nwhere\n    T: super::pyclass_init::PyClassInit<'py, IS_PYCLASS, IS_INITIALIZER_TUPLE>,\n{\n    unsafe {\n        obj.init(crate::Borrowed::from_ptr_unchecked(py, cls.cast()).cast_unchecked())\n            .map(Bound::into_ptr)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    #[test]\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    fn test_fastcall_function_with_keywords() {\n        use super::PyMethodDef;\n        use crate::impl_::pyfunction::PyFunctionDef;\n        use crate::types::PyAnyMethods;\n        use crate::{ffi, Python};\n\n        Python::attach(|py| {\n            let def =\n                PyFunctionDef::from_method_def(PyMethodDef::fastcall_cfunction_with_keywords(\n                    c\"test\",\n                    accepts_no_arguments,\n                    c\"doc\",\n                ));\n            // leak to make it 'static\n            // deliberately done at runtime to have coverage of `PyFunctionDef::from_method_def`\n            let def = Box::leak(Box::new(def));\n\n            unsafe extern \"C\" fn accepts_no_arguments(\n                _slf: *mut ffi::PyObject,\n                _args: *const *mut ffi::PyObject,\n                nargs: ffi::Py_ssize_t,\n                kwargs: *mut ffi::PyObject,\n            ) -> *mut ffi::PyObject {\n                assert_eq!(nargs, 0);\n                assert!(kwargs.is_null());\n                unsafe { Python::assume_attached().None().into_ptr() }\n            }\n\n            let f = def.create_py_c_function(py, None).unwrap();\n\n            f.call0().unwrap();\n        });\n    }\n}\n"
  },
  {
    "path": "src/impl_/pymodule.rs",
    "content": "//! Implementation details of `#[pymodule]` which need to be accessible from proc-macro generated code.\n\nuse std::{\n    cell::UnsafeCell,\n    ffi::CStr,\n    marker::PhantomData,\n    os::raw::{c_int, c_void},\n};\n\n#[cfg(all(\n    not(any(PyPy, GraalPy)),\n    Py_3_9,\n    not(all(windows, Py_LIMITED_API, not(Py_3_10))),\n))]\nuse std::sync::atomic::Ordering;\n\n#[cfg(all(\n    not(any(PyPy, GraalPy)),\n    Py_3_9,\n    not(all(windows, Py_LIMITED_API, not(Py_3_10))),\n    not(target_has_atomic = \"64\"),\n))]\nuse portable_atomic::AtomicI64;\n#[cfg(all(\n    not(any(PyPy, GraalPy)),\n    Py_3_9,\n    not(all(windows, Py_LIMITED_API, not(Py_3_10))),\n    target_has_atomic = \"64\",\n))]\nuse std::sync::atomic::AtomicI64;\n\n#[cfg(not(any(PyPy, GraalPy)))]\nuse crate::exceptions::PyImportError;\nuse crate::prelude::PyTypeMethods;\nuse crate::{\n    ffi,\n    impl_::pyfunction::PyFunctionDef,\n    sync::PyOnceLock,\n    types::{any::PyAnyMethods, dict::PyDictMethods, PyDict, PyModule, PyModuleMethods},\n    Bound, Py, PyAny, PyClass, PyResult, PyTypeInfo, Python,\n};\nuse crate::{ffi_ptr_ext::FfiPtrExt, PyErr};\n\n/// `Sync` wrapper of `ffi::PyModuleDef`.\npub struct ModuleDef {\n    // wrapped in UnsafeCell so that Rust compiler treats this as interior mutability\n    ffi_def: UnsafeCell<ffi::PyModuleDef>,\n    #[cfg(Py_3_15)]\n    name: &'static CStr,\n    #[cfg(Py_3_15)]\n    doc: &'static CStr,\n    slots: &'static PyModuleSlots,\n    /// Interpreter ID where module was initialized (not applicable on PyPy).\n    #[cfg(all(\n        not(any(PyPy, GraalPy)),\n        Py_3_9,\n        not(all(windows, Py_LIMITED_API, not(Py_3_10)))\n    ))]\n    interpreter: AtomicI64,\n    /// Initialized module object, cached to avoid reinitialization.\n    module: PyOnceLock<Py<PyModule>>,\n}\n\nunsafe impl Sync for ModuleDef {}\n\nimpl ModuleDef {\n    /// Make new module definition with given module name.\n    pub const fn new(\n        name: &'static CStr,\n        doc: &'static CStr,\n        slots: &'static PyModuleSlots,\n    ) -> Self {\n        // This is only used in PyO3 for append_to_inittab on Python 3.15 and newer.\n        // There could also be other tools that need the legacy init hook.\n        // Opaque PyObject builds won't be able to use this.\n        #[allow(clippy::declare_interior_mutable_const)]\n        const INIT: ffi::PyModuleDef = ffi::PyModuleDef {\n            m_base: ffi::PyModuleDef_HEAD_INIT,\n            m_name: std::ptr::null(),\n            m_doc: std::ptr::null(),\n            m_size: 0,\n            m_methods: std::ptr::null_mut(),\n            m_slots: std::ptr::null_mut(),\n            m_traverse: None,\n            m_clear: None,\n            m_free: None,\n        };\n\n        let ffi_def = UnsafeCell::new(ffi::PyModuleDef {\n            m_name: name.as_ptr(),\n            m_doc: doc.as_ptr(),\n            // TODO: would be slightly nicer to use `[T]::as_mut_ptr()` here,\n            // but that requires mut ptr deref on MSRV.\n            m_slots: slots.0.get() as _,\n            ..INIT\n        });\n\n        ModuleDef {\n            ffi_def,\n            #[cfg(Py_3_15)]\n            name,\n            #[cfg(Py_3_15)]\n            doc,\n            slots,\n            // -1 is never expected to be a valid interpreter ID\n            #[cfg(all(\n                not(any(PyPy, GraalPy)),\n                Py_3_9,\n                not(all(windows, Py_LIMITED_API, not(Py_3_10)))\n            ))]\n            interpreter: AtomicI64::new(-1),\n            module: PyOnceLock::new(),\n        }\n    }\n\n    pub fn init_multi_phase(&'static self) -> *mut ffi::PyObject {\n        unsafe { ffi::PyModuleDef_Init(self.ffi_def.get()) }\n    }\n\n    /// Builds a module object directly. Used for [`#[pymodule]`][crate::pymodule] submodules.\n    pub fn make_module(&'static self, py: Python<'_>) -> PyResult<Py<PyModule>> {\n        // Check the interpreter ID has not changed, since we currently have no way to guarantee\n        // that static data is not reused across interpreters.\n        //\n        // PyPy does not have subinterpreters, so no need to check interpreter ID.\n        //\n        // TODO: it should be possible to use the Py_mod_multiple_interpreters slot on sufficiently\n        // new Python versions to remove the need for this custom logic\n        #[cfg(not(any(PyPy, GraalPy)))]\n        {\n            // PyInterpreterState_Get is only available on 3.9 and later, but is missing\n            // from python3.dll for Windows stable API on 3.9\n            #[cfg(all(Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10)))))]\n            {\n                let current_interpreter =\n                    unsafe { ffi::PyInterpreterState_GetID(ffi::PyInterpreterState_Get()) };\n                crate::err::error_on_minusone(py, current_interpreter)?;\n                if let Err(initialized_interpreter) = self.interpreter.compare_exchange(\n                    -1,\n                    current_interpreter,\n                    Ordering::SeqCst,\n                    Ordering::SeqCst,\n                ) {\n                    if initialized_interpreter != current_interpreter {\n                        return Err(PyImportError::new_err(\n                            \"PyO3 modules do not yet support subinterpreters, see https://github.com/PyO3/pyo3/issues/576\",\n                        ));\n                    }\n                }\n            }\n            #[cfg(not(all(Py_3_9, not(all(windows, Py_LIMITED_API, not(Py_3_10))))))]\n            {\n                // CPython before 3.9 does not have APIs to check the interpreter ID, so best that can be\n                // done to guard against subinterpreters is fail if the module is initialized twice\n                if self.module.get(py).is_some() {\n                    return Err(PyImportError::new_err(\n                        \"PyO3 modules compiled for CPython 3.8 or older may only be initialized once per interpreter process\"\n                    ));\n                }\n            }\n        }\n\n        // Make a dummy spec, needs a `name` attribute and that seems to be sufficient\n        // for the loader system\n\n        static SIMPLE_NAMESPACE: PyOnceLock<Py<PyAny>> = PyOnceLock::new();\n        let simple_ns = SIMPLE_NAMESPACE.import(py, \"types\", \"SimpleNamespace\")?;\n\n        #[cfg(not(Py_3_15))]\n        {\n            let ffi_def = self.ffi_def.get();\n\n            let m_name = unsafe { CStr::from_ptr((*ffi_def).m_name) };\n            let name = m_name\n                .to_str()\n                .map_err(|e| {\n                    crate::exceptions::PyUnicodeDecodeError::new_err_from_utf8(\n                        py,\n                        m_name.to_bytes(),\n                        e,\n                    )\n                })?\n                .to_string();\n            let kwargs = PyDict::new(py);\n            kwargs.set_item(\"name\", name)?;\n            let spec = simple_ns.call((), Some(&kwargs))?;\n\n            self.module\n                .get_or_try_init(py, || {\n                    let def = self.ffi_def.get();\n                    let module = unsafe {\n                        ffi::PyModule_FromDefAndSpec(def, spec.as_ptr()).assume_owned_or_err(py)?\n                    }\n                    .cast_into()?;\n                    if unsafe { ffi::PyModule_ExecDef(module.as_ptr(), def) } != 0 {\n                        return Err(PyErr::fetch(py));\n                    }\n                    Ok(module.unbind())\n                })\n                .map(|py_module| py_module.clone_ref(py))\n        }\n\n        #[cfg(Py_3_15)]\n        {\n            let name = self.name;\n            let doc = self.doc;\n            let kwargs = PyDict::new(py);\n            kwargs.set_item(\"name\", name)?;\n            let spec = simple_ns.call((), Some(&kwargs))?;\n\n            self.module\n                .get_or_try_init(py, || {\n                    let slots = self.get_slots();\n                    let module = unsafe { ffi::PyModule_FromSlotsAndSpec(slots, spec.as_ptr()) };\n                    if unsafe { ffi::PyModule_SetDocString(module, doc.as_ptr()) } != 0 {\n                        return Err(PyErr::fetch(py));\n                    }\n                    let module = unsafe { module.assume_owned_or_err(py)? }.cast_into()?;\n                    if unsafe { ffi::PyModule_Exec(module.as_ptr()) } != 0 {\n                        return Err(PyErr::fetch(py));\n                    }\n                    Ok(module.unbind())\n                })\n                .map(|py_module| py_module.clone_ref(py))\n        }\n    }\n    pub fn get_slots(&'static self) -> *mut ffi::PyModuleDef_Slot {\n        self.slots.0.get() as *mut ffi::PyModuleDef_Slot\n    }\n}\n\n/// Type of the exec slot used to initialise module contents\npub type ModuleExecSlot = unsafe extern \"C\" fn(*mut ffi::PyObject) -> c_int;\n\nconst MAX_SLOTS: usize =\n    // Py_mod_exec\n    1 +\n    // Py_mod_gil\n    cfg!(Py_3_13) as usize +\n    // Py_mod_name, Py_mod_doc, and Py_mod_abi\n    3 * (cfg!(Py_3_15) as usize);\nconst MAX_SLOTS_WITH_TRAILING_NULL: usize = MAX_SLOTS + 1;\n\n/// Builder to create `PyModuleSlots`. The size of the number of slots desired must\n/// be known up front, and N needs to be at least one greater than the number of\n/// actual slots pushed due to the need to have a zeroed element on the end.\npub struct PyModuleSlotsBuilder {\n    // values (initially all zeroed)\n    values: [ffi::PyModuleDef_Slot; MAX_SLOTS_WITH_TRAILING_NULL],\n    // current length\n    len: usize,\n}\n\n// note that macros cannot use conditional compilation,\n// so all implementations below must be available in all\n// Python versions\n// By handling it here we can avoid conditional\n// compilation within the macros; they can always emit\n// e.g. a `.with_gil_used()` call.\nimpl PyModuleSlotsBuilder {\n    #[allow(clippy::new_without_default)]\n    pub const fn new() -> Self {\n        Self {\n            values: [unsafe { std::mem::zeroed() }; MAX_SLOTS_WITH_TRAILING_NULL],\n            len: 0,\n        }\n    }\n\n    pub const fn with_mod_exec(self, exec: ModuleExecSlot) -> Self {\n        self.push(ffi::Py_mod_exec, exec as *mut c_void)\n    }\n\n    pub const fn with_gil_used(self, gil_used: bool) -> Self {\n        #[cfg(Py_3_13)]\n        {\n            self.push(\n                ffi::Py_mod_gil,\n                if gil_used {\n                    ffi::Py_MOD_GIL_USED\n                } else {\n                    ffi::Py_MOD_GIL_NOT_USED\n                },\n            )\n        }\n\n        #[cfg(not(Py_3_13))]\n        {\n            // Silence unused variable warning\n            let _ = gil_used;\n            self\n        }\n    }\n\n    pub const fn with_name(self, name: &'static CStr) -> Self {\n        #[cfg(Py_3_15)]\n        {\n            self.push(ffi::Py_mod_name, name.as_ptr() as *mut c_void)\n        }\n\n        #[cfg(not(Py_3_15))]\n        {\n            // Silence unused variable warning\n            let _ = name;\n            self\n        }\n    }\n\n    pub const fn with_abi_info(self) -> Self {\n        #[cfg(Py_3_15)]\n        {\n            ffi::PyABIInfo_VAR!(ABI_INFO);\n            self.push(ffi::Py_mod_abi, std::ptr::addr_of_mut!(ABI_INFO).cast())\n        }\n\n        #[cfg(not(Py_3_15))]\n        {\n            self\n        }\n    }\n\n    pub const fn with_doc(self, doc: &'static CStr) -> Self {\n        #[cfg(Py_3_15)]\n        {\n            self.push(ffi::Py_mod_doc, doc.as_ptr() as *mut c_void)\n        }\n\n        #[cfg(not(Py_3_15))]\n        {\n            // Silence unused variable warning\n            let _ = doc;\n            self\n        }\n    }\n\n    pub const fn build(self) -> PyModuleSlots {\n        PyModuleSlots(UnsafeCell::new(self.values))\n    }\n\n    const fn push(mut self, slot: c_int, value: *mut c_void) -> Self {\n        // Required to guarantee there's still a zeroed element\n        // at the end\n        assert!(\n            self.len < MAX_SLOTS,\n            \"Cannot add more than MAX_SLOTS slots to a PyModuleSlots\",\n        );\n        self.values[self.len] = ffi::PyModuleDef_Slot { slot, value };\n        self.len += 1;\n        self\n    }\n}\n\n/// Wrapper to safely store module slots, to be used in a `ModuleDef`.\npub struct PyModuleSlots(UnsafeCell<[ffi::PyModuleDef_Slot; MAX_SLOTS_WITH_TRAILING_NULL]>);\n\n// It might be possible to avoid this with SyncUnsafeCell in the future\n//\n// SAFETY: the inner values are only accessed within a `ModuleDef`,\n// which only uses them to build the `ffi::ModuleDef`.\nunsafe impl Sync for PyModuleSlots {}\n\n/// Trait to add an element (class, function...) to a module.\n///\n/// Currently only implemented for classes.\npub trait PyAddToModule: crate::sealed::Sealed {\n    fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()>;\n}\n\n/// For adding native types (non-pyclass) to a module.\npub struct AddTypeToModule<T>(PhantomData<T>);\n\nimpl<T> AddTypeToModule<T> {\n    #[allow(clippy::new_without_default)]\n    pub const fn new() -> Self {\n        AddTypeToModule(PhantomData)\n    }\n}\n\nimpl<T: PyTypeInfo> PyAddToModule for AddTypeToModule<T> {\n    fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> {\n        let object = T::type_object(module.py());\n        module.add(object.name()?, object)\n    }\n}\n\n/// For adding a class to a module.\npub struct AddClassToModule<T>(PhantomData<T>);\n\nimpl<T> AddClassToModule<T> {\n    #[allow(clippy::new_without_default)]\n    pub const fn new() -> Self {\n        AddClassToModule(PhantomData)\n    }\n}\n\nimpl<T: PyClass> PyAddToModule for AddClassToModule<T> {\n    fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> {\n        module.add_class::<T>()\n    }\n}\n\n/// For adding a function to a module.\nimpl PyAddToModule for PyFunctionDef {\n    fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> {\n        // safety: self is static\n        module.add_function(self.create_py_c_function(module.py(), Some(module))?)\n    }\n}\n\n/// For adding a module to a module.\nimpl PyAddToModule for ModuleDef {\n    fn add_to_module(&'static self, module: &Bound<'_, PyModule>) -> PyResult<()> {\n        module.add_submodule(self.make_module(module.py())?.bind(module.py()))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::{borrow::Cow, ffi::CStr, os::raw::c_int};\n\n    use crate::{\n        ffi,\n        impl_::{\n            pymodule::{PyModuleSlots, PyModuleSlotsBuilder},\n            trampoline,\n        },\n        types::{any::PyAnyMethods, module::PyModuleMethods},\n        Python,\n    };\n\n    use super::{ModuleDef, MAX_SLOTS};\n\n    unsafe extern \"C\" fn module_exec(_module: *mut ffi::PyObject) -> c_int {\n        0\n    }\n\n    #[test]\n    fn module_init() {\n        unsafe extern \"C\" fn module_exec(module: *mut ffi::PyObject) -> c_int {\n            unsafe {\n                trampoline::module_exec(module, |m| {\n                    m.add(\"SOME_CONSTANT\", 42)?;\n                    Ok(())\n                })\n            }\n        }\n\n        static NAME: &CStr = c\"test_module\";\n        static DOC: &CStr = c\"some doc\";\n\n        static SLOTS: PyModuleSlots = PyModuleSlotsBuilder::new()\n            .with_mod_exec(module_exec)\n            .with_gil_used(false)\n            .with_abi_info()\n            .with_name(NAME)\n            .with_doc(DOC)\n            .build();\n\n        static MODULE_DEF: ModuleDef = ModuleDef::new(NAME, DOC, &SLOTS);\n\n        Python::attach(|py| {\n            let module = MODULE_DEF.make_module(py).unwrap().into_bound(py);\n            assert_eq!(\n                module\n                    .getattr(\"__name__\")\n                    .unwrap()\n                    .extract::<Cow<'_, str>>()\n                    .unwrap(),\n                \"test_module\",\n            );\n            assert_eq!(\n                module\n                    .getattr(\"__doc__\")\n                    .unwrap()\n                    .extract::<Cow<'_, str>>()\n                    .unwrap(),\n                \"some doc\",\n            );\n            assert_eq!(\n                module\n                    .getattr(\"SOME_CONSTANT\")\n                    .unwrap()\n                    .extract::<u8>()\n                    .unwrap(),\n                42,\n            );\n        })\n    }\n\n    #[test]\n    fn module_def_new() {\n        // To get coverage for ModuleDef::new() need to create a non-static ModuleDef, however init\n        // etc require static ModuleDef, so this test needs to be separated out.\n        static NAME: &CStr = c\"test_module\";\n        static DOC: &CStr = c\"some doc\";\n\n        static SLOTS: PyModuleSlots = PyModuleSlotsBuilder::new().build();\n\n        let module_def: ModuleDef = ModuleDef::new(NAME, DOC, &SLOTS);\n\n        unsafe {\n            assert_eq!((*module_def.ffi_def.get()).m_slots, SLOTS.0.get().cast());\n        }\n        #[cfg(Py_3_15)]\n        {\n            assert_eq!(module_def.name, NAME);\n            assert_eq!(module_def.doc, DOC);\n        }\n        assert_eq!(module_def.slots.0.get(), SLOTS.0.get());\n    }\n\n    #[test]\n    #[cfg(panic = \"unwind\")]\n    fn test_build_maximal_slots() {\n        let builder = PyModuleSlotsBuilder::new()\n            .with_mod_exec(module_exec)\n            .with_name(c\"test_module\")\n            .with_doc(c\"some doc\")\n            .with_gil_used(false)\n            .with_abi_info();\n\n        assert!(builder.values[builder.len] == unsafe { std::mem::zeroed() });\n        assert!(builder.values[builder.len - 1] != unsafe { std::mem::zeroed() });\n        assert!(builder.len == MAX_SLOTS);\n\n        let result = std::panic::catch_unwind(|| builder.with_mod_exec(module_exec).build());\n\n        assert!(result.is_err());\n    }\n\n    #[test]\n    #[should_panic]\n    fn test_module_slots_builder_overflow() {\n        let mut builder = PyModuleSlotsBuilder::new();\n        for _ in 0..MAX_SLOTS + 1 {\n            builder = builder.with_mod_exec(module_exec);\n        }\n    }\n}\n"
  },
  {
    "path": "src/impl_/trampoline.rs",
    "content": "#![warn(clippy::undocumented_unsafe_blocks, clippy::missing_safety_doc)]\n\n//! Trampolines for various pyfunction and pymethod implementations.\n//!\n//! They exist to monomorphise std::panic::catch_unwind once into PyO3, rather than inline in every\n//! function, thus saving a huge amount of compile-time complexity.\n\nuse std::{\n    any::Any,\n    os::raw::c_int,\n    panic::{self, UnwindSafe},\n};\n\nuse crate::internal::state::AttachGuard;\nuse crate::{\n    ffi, ffi_ptr_ext::FfiPtrExt, impl_::callback::PyCallbackOutput, impl_::panic::PanicTrap,\n    impl_::pymethods::IPowModulo, panic::PanicException, types::PyModule, Bound, PyResult, Python,\n};\n\n#[inline]\npub unsafe fn module_exec(\n    module: *mut ffi::PyObject,\n    f: for<'a, 'py> fn(&'a Bound<'py, PyModule>) -> PyResult<()>,\n) -> c_int {\n    // SAFETY: f accepts a Bound object so Python is attached\n    unsafe {\n        trampoline(|py| {\n            let module = module.assume_borrowed_or_err(py)?.cast::<PyModule>()?;\n            f(&module)?;\n            Ok(0)\n        })\n    }\n}\n\n/// A workaround for Rust not allowing function pointers as const generics: define a trait which\n/// has a constant function pointer.\npub trait MethodDef<T> {\n    const METH: T;\n}\n\n/// Generates an implementation of `MethodDef` and then returns the trampoline function\n/// specialized to call the provided method.\n///\n/// Note that the functions returned by this macro are instantiations of generic functions. Code\n/// should not depend on these function pointers being stable (e.g. across compilation units);\n/// the intended purpose of these is to create function pointers which can be passed to the Python\n/// C-API to correctly wrap Rust functions.\n#[macro_export]\n#[doc(hidden)]\nmacro_rules! get_trampoline_function {\n    ($trampoline:ident, $f:path) => {{\n        struct Def;\n        impl $crate::impl_::trampoline::MethodDef<$crate::impl_::trampoline::$trampoline::Func> for Def {\n            const METH: $crate::impl_::trampoline::$trampoline::Func = $f;\n        }\n        $crate::impl_::trampoline::$trampoline::<Def>\n    }};\n}\n\npub use get_trampoline_function;\n\n/// Macro to define a trampoline function for a given function signature.\n///\n/// This macro generates:\n/// 1. An external \"C\" function that serves as the trampoline, generic on a specific function pointer.\n/// 2. A companion module containing a non-generic inner function, and the function pointer type.\nmacro_rules! trampoline {\n    (pub fn $name:ident($($arg_names:ident: $arg_types:ty),* $(,)?) -> $ret:ty;) => {\n        /// External symbol called by Python, which calls the provided Rust function.\n        ///\n        /// The Rust function is supplied via the generic parameter `Meth`.\n        ///\n        /// # Safety\n        ///\n        /// The interpreter must be attached\n        pub unsafe extern \"C\" fn $name<Meth: MethodDef<$name::Func>>(\n            $($arg_names: $arg_types,)*\n        ) -> $ret {\n            // SAFETY: caller upholds requirements\n            unsafe { $name::inner($($arg_names),*, Meth::METH) }\n        }\n\n        /// Companion module contains the function pointer type.\n        pub mod $name {\n            use super::*;\n\n            /// Non-generic inner function to ensure only one trampoline instantiated\n            ///\n            /// # Safety\n            ///\n            /// The interpreter must be attached\n            #[inline]\n            pub(crate) unsafe fn inner($($arg_names: $arg_types),*, f: $name::Func) -> $ret {\n                // SAFETY: caller upholds requirements\n                unsafe { trampoline(|py| f(py, $($arg_names,)*)) }\n            }\n\n            /// The type of the function pointer for this trampoline.\n            pub type Func = for<'py> unsafe fn (Python<'py>, $($arg_types),*) -> PyResult<$ret>;\n        }\n    }\n}\n\n/// Noargs is a special case where the `_args` parameter is unused and not passed to the inner `Func`.\n/// # Safety\n///\n/// Interpreter must be attached\npub unsafe extern \"C\" fn noargs<Meth: MethodDef<noargs::Func>>(\n    slf: *mut ffi::PyObject,\n    _args: *mut ffi::PyObject, // unused and value not defined\n) -> *mut ffi::PyObject {\n    // SAFETY: caller upholds requirements\n    unsafe { noargs::inner(slf, Meth::METH) }\n}\n\npub mod noargs {\n    use super::*;\n\n    /// # Safety\n    ///\n    /// Interpreter must be attached\n    #[inline]\n    pub(crate) unsafe fn inner(slf: *mut ffi::PyObject, f: Func) -> *mut ffi::PyObject {\n        // SAFETY: caller upholds requirements\n        unsafe { trampoline(|py| f(py, slf)) }\n    }\n\n    pub type Func = unsafe fn(Python<'_>, *mut ffi::PyObject) -> PyResult<*mut ffi::PyObject>;\n}\n\nmacro_rules! trampolines {\n    ($(pub fn $name:ident($($arg_names:ident: $arg_types:ty),* $(,)?) -> $ret:ty);* ;) => {\n        $(trampoline!(pub fn $name($($arg_names: $arg_types),*) -> $ret;));*;\n    }\n}\n\n// Trampolines used by `PyMethodDef` constructors\ntrampolines!(\n    pub fn fastcall_cfunction_with_keywords(\n        slf: *mut ffi::PyObject,\n        args: *const *mut ffi::PyObject,\n        nargs: ffi::Py_ssize_t,\n        kwnames: *mut ffi::PyObject,\n    ) -> *mut ffi::PyObject;\n\n    pub fn cfunction_with_keywords(\n        slf: *mut ffi::PyObject,\n        args: *mut ffi::PyObject,\n        kwargs: *mut ffi::PyObject,\n    ) -> *mut ffi::PyObject;\n);\n\n/// \"fastcall\" method calls only avaible on abi3 in Python 3.10 and up, otherwise fall back to the older call convention.\n#[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\npub use self::fastcall_cfunction_with_keywords as maybe_fastcall_cfunction_with_keywords;\n\n#[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))]\npub use self::cfunction_with_keywords as maybe_fastcall_cfunction_with_keywords;\n\n// Trampolines used by slot methods\ntrampolines!(\n    pub fn getattrofunc(slf: *mut ffi::PyObject, attr: *mut ffi::PyObject) -> *mut ffi::PyObject;\n\n    pub fn setattrofunc(\n        slf: *mut ffi::PyObject,\n        attr: *mut ffi::PyObject,\n        value: *mut ffi::PyObject,\n    ) -> c_int;\n\n    pub fn binaryfunc(slf: *mut ffi::PyObject, arg1: *mut ffi::PyObject) -> *mut ffi::PyObject;\n\n    pub fn descrgetfunc(\n        slf: *mut ffi::PyObject,\n        arg1: *mut ffi::PyObject,\n        arg2: *mut ffi::PyObject,\n    ) -> *mut ffi::PyObject;\n\n    pub fn getiterfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject;\n\n    pub fn hashfunc(slf: *mut ffi::PyObject) -> ffi::Py_hash_t;\n\n    pub fn inquiry(slf: *mut ffi::PyObject) -> c_int;\n\n    pub fn iternextfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject;\n\n    pub fn lenfunc(slf: *mut ffi::PyObject) -> ffi::Py_ssize_t;\n\n    pub fn newfunc(\n        subtype: *mut ffi::PyTypeObject,\n        args: *mut ffi::PyObject,\n        kwargs: *mut ffi::PyObject,\n    ) -> *mut ffi::PyObject;\n\n    pub fn initproc(\n        slf: *mut ffi::PyObject,\n        args: *mut ffi::PyObject,\n        kwargs: *mut ffi::PyObject,\n    ) -> c_int;\n\n    pub fn objobjproc(slf: *mut ffi::PyObject, arg1: *mut ffi::PyObject) -> c_int;\n\n    pub fn reprfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject;\n\n    pub fn richcmpfunc(\n        slf: *mut ffi::PyObject,\n        other: *mut ffi::PyObject,\n        op: c_int,\n    ) -> *mut ffi::PyObject;\n\n    pub fn ssizeargfunc(arg1: *mut ffi::PyObject, arg2: ffi::Py_ssize_t) -> *mut ffi::PyObject;\n\n    pub fn ternaryfunc(\n        slf: *mut ffi::PyObject,\n        arg1: *mut ffi::PyObject,\n        arg2: *mut ffi::PyObject,\n    ) -> *mut ffi::PyObject;\n\n    pub fn unaryfunc(slf: *mut ffi::PyObject) -> *mut ffi::PyObject;\n);\n\n#[cfg(any(not(Py_LIMITED_API), Py_3_11))]\ntrampoline! {\n    pub fn getbufferproc(slf: *mut ffi::PyObject, buf: *mut ffi::Py_buffer, flags: c_int) -> c_int;\n}\n\n/// Releasebufferproc is a special case where the function cannot return an error,\n/// so we use trampoline_unraisable.\n/// # Safety\n///\n/// - It must be sound to call the method with slf and buf\n/// - Interpreter must be attached\n#[cfg(any(not(Py_LIMITED_API), Py_3_11))]\npub unsafe extern \"C\" fn releasebufferproc<Meth: MethodDef<releasebufferproc::Func>>(\n    slf: *mut ffi::PyObject,\n    buf: *mut ffi::Py_buffer,\n) {\n    // SAFETY: caller upholds rquirements\n    unsafe { releasebufferproc::inner(slf, buf, Meth::METH) }\n}\n\n#[cfg(any(not(Py_LIMITED_API), Py_3_11))]\npub mod releasebufferproc {\n    use super::*;\n\n    /// # Safety\n    ///\n    /// - It must be sound to call f with slf and buf\n    /// - Interpreter must be attached\n    #[inline]\n    pub(crate) unsafe fn inner(slf: *mut ffi::PyObject, buf: *mut ffi::Py_buffer, f: Func) {\n        // SAFETY: caller upholds requirements\n        unsafe { trampoline_unraisable(|py| f(py, slf, buf), slf) }\n    }\n\n    pub type Func = unsafe fn(Python<'_>, *mut ffi::PyObject, *mut ffi::Py_buffer) -> PyResult<()>;\n}\n\n/// # Safety\n///\n/// - slf must be either a valid ffi::PyObject or NULL\n/// - if slf isn't NULL it must not be used again\n/// - The thread must be attached to the interpreter when this is called.\n#[inline]\npub(crate) unsafe fn dealloc(\n    slf: *mut ffi::PyObject,\n    f: for<'py> unsafe fn(Python<'py>, *mut ffi::PyObject) -> (),\n) {\n    // After calling tp_dealloc the object is no longer valid,\n    // so pass null_mut() to the context.\n    //\n    // (Note that we don't allow the implementation `f` to fail.)\n    //\n    // SAFETY: caller upholds requirements\n    unsafe {\n        trampoline_unraisable(\n            |py| {\n                f(py, slf);\n                Ok(())\n            },\n            std::ptr::null_mut(),\n        )\n    }\n}\n\n// Ipowfunc is a unique case where PyO3 has its own type\n// to workaround a problem on 3.7 (see IPowModulo type definition).\n// Once 3.7 support dropped can just remove this.\ntrampoline!(\n    pub fn ipowfunc(\n        arg1: *mut ffi::PyObject,\n        arg2: *mut ffi::PyObject,\n        arg3: IPowModulo,\n    ) -> *mut ffi::PyObject;\n);\n\n/// Implementation of trampoline functions, which sets up an AttachGuard and calls F.\n///\n/// Panics during execution are trapped so that they don't propagate through any\n/// outer FFI boundary.\n///\n/// # Safety\n/// The thread must already be attached to the interpreter when this is called.\n#[inline]\npub(crate) unsafe fn trampoline<F, R>(body: F) -> R\nwhere\n    F: for<'py> FnOnce(Python<'py>) -> PyResult<R> + UnwindSafe,\n    R: PyCallbackOutput,\n{\n    let trap = PanicTrap::new(\"uncaught panic at ffi boundary\");\n\n    // SAFETY: This function requires the thread to already be attached.\n    let guard = unsafe { AttachGuard::assume() };\n    let py = guard.python();\n    let out = panic_result_into_callback_output(\n        py,\n        panic::catch_unwind(move || -> PyResult<_> { body(py) }),\n    );\n    trap.disarm();\n    out\n}\n\n/// Converts the output of std::panic::catch_unwind into a Python function output, either by raising a Python\n/// exception or by unwrapping the contained success output.\n#[inline]\nfn panic_result_into_callback_output<R>(\n    py: Python<'_>,\n    panic_result: Result<PyResult<R>, Box<dyn Any + Send + 'static>>,\n) -> R\nwhere\n    R: PyCallbackOutput,\n{\n    let py_err = match panic_result {\n        Ok(Ok(value)) => return value,\n        Ok(Err(py_err)) => py_err,\n        Err(payload) => PanicException::from_panic_payload(payload),\n    };\n    py_err.restore(py);\n    R::ERR_VALUE\n}\n\n/// Implementation of trampoline for functions which can't return an error.\n///\n/// Panics during execution are trapped so that they don't propagate through any\n/// outer FFI boundary.\n///\n/// Exceptions produced are sent to `sys.unraisablehook`.\n///\n/// # Safety\n///\n/// - ctx must be either a valid ffi::PyObject or NULL\n/// - The thread must be attached to the interpreter when this is called.\n#[inline]\nunsafe fn trampoline_unraisable<F>(body: F, ctx: *mut ffi::PyObject)\nwhere\n    F: for<'py> FnOnce(Python<'py>) -> PyResult<()> + UnwindSafe,\n{\n    let trap = PanicTrap::new(\"uncaught panic at ffi boundary\");\n\n    // SAFETY: Thread is known to be attached.\n    let guard = unsafe { AttachGuard::assume() };\n    let py = guard.python();\n\n    if let Err(py_err) = panic::catch_unwind(move || body(py))\n        .unwrap_or_else(|payload| Err(PanicException::from_panic_payload(payload)))\n    {\n        // SAFETY: caller upholds requirements\n        py_err.write_unraisable(py, unsafe { ctx.assume_borrowed_or_opt(py) }.as_deref());\n    }\n    trap.disarm();\n}\n"
  },
  {
    "path": "src/impl_/unindent.rs",
    "content": "#![warn(clippy::undocumented_unsafe_blocks)]\n\nuse crate::impl_::concat::slice_copy_from_slice;\n\n/// This is a reimplementation of the `indoc` crate's unindent functionality:\n///\n/// 1. Count the leading spaces of each line, ignoring the first line and any lines that are empty or contain spaces only.\n/// 2. Take the minimum.\n/// 3. If the first line is empty i.e. the string begins with a newline, remove the first line.\n/// 4. Remove the computed number of spaces from the beginning of each line.\nconst fn unindent_bytes(bytes: &mut [u8]) -> usize {\n    // (1) + (2) - count leading spaces, take the minimum\n    let Some(to_unindent) = get_minimum_leading_spaces(bytes) else {\n        // all lines were empty, nothing to unindent\n        return bytes.len();\n    };\n\n    // now copy from the original buffer, bringing values forward as needed\n    let mut read_idx = 0;\n    let mut write_idx = 0;\n\n    // (3) - remove first line if it is empty\n    match consume_eol(bytes, read_idx) {\n        // skip empty first line\n        Some(eol) => read_idx = eol,\n        // copy non-empty first line as-is\n        None => {\n            (read_idx, write_idx) = copy_forward_until_eol(bytes, read_idx, write_idx);\n        }\n    };\n\n    // (4) - unindent remaining lines\n    while read_idx < bytes.len() {\n        let leading_spaces = count_spaces(bytes, read_idx);\n\n        if leading_spaces < to_unindent {\n            read_idx += leading_spaces;\n            assert!(\n                consume_eol(bytes, read_idx).is_some(),\n                \"removed fewer spaces than expected on non-empty line\"\n            );\n        } else {\n            // leading_spaces may be equal to or larger than to_unindent, only need to unindent\n            // the required amount, additional indentation is meaningful\n            read_idx += to_unindent;\n        }\n\n        // copy remainder of line\n        (read_idx, write_idx) = copy_forward_until_eol(bytes, read_idx, write_idx);\n    }\n\n    write_idx\n}\n\n/// Counts the minimum leading spaces of all non-empty lines except the first line.\n///\n/// Returns `None` if there are no non-empty lines except the first line.\nconst fn get_minimum_leading_spaces(bytes: &[u8]) -> Option<usize> {\n    // scan for leading spaces (ignoring first line and empty lines)\n    let mut i = 0;\n\n    // skip first line\n    i = advance_to_next_line(bytes, i);\n\n    let mut to_unindent = None;\n\n    // for remaining lines, count leading spaces\n    while i < bytes.len() {\n        let line_leading_spaces = count_spaces(bytes, i);\n        i += line_leading_spaces;\n\n        // line only had spaces, ignore for the count\n        if let Some(eol) = consume_eol(bytes, i) {\n            i = eol;\n            continue;\n        }\n\n        // this line has content, consider its leading spaces\n        if let Some(current) = to_unindent {\n            // .unwrap_or(usize::MAX) not available in const fn\n            if line_leading_spaces < current {\n                to_unindent = Some(line_leading_spaces);\n            }\n        } else {\n            to_unindent = Some(line_leading_spaces);\n        }\n\n        i = advance_to_next_line(bytes, i);\n    }\n\n    to_unindent\n}\n\nconst fn advance_to_next_line(bytes: &[u8], mut i: usize) -> usize {\n    while i < bytes.len() {\n        if let Some(eol) = consume_eol(bytes, i) {\n            return eol;\n        }\n        i += 1;\n    }\n    i\n}\n\n/// Brings elements in `bytes` forward until `\\n` (inclusive) or end of `source`.\n///\n/// `read_idx` must be greater than or equal to `write_idx`.\nconst fn copy_forward_until_eol(\n    bytes: &mut [u8],\n    mut read_idx: usize,\n    mut write_idx: usize,\n) -> (usize, usize) {\n    assert!(read_idx >= write_idx);\n    while read_idx < bytes.len() {\n        let value = bytes[read_idx];\n        bytes[write_idx] = value;\n        read_idx += 1;\n        write_idx += 1;\n        if value == b'\\n' {\n            break;\n        }\n    }\n    (read_idx, write_idx)\n}\n\nconst fn count_spaces(bytes: &[u8], mut i: usize) -> usize {\n    let mut count = 0;\n    while i < bytes.len() && bytes[i] == b' ' {\n        count += 1;\n        i += 1;\n    }\n    count\n}\n\nconst fn consume_eol(bytes: &[u8], i: usize) -> Option<usize> {\n    if bytes.len() == i {\n        // special case: treat end of buffer as EOL without consuming anything\n        Some(i)\n    } else if bytes.len() > i && bytes[i] == b'\\n' {\n        Some(i + 1)\n    } else if bytes[i] == b'\\r' && bytes.len() > i + 1 && bytes[i + 1] == b'\\n' {\n        Some(i + 2)\n    } else {\n        None\n    }\n}\n\npub const fn unindent_sized<const N: usize>(src: &[u8]) -> ([u8; N], usize) {\n    let mut out: [u8; N] = [0; N];\n    slice_copy_from_slice(&mut out, src);\n    let new_len = unindent_bytes(&mut out);\n    (out, new_len)\n}\n\n/// Helper for `py_run!` macro which unindents a string at compile time.\n#[macro_export]\n#[doc(hidden)]\nmacro_rules! unindent {\n    ($value:expr) => {{\n        const RAW: &str = $value;\n        const LEN: usize = RAW.len();\n        const UNINDENTED: ([u8; LEN], usize) =\n            $crate::impl_::unindent::unindent_sized::<LEN>(RAW.as_bytes());\n        // SAFETY: this removes only spaces and preserves all other contents\n        unsafe { ::core::str::from_utf8_unchecked(UNINDENTED.0.split_at(UNINDENTED.1).0) }\n    }};\n}\n\npub use crate::unindent;\n\n/// Equivalent of the `unindent!` macro, but works at runtime.\npub fn unindent(s: &str) -> String {\n    let mut bytes = s.as_bytes().to_owned();\n    let unindented_size = unindent_bytes(&mut bytes);\n    bytes.resize(unindented_size, 0);\n    String::from_utf8(bytes).unwrap()\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    const SAMPLE_1_WITH_FIRST_LINE: &str = \"  first line\n        line one\n\n          line two\n    \";\n\n    const UNINDENTED_1: &str = \"  first line\\nline one\\n\\n  line two\\n\";\n\n    const SAMPLE_2_EMPTY_FIRST_LINE: &str = \"\n            line one\n\n              line two\n        \";\n    const UNINDENTED_2: &str = \"line one\\n\\n  line two\\n\";\n\n    const SAMPLE_3_NO_INDENT: &str = \"\nno indent\n  here\";\n\n    const UNINDENTED_3: &str = \"no indent\\n  here\";\n\n    const SAMPLE_4_NOOP: &str = \"no indent\\nhere\\n  but here\";\n\n    const SAMPLE_5_EMPTY: &str = \"   \\n   \\n\";\n\n    const ALL_CASES: &[(&str, &str)] = &[\n        (SAMPLE_1_WITH_FIRST_LINE, UNINDENTED_1),\n        (SAMPLE_2_EMPTY_FIRST_LINE, UNINDENTED_2),\n        (SAMPLE_3_NO_INDENT, UNINDENTED_3),\n        (SAMPLE_4_NOOP, SAMPLE_4_NOOP),\n        (SAMPLE_5_EMPTY, SAMPLE_5_EMPTY),\n    ];\n\n    // run const tests for each sample to ensure they work at compile time\n\n    #[test]\n    fn test_unindent_const() {\n        const UNINDENTED: &str = unindent!(SAMPLE_1_WITH_FIRST_LINE);\n        assert_eq!(UNINDENTED, UNINDENTED_1);\n    }\n\n    #[test]\n    fn test_unindent_const_removes_empty_first_line() {\n        const UNINDENTED: &str = unindent!(SAMPLE_2_EMPTY_FIRST_LINE);\n        assert_eq!(UNINDENTED, UNINDENTED_2);\n    }\n\n    #[test]\n    fn test_unindent_const_no_indent() {\n        const UNINDENTED: &str = unindent!(SAMPLE_3_NO_INDENT);\n        assert_eq!(UNINDENTED, UNINDENTED_3);\n    }\n\n    #[test]\n    fn test_unindent_macro_runtime() {\n        // this variation on the test ensures full coverage (const eval not included in coverage)\n        const INDENTED: &str = SAMPLE_1_WITH_FIRST_LINE;\n        const LEN: usize = INDENTED.len();\n        let (unindented, unindented_size) = unindent_sized::<LEN>(INDENTED.as_bytes());\n        let unindented = std::str::from_utf8(&unindented[..unindented_size]).unwrap();\n        assert_eq!(unindented, UNINDENTED_1);\n    }\n\n    #[test]\n    fn test_unindent_function() {\n        for (indented, expected) in ALL_CASES {\n            let unindented = unindent(indented);\n            assert_eq!(&unindented, expected);\n        }\n    }\n}\n"
  },
  {
    "path": "src/impl_/wrap.rs",
    "content": "#![warn(clippy::undocumented_unsafe_blocks)]\n\nuse std::{convert::Infallible, marker::PhantomData, ops::Deref};\n\nuse crate::{\n    ffi, types::PyNone, Bound, IntoPyObject, IntoPyObjectExt, Py, PyAny, PyResult, Python,\n};\n\n/// Used to wrap values in `Option<T>` for default arguments.\npub trait SomeWrap<T> {\n    fn wrap(self) -> Option<T>;\n}\n\nimpl<T> SomeWrap<T> for T {\n    fn wrap(self) -> Option<T> {\n        Some(self)\n    }\n}\n\nimpl<T> SomeWrap<T> for Option<T> {\n    fn wrap(self) -> Self {\n        self\n    }\n}\n\n// Hierarchy of conversions used in the function return type machinery\npub struct Converter<T>(EmptyTupleConverter<T>);\npub struct EmptyTupleConverter<T>(IntoPyObjectConverter<T>);\npub struct IntoPyObjectConverter<T>(UnknownReturnResultType<T>);\npub struct UnknownReturnResultType<T>(UnknownReturnType<T>);\npub struct UnknownReturnType<T>(PhantomData<T>);\n\npub fn converter<T>(_: &T) -> Converter<T> {\n    Converter(EmptyTupleConverter(IntoPyObjectConverter(\n        UnknownReturnResultType(UnknownReturnType(PhantomData)),\n    )))\n}\n\nimpl<T> Deref for Converter<T> {\n    type Target = EmptyTupleConverter<T>;\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl<T> Deref for EmptyTupleConverter<T> {\n    type Target = IntoPyObjectConverter<T>;\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl<T> Deref for IntoPyObjectConverter<T> {\n    type Target = UnknownReturnResultType<T>;\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl<T> Deref for UnknownReturnResultType<T> {\n    type Target = UnknownReturnType<T>;\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n\nimpl EmptyTupleConverter<PyResult<()>> {\n    #[inline]\n    pub fn map_into_ptr(&self, py: Python<'_>, obj: PyResult<()>) -> PyResult<*mut ffi::PyObject> {\n        obj.map(|_| PyNone::get(py).to_owned().into_ptr())\n    }\n\n    #[inline]\n    pub fn map_into_pyobject(&self, py: Python<'_>, obj: PyResult<()>) -> PyResult<Py<PyAny>> {\n        obj.map(|_| PyNone::get(py).to_owned().into_any().unbind())\n    }\n}\n\nimpl<'py, T: IntoPyObject<'py>> IntoPyObjectConverter<T> {\n    #[inline]\n    pub fn wrap(&self, obj: T) -> Result<T, Infallible> {\n        Ok(obj)\n    }\n}\n\nimpl<'py, T: IntoPyObject<'py>, E> IntoPyObjectConverter<Result<T, E>> {\n    #[inline]\n    pub fn wrap(&self, obj: Result<T, E>) -> Result<T, E> {\n        obj\n    }\n\n    #[inline]\n    pub fn map_into_pyobject(&self, py: Python<'py>, obj: PyResult<T>) -> PyResult<Py<PyAny>>\n    where\n        T: IntoPyObject<'py>,\n    {\n        obj.and_then(|obj| obj.into_py_any(py))\n    }\n\n    #[inline]\n    pub fn map_into_ptr(&self, py: Python<'py>, obj: PyResult<T>) -> PyResult<*mut ffi::PyObject>\n    where\n        T: IntoPyObject<'py>,\n    {\n        obj.and_then(|obj| obj.into_bound_py_any(py))\n            .map(Bound::into_ptr)\n    }\n}\n\nimpl<T, E> UnknownReturnResultType<Result<T, E>> {\n    #[inline]\n    pub fn wrap<'py>(&self, _: Result<T, E>) -> Result<T, E>\n    where\n        T: IntoPyObject<'py>,\n    {\n        unreachable!(\"should be handled by IntoPyObjectConverter\")\n    }\n}\n\nimpl<T> UnknownReturnType<T> {\n    #[inline]\n    pub fn wrap<'py>(&self, _: T) -> T\n    where\n        T: IntoPyObject<'py>,\n    {\n        unreachable!(\"should be handled by IntoPyObjectConverter\")\n    }\n\n    #[inline]\n    pub fn map_into_pyobject<'py>(&self, _: Python<'py>, _: PyResult<T>) -> PyResult<Py<PyAny>>\n    where\n        T: IntoPyObject<'py>,\n    {\n        unreachable!(\"should be handled by IntoPyObjectConverter\")\n    }\n\n    #[inline]\n    pub fn map_into_ptr<'py>(&self, _: Python<'py>, _: PyResult<T>) -> PyResult<*mut ffi::PyObject>\n    where\n        T: IntoPyObject<'py>,\n    {\n        unreachable!(\"should be handled by IntoPyObjectConverter\")\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn wrap_option() {\n        let a: Option<u8> = SomeWrap::wrap(42);\n        assert_eq!(a, Some(42));\n\n        let b: Option<u8> = SomeWrap::wrap(None);\n        assert_eq!(b, None);\n    }\n}\n"
  },
  {
    "path": "src/impl_.rs",
    "content": "#![allow(missing_docs)]\n\n//! Internals of PyO3 which are accessed by code expanded from PyO3's procedural macros.\n//!\n//! Usage of any of these APIs in downstream code is implicitly acknowledging that these\n//! APIs may may change at any time without documentation in the CHANGELOG and without\n//! breaking semver guarantees.\n\npub mod callback;\npub mod concat;\n#[cfg(feature = \"experimental-async\")]\npub mod coroutine;\npub mod deprecated;\npub mod exceptions;\npub mod extract_argument;\npub mod freelist;\npub mod frompyobject;\n#[cfg(feature = \"experimental-inspect\")]\npub mod introspection;\npub mod panic;\npub mod pycell;\npub mod pyclass;\npub mod pyclass_init;\npub mod pyfunction;\npub mod pymethods;\npub mod pymodule;\n#[doc(hidden)]\npub mod trampoline;\npub mod unindent;\npub mod wrap;\n"
  },
  {
    "path": "src/inspect.rs",
    "content": "//! Runtime inspection of objects exposed to Python.\n//!\n//! Tracking issue: <https://github.com/PyO3/pyo3/issues/2454>.\n\nuse crate::impl_::introspection::{escape_json_string, escaped_json_string_len};\nuse std::fmt::{self, Display, Write};\n\n/// Builds a type hint from a module name and a member name in the module\n///\n/// ```\n/// use pyo3::type_hint_identifier;\n/// use pyo3::inspect::PyStaticExpr;\n///\n/// const T: PyStaticExpr = type_hint_identifier!(\"datetime\", \"date\");\n/// assert_eq!(T.to_string(), \"datetime.date\");\n///\n/// const T2: PyStaticExpr = type_hint_identifier!(\"builtins\", \"int\");\n/// assert_eq!(T2.to_string(), \"int\");\n/// ```\n#[macro_export]\nmacro_rules! type_hint_identifier {\n    (\"builtins\", $name:expr) => {\n        $crate::inspect::PyStaticExpr::Name { id: $name }\n    };\n    ($module:expr, $name:expr) => {\n        $crate::inspect::PyStaticExpr::Attribute {\n            value: &$crate::inspect::PyStaticExpr::Name { id: $module },\n            attr: $name,\n        }\n    };\n}\npub(crate) use type_hint_identifier;\n\n/// Builds the union of multiple type hints\n///\n/// ```\n/// use pyo3::{type_hint_identifier, type_hint_union};\n/// use pyo3::inspect::PyStaticExpr;\n///\n/// const T: PyStaticExpr = type_hint_union!(type_hint_identifier!(\"builtins\", \"int\"), type_hint_identifier!(\"builtins\", \"float\"));\n/// assert_eq!(T.to_string(), \"int | float\");\n/// ```\n#[macro_export]\nmacro_rules! type_hint_union {\n    ($e:expr) => { $e };\n    ($l:expr , $($r:expr),+) => { $crate::inspect::PyStaticExpr::BinOp {\n        left: &$l,\n        op: $crate::inspect::PyStaticOperator::BitOr,\n        right: &type_hint_union!($($r),+),\n    } };\n}\npub(crate) use type_hint_union;\n\n/// Builds a subscribed type hint\n///\n/// ```\n/// use pyo3::{type_hint_identifier, type_hint_subscript};\n/// use pyo3::inspect::PyStaticExpr;\n///\n/// const T: PyStaticExpr = type_hint_subscript!(type_hint_identifier!(\"collections.abc\", \"Sequence\"), type_hint_identifier!(\"builtins\", \"float\"));\n/// assert_eq!(T.to_string(), \"collections.abc.Sequence[float]\");\n///\n/// const T2: PyStaticExpr = type_hint_subscript!(type_hint_identifier!(\"builtins\", \"dict\"), type_hint_identifier!(\"builtins\", \"str\"), type_hint_identifier!(\"builtins\", \"float\"));\n/// assert_eq!(T2.to_string(), \"dict[str, float]\");\n/// ```\n#[macro_export]\nmacro_rules! type_hint_subscript {\n    ($l:expr, $r:expr) => {\n        $crate::inspect::PyStaticExpr::Subscript {\n            value: &$l,\n            slice: &$r\n        }\n    };\n    ($l:expr, $($r:expr),*) => {\n        $crate::inspect::PyStaticExpr::Subscript {\n            value: &$l,\n            slice: &$crate::inspect::PyStaticExpr::Tuple { elts: &[$($r),*] }\n        }\n    };\n}\npub(crate) use type_hint_subscript;\n\n/// A Python expression.\n///\n/// This is the `expr` production of the [Python `ast` module grammar](https://docs.python.org/3/library/ast.html#abstract-grammar)\n///\n/// This struct aims at being used in `const` contexts like in [`FromPyObject::INPUT_TYPE`](crate::FromPyObject::INPUT_TYPE) and [`IntoPyObject::OUTPUT_TYPE`](crate::IntoPyObject::OUTPUT_TYPE).\n///\n/// Use macros like [`type_hint_identifier`], [`type_hint_union`] and [`type_hint_subscript`] to construct values.\n#[derive(Clone, Copy)]\n#[non_exhaustive]\n#[allow(missing_docs)]\npub enum PyStaticExpr {\n    /// A constant like `None` or `123`\n    Constant { value: PyStaticConstant },\n    /// A name\n    Name { id: &'static str },\n    /// An attribute `value.attr`\n    Attribute {\n        value: &'static Self,\n        attr: &'static str,\n    },\n    /// A binary operator\n    BinOp {\n        left: &'static Self,\n        op: PyStaticOperator,\n        right: &'static Self,\n    },\n    /// A tuple\n    Tuple { elts: &'static [Self] },\n    /// A list\n    List { elts: &'static [Self] },\n    /// A subscript `value[slice]`\n    Subscript {\n        value: &'static Self,\n        slice: &'static Self,\n    },\n    /// A `#[pyclass]` type. This is separated type for introspection reasons.\n    PyClass(PyClassNameStaticExpr),\n}\n\n/// Serialize the type for introspection and return the number of written bytes\n#[doc(hidden)]\npub const fn serialize_for_introspection(expr: &PyStaticExpr, mut output: &mut [u8]) -> usize {\n    let original_len = output.len();\n    match expr {\n        PyStaticExpr::Constant { value } => match value {\n            PyStaticConstant::None => {\n                output = write_slice_and_move_forward(\n                    b\"{\\\"type\\\":\\\"constant\\\",\\\"kind\\\":\\\"none\\\"}\",\n                    output,\n                )\n            }\n            PyStaticConstant::Bool(value) => {\n                output = write_slice_and_move_forward(\n                    if *value {\n                        b\"{\\\"type\\\":\\\"constant\\\",\\\"kind\\\":\\\"bool\\\",\\\"value\\\":true}\"\n                    } else {\n                        b\"{\\\"type\\\":\\\"constant\\\",\\\"kind\\\":\\\"bool\\\",\\\"value\\\":false}\"\n                    },\n                    output,\n                )\n            }\n            PyStaticConstant::Int(value) => {\n                output = write_slice_and_move_forward(\n                    b\"{\\\"type\\\":\\\"constant\\\",\\\"kind\\\":\\\"int\\\",\\\"value\\\":\\\"\",\n                    output,\n                );\n                output = write_slice_and_move_forward(value.as_bytes(), output);\n                output = write_slice_and_move_forward(b\"\\\"}\", output);\n            }\n            PyStaticConstant::Float(value) => {\n                output = write_slice_and_move_forward(\n                    b\"{\\\"type\\\":\\\"constant\\\",\\\"kind\\\":\\\"float\\\",\\\"value\\\":\\\"\",\n                    output,\n                );\n                output = write_slice_and_move_forward(value.as_bytes(), output);\n                output = write_slice_and_move_forward(b\"\\\"}\", output);\n            }\n            PyStaticConstant::Str(value) => {\n                output = write_slice_and_move_forward(\n                    b\"{\\\"type\\\":\\\"constant\\\",\\\"kind\\\":\\\"str\\\",\\\"value\\\":\",\n                    output,\n                );\n                output = write_json_string_and_move_forward(value, output);\n                output = write_slice_and_move_forward(b\"}\", output);\n            }\n            PyStaticConstant::Ellipsis => {\n                output = write_slice_and_move_forward(\n                    b\"{\\\"type\\\":\\\"constant\\\",\\\"kind\\\":\\\"ellipsis\\\"}\",\n                    output,\n                )\n            }\n        },\n        PyStaticExpr::Name { id } => {\n            output = write_slice_and_move_forward(b\"{\\\"type\\\":\\\"name\\\",\\\"id\\\":\\\"\", output);\n            output = write_slice_and_move_forward(id.as_bytes(), output);\n            output = write_slice_and_move_forward(b\"\\\"}\", output);\n        }\n        PyStaticExpr::Attribute { value, attr } => {\n            output = write_slice_and_move_forward(b\"{\\\"type\\\":\\\"attribute\\\",\\\"value\\\":\", output);\n            output = write_expr_and_move_forward(value, output);\n            output = write_slice_and_move_forward(b\",\\\"attr\\\":\\\"\", output);\n            output = write_slice_and_move_forward(attr.as_bytes(), output);\n            output = write_slice_and_move_forward(b\"\\\"}\", output);\n        }\n        PyStaticExpr::BinOp { left, op, right } => {\n            output = write_slice_and_move_forward(b\"{\\\"type\\\":\\\"binop\\\",\\\"left\\\":\", output);\n            output = write_expr_and_move_forward(left, output);\n            output = write_slice_and_move_forward(b\",\\\"op\\\":\\\"\", output);\n            output = write_slice_and_move_forward(\n                match op {\n                    PyStaticOperator::BitOr => b\"bitor\",\n                },\n                output,\n            );\n            output = write_slice_and_move_forward(b\"\\\",\\\"right\\\":\", output);\n            output = write_expr_and_move_forward(right, output);\n            output = write_slice_and_move_forward(b\"}\", output);\n        }\n        PyStaticExpr::Tuple { elts } => {\n            output = write_container_and_move_forward(b\"tuple\", elts, output);\n        }\n        PyStaticExpr::List { elts } => {\n            output = write_container_and_move_forward(b\"list\", elts, output);\n        }\n        PyStaticExpr::Subscript { value, slice } => {\n            output = write_slice_and_move_forward(b\"{\\\"type\\\":\\\"subscript\\\",\\\"value\\\":\", output);\n            output = write_expr_and_move_forward(value, output);\n            output = write_slice_and_move_forward(b\",\\\"slice\\\":\", output);\n            output = write_expr_and_move_forward(slice, output);\n            output = write_slice_and_move_forward(b\"}\", output);\n        }\n        PyStaticExpr::PyClass(expr) => {\n            output = write_slice_and_move_forward(b\"{\\\"type\\\":\\\"id\\\",\\\"id\\\":\\\"\", output);\n            output = write_slice_and_move_forward(expr.introspection_id.as_bytes(), output);\n            output = write_slice_and_move_forward(b\"\\\"}\", output);\n        }\n    }\n    original_len - output.len()\n}\n\n/// Length required by [`serialize_for_introspection`]\n#[doc(hidden)]\npub const fn serialized_len_for_introspection(expr: &PyStaticExpr) -> usize {\n    match expr {\n        PyStaticExpr::Constant { value } => match value {\n            PyStaticConstant::None => 33,\n            PyStaticConstant::Bool(value) => 42 + if *value { 4 } else { 5 },\n            PyStaticConstant::Int(value) => 43 + value.len(),\n            PyStaticConstant::Float(value) => 45 + value.len(),\n            PyStaticConstant::Str(value) => 43 + escaped_json_string_len(value),\n            PyStaticConstant::Ellipsis => 37,\n        },\n        PyStaticExpr::Name { id } => 23 + id.len(),\n        PyStaticExpr::Attribute { value, attr } => {\n            39 + serialized_len_for_introspection(value) + attr.len()\n        }\n        PyStaticExpr::BinOp { left, op, right } => {\n            41 + serialized_len_for_introspection(left)\n                + match op {\n                    PyStaticOperator::BitOr => 5,\n                }\n                + serialized_len_for_introspection(right)\n        }\n        PyStaticExpr::Tuple { elts } => 5 + serialized_container_len_for_introspection(elts),\n        PyStaticExpr::List { elts } => 4 + serialized_container_len_for_introspection(elts),\n        PyStaticExpr::Subscript { value, slice } => {\n            38 + serialized_len_for_introspection(value) + serialized_len_for_introspection(slice)\n        }\n        PyStaticExpr::PyClass(expr) => 21 + expr.introspection_id.len(),\n    }\n}\n\nimpl fmt::Display for PyStaticExpr {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        match self {\n            Self::Constant { value } => match value {\n                PyStaticConstant::None => f.write_str(\"None\"),\n                PyStaticConstant::Bool(value) => f.write_str(if *value { \"True\" } else { \"False\" }),\n                PyStaticConstant::Int(value) => f.write_str(value),\n                PyStaticConstant::Float(value) => {\n                    f.write_str(value)?;\n                    if !value.contains(['.', 'e', 'E']) {\n                        // Makes sure it's not parsed as an int\n                        f.write_char('.')?;\n                    }\n                    Ok(())\n                }\n                PyStaticConstant::Str(value) => write!(f, \"{value:?}\"),\n                PyStaticConstant::Ellipsis => f.write_str(\"...\"),\n            },\n            Self::Name { id, .. } => f.write_str(id),\n            Self::Attribute { value, attr } => {\n                value.fmt(f)?;\n                f.write_str(\".\")?;\n                f.write_str(attr)\n            }\n            Self::BinOp { left, op, right } => {\n                left.fmt(f)?;\n                f.write_char(' ')?;\n                f.write_char(match op {\n                    PyStaticOperator::BitOr => '|',\n                })?;\n                f.write_char(' ')?;\n                right.fmt(f)\n            }\n            Self::Tuple { elts } => {\n                f.write_char('(')?;\n                fmt_elements(elts, f)?;\n                if elts.len() == 1 {\n                    f.write_char(',')?;\n                }\n                f.write_char(')')\n            }\n            Self::List { elts } => {\n                f.write_char('[')?;\n                fmt_elements(elts, f)?;\n                f.write_char(']')\n            }\n            Self::Subscript { value, slice } => {\n                value.fmt(f)?;\n                f.write_char('[')?;\n                if let PyStaticExpr::Tuple { elts } = slice {\n                    // We don't display the tuple parentheses\n                    fmt_elements(elts, f)?;\n                } else {\n                    slice.fmt(f)?;\n                }\n                f.write_char(']')\n            }\n            Self::PyClass(expr) => expr.expr.fmt(f),\n        }\n    }\n}\n\n/// A PyO3 extension to the Python AST to know more about [`PyStaticExpr::Constant`].\n///\n/// This enables advanced features like escaping.\n#[derive(Clone, Copy)]\n#[non_exhaustive]\npub enum PyStaticConstant {\n    /// None\n    None,\n    /// The `True` and `False` booleans\n    Bool(bool),\n    /// `int` value written in base 10 (`[+-]?[0-9]+`)\n    Int(&'static str),\n    /// `float` value written in base-10 (`[+-]?[0-9]*(.[0-9]*)*([eE])[0-9]*`), not including Inf and NaN\n    Float(&'static str),\n    /// `str` value unescaped and without quotes\n    Str(&'static str),\n    /// `...` value\n    Ellipsis,\n}\n\n/// An operator used in [`PyStaticExpr::BinOp`].\n#[derive(Clone, Copy)]\n#[non_exhaustive]\npub enum PyStaticOperator {\n    /// `|` operator\n    BitOr,\n}\n\nconst fn write_slice_and_move_forward<'a>(value: &[u8], output: &'a mut [u8]) -> &'a mut [u8] {\n    // TODO: use copy_from_slice with MSRV 1.87+\n    let mut i = 0;\n    while i < value.len() {\n        output[i] = value[i];\n        i += 1;\n    }\n    output.split_at_mut(value.len()).1\n}\n\nconst fn write_json_string_and_move_forward<'a>(value: &str, output: &'a mut [u8]) -> &'a mut [u8] {\n    output[0] = b'\"';\n    let output = output.split_at_mut(1).1;\n    let written = escape_json_string(value, output);\n    output[written] = b'\"';\n    output.split_at_mut(written + 1).1\n}\n\nconst fn write_expr_and_move_forward<'a>(\n    value: &PyStaticExpr,\n    output: &'a mut [u8],\n) -> &'a mut [u8] {\n    let written = serialize_for_introspection(value, output);\n    output.split_at_mut(written).1\n}\n\nconst fn write_container_and_move_forward<'a>(\n    name: &'static [u8],\n    elts: &[PyStaticExpr],\n    mut output: &'a mut [u8],\n) -> &'a mut [u8] {\n    output = write_slice_and_move_forward(b\"{\\\"type\\\":\\\"\", output);\n    output = write_slice_and_move_forward(name, output);\n    output = write_slice_and_move_forward(b\"\\\",\\\"elts\\\":[\", output);\n    let mut i = 0;\n    while i < elts.len() {\n        if i > 0 {\n            output = write_slice_and_move_forward(b\",\", output);\n        }\n        output = write_expr_and_move_forward(&elts[i], output);\n        i += 1;\n    }\n    write_slice_and_move_forward(b\"]}\", output)\n}\n\nconst fn serialized_container_len_for_introspection(elts: &[PyStaticExpr]) -> usize {\n    let mut len = 21;\n    let mut i = 0;\n    while i < elts.len() {\n        if i > 0 {\n            len += 1;\n        }\n        len += serialized_len_for_introspection(&elts[i]);\n        i += 1;\n    }\n    len\n}\n\nfn fmt_elements(elts: &[PyStaticExpr], f: &mut fmt::Formatter<'_>) -> fmt::Result {\n    for (i, elt) in elts.iter().enumerate() {\n        if i > 0 {\n            f.write_str(\", \")?;\n        }\n        elt.fmt(f)?;\n    }\n    Ok(())\n}\n\n/// The full name of a `#[pyclass]` inside a [`PyStaticExpr`].\n///\n/// To get the underlying [`PyStaticExpr`] use [`expr`](PyClassNameStaticExpr::expr).\n#[derive(Clone, Copy)]\npub struct PyClassNameStaticExpr {\n    expr: &'static PyStaticExpr,\n    introspection_id: &'static str,\n}\n\nimpl PyClassNameStaticExpr {\n    #[doc(hidden)]\n    #[inline]\n    pub const fn new(expr: &'static PyStaticExpr, introspection_id: &'static str) -> Self {\n        Self {\n            expr,\n            introspection_id,\n        }\n    }\n\n    /// The pyclass type as an expression like `module.name`\n    ///\n    /// This is based on the `name` and `module` parameter of the `#[pyclass]` macro.\n    /// The `module` part might not be a valid module from which the type can be imported.\n    #[inline]\n    pub const fn expr(&self) -> &'static PyStaticExpr {\n        self.expr\n    }\n}\n\nimpl AsRef<PyStaticExpr> for PyClassNameStaticExpr {\n    #[inline]\n    fn as_ref(&self) -> &PyStaticExpr {\n        self.expr\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_to_string() {\n        const T: PyStaticExpr = type_hint_subscript!(\n            type_hint_identifier!(\"builtins\", \"dict\"),\n            type_hint_union!(\n                type_hint_identifier!(\"builtins\", \"int\"),\n                type_hint_subscript!(\n                    type_hint_identifier!(\"typing\", \"Literal\"),\n                    PyStaticExpr::Constant {\n                        value: PyStaticConstant::Str(\"\\0\\t\\\\\\\"\")\n                    }\n                )\n            ),\n            type_hint_identifier!(\"datetime\", \"time\")\n        );\n        assert_eq!(\n            T.to_string(),\n            \"dict[int | typing.Literal[\\\"\\\\0\\\\t\\\\\\\\\\\\\\\"\\\"], datetime.time]\"\n        )\n    }\n\n    #[test]\n    fn test_serialize_for_introspection() {\n        fn check_serialization(expr: PyStaticExpr, expected: &str) {\n            let mut out = vec![0; serialized_len_for_introspection(&expr)];\n            serialize_for_introspection(&expr, &mut out);\n            assert_eq!(std::str::from_utf8(&out).unwrap(), expected)\n        }\n\n        check_serialization(\n            PyStaticExpr::Constant {\n                value: PyStaticConstant::None,\n            },\n            r#\"{\"type\":\"constant\",\"kind\":\"none\"}\"#,\n        );\n        check_serialization(\n            type_hint_identifier!(\"builtins\", \"int\"),\n            r#\"{\"type\":\"name\",\"id\":\"int\"}\"#,\n        );\n        check_serialization(\n            type_hint_identifier!(\"datetime\", \"date\"),\n            r#\"{\"type\":\"attribute\",\"value\":{\"type\":\"name\",\"id\":\"datetime\"},\"attr\":\"date\"}\"#,\n        );\n        check_serialization(\n            type_hint_union!(\n                type_hint_identifier!(\"builtins\", \"int\"),\n                type_hint_identifier!(\"builtins\", \"float\")\n            ),\n            r#\"{\"type\":\"binop\",\"left\":{\"type\":\"name\",\"id\":\"int\"},\"op\":\"bitor\",\"right\":{\"type\":\"name\",\"id\":\"float\"}}\"#,\n        );\n        check_serialization(\n            PyStaticExpr::Tuple {\n                elts: &[type_hint_identifier!(\"builtins\", \"list\")],\n            },\n            r#\"{\"type\":\"tuple\",\"elts\":[{\"type\":\"name\",\"id\":\"list\"}]}\"#,\n        );\n        check_serialization(\n            PyStaticExpr::List {\n                elts: &[type_hint_identifier!(\"builtins\", \"list\")],\n            },\n            r#\"{\"type\":\"list\",\"elts\":[{\"type\":\"name\",\"id\":\"list\"}]}\"#,\n        );\n        check_serialization(\n            type_hint_subscript!(\n                type_hint_identifier!(\"builtins\", \"list\"),\n                type_hint_identifier!(\"builtins\", \"int\")\n            ),\n            r#\"{\"type\":\"subscript\",\"value\":{\"type\":\"name\",\"id\":\"list\"},\"slice\":{\"type\":\"name\",\"id\":\"int\"}}\"#,\n        );\n        check_serialization(\n            PyStaticExpr::PyClass(PyClassNameStaticExpr::new(\n                &type_hint_identifier!(\"builtins\", \"foo\"),\n                \"foo\",\n            )),\n            r#\"{\"type\":\"id\",\"id\":\"foo\"}\"#,\n        );\n        check_serialization(\n            PyStaticExpr::Constant {\n                value: PyStaticConstant::Bool(true),\n            },\n            r#\"{\"type\":\"constant\",\"kind\":\"bool\",\"value\":true}\"#,\n        );\n        check_serialization(\n            PyStaticExpr::Constant {\n                value: PyStaticConstant::Bool(false),\n            },\n            r#\"{\"type\":\"constant\",\"kind\":\"bool\",\"value\":false}\"#,\n        );\n        check_serialization(\n            PyStaticExpr::Constant {\n                value: PyStaticConstant::Int(\"-123\"),\n            },\n            r#\"{\"type\":\"constant\",\"kind\":\"int\",\"value\":\"-123\"}\"#,\n        );\n        check_serialization(\n            PyStaticExpr::Constant {\n                value: PyStaticConstant::Float(\"-2.1\"),\n            },\n            r#\"{\"type\":\"constant\",\"kind\":\"float\",\"value\":\"-2.1\"}\"#,\n        );\n        check_serialization(\n            PyStaticExpr::Constant {\n                value: PyStaticConstant::Float(\"+2.1e10\"),\n            },\n            r#\"{\"type\":\"constant\",\"kind\":\"float\",\"value\":\"+2.1e10\"}\"#,\n        );\n        check_serialization(\n            PyStaticExpr::Constant {\n                value: PyStaticConstant::Str(\"abc(1)\"),\n            },\n            r#\"{\"type\":\"constant\",\"kind\":\"str\",\"value\":\"abc(1)\"}\"#,\n        );\n        check_serialization(\n            PyStaticExpr::Constant {\n                value: PyStaticConstant::Str(\"\\\"\\\\/\\x08\\x0C\\n\\r\\t\\0\\x19a\"),\n            },\n            r#\"{\"type\":\"constant\",\"kind\":\"str\",\"value\":\"\\\"\\\\/\\b\\f\\n\\r\\t\\u0000\\u0019a\"}\"#,\n        );\n        check_serialization(\n            PyStaticExpr::Constant {\n                value: PyStaticConstant::Ellipsis,\n            },\n            r#\"{\"type\":\"constant\",\"kind\":\"ellipsis\"}\"#,\n        );\n    }\n}\n"
  },
  {
    "path": "src/instance.rs",
    "content": "#![warn(clippy::undocumented_unsafe_blocks)] // TODO: remove this when the top-level is \"warn\" - https://github.com/PyO3/pyo3/issues/5487\n\nuse crate::call::PyCallArgs;\nuse crate::conversion::IntoPyObject;\nuse crate::err::{PyErr, PyResult};\nuse crate::impl_::pyclass::PyClassImpl;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse crate::pycell::impl_::PyClassObjectLayout;\nuse crate::pycell::{PyBorrowError, PyBorrowMutError};\nuse crate::pyclass::boolean_struct::{False, True};\nuse crate::types::{any::PyAnyMethods, string::PyStringMethods, typeobject::PyTypeMethods};\nuse crate::types::{DerefToPyAny, PyDict, PyString};\n#[allow(deprecated)]\nuse crate::DowncastError;\nuse crate::{\n    ffi, CastError, CastIntoError, FromPyObject, PyAny, PyClass, PyClassInitializer, PyRef,\n    PyRefMut, PyTypeInfo, Python,\n};\nuse crate::{internal::state, PyTypeCheck};\nuse std::marker::PhantomData;\nuse std::mem::ManuallyDrop;\nuse std::ops::Deref;\nuse std::ptr;\nuse std::ptr::NonNull;\n\n/// Owned or borrowed Python smart pointer with a lifetime `'py` signalling\n/// attachment to the Python interpreter.\n///\n/// This is implemented for [`Bound`] and [`Borrowed`].\npub trait BoundObject<'py, T>: bound_object_sealed::Sealed {\n    /// Type erased version of `Self`\n    type Any: BoundObject<'py, PyAny>;\n    /// Borrow this smart pointer.\n    fn as_borrowed(&self) -> Borrowed<'_, 'py, T>;\n    /// Turns this smart pointer into an owned [`Bound<'py, T>`]\n    fn into_bound(self) -> Bound<'py, T>;\n    /// Upcast the target type of this smart pointer\n    fn into_any(self) -> Self::Any;\n    /// Turn this smart pointer into a strong reference pointer\n    fn into_ptr(self) -> *mut ffi::PyObject;\n    /// Turn this smart pointer into a borrowed reference pointer\n    fn as_ptr(&self) -> *mut ffi::PyObject;\n    /// Turn this smart pointer into an owned [`Py<T>`]\n    fn unbind(self) -> Py<T>;\n}\n\nmod bound_object_sealed {\n    /// # Safety\n    ///\n    /// Type must be layout-compatible with `*mut ffi::PyObject`.\n    pub unsafe trait Sealed {}\n\n    // SAFETY: `Bound` is layout-compatible with `*mut ffi::PyObject`.\n    unsafe impl<T> Sealed for super::Bound<'_, T> {}\n    // SAFETY: `Borrowed` is layout-compatible with `*mut ffi::PyObject`.\n    unsafe impl<T> Sealed for super::Borrowed<'_, '_, T> {}\n}\n\n/// A Python thread-attached equivalent to [`Py<T>`].\n///\n/// This type can be thought of as equivalent to the tuple `(Py<T>, Python<'py>)`. By having the `'py`\n/// lifetime of the [`Python<'py>`] token, this ties the lifetime of the [`Bound<'py, T>`] smart pointer\n/// to the lifetime the thread is attached to the Python interpreter and allows PyO3 to call Python APIs\n/// at maximum efficiency.\n///\n/// To access the object in situations where the thread is not attached, convert it to [`Py<T>`]\n/// using [`.unbind()`][Bound::unbind]. This includes, for example, usage in\n/// [`Python::detach`](crate::Python::detach)'s closure.\n///\n/// See\n#[doc = concat!(\"[the guide](https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/types.html#boundpy-t)\")]\n/// for more detail.\n#[repr(transparent)]\npub struct Bound<'py, T>(Python<'py>, ManuallyDrop<Py<T>>);\n\nimpl<'py, T> Bound<'py, T>\nwhere\n    T: PyClass,\n{\n    /// Creates a new instance `Bound<T>` of a `#[pyclass]` on the Python heap.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyclass]\n    /// struct Foo {/* fields omitted */}\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// let foo: Py<Foo> = Python::attach(|py| -> PyResult<_> {\n    ///     let foo: Bound<'_, Foo> = Bound::new(py, Foo {})?;\n    ///     Ok(foo.into())\n    /// })?;\n    /// # Python::attach(move |_py| drop(foo));\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn new(\n        py: Python<'py>,\n        value: impl Into<PyClassInitializer<T>>,\n    ) -> PyResult<Bound<'py, T>> {\n        value.into().create_class_object(py)\n    }\n}\n\nimpl<'py, T> Bound<'py, T> {\n    /// Cast this to a concrete Python type or pyclass.\n    ///\n    /// Note that you can often avoid casting yourself by just specifying the desired type in\n    /// function or method signatures. However, manual casting is sometimes necessary.\n    ///\n    /// For extracting a Rust-only type, see [`extract`](PyAnyMethods::extract).\n    ///\n    /// This performs a runtime type check using the equivalent of Python's\n    /// `isinstance(self, U)`.\n    ///\n    /// # Example: Casting to a specific Python object\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::{PyDict, PyList};\n    ///\n    /// Python::attach(|py| {\n    ///     let dict = PyDict::new(py);\n    ///     assert!(dict.is_instance_of::<PyAny>());\n    ///     let any = dict.as_any();\n    ///\n    ///     assert!(any.cast::<PyDict>().is_ok());\n    ///     assert!(any.cast::<PyList>().is_err());\n    /// });\n    /// ```\n    ///\n    /// # Example: Getting a reference to a pyclass\n    ///\n    /// This is useful if you want to mutate a `Py<PyAny>` that might actually be a pyclass.\n    ///\n    /// ```rust\n    /// # fn main() -> Result<(), pyo3::PyErr> {\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyclass]\n    /// struct Class {\n    ///     i: i32,\n    /// }\n    ///\n    /// Python::attach(|py| {\n    ///     let class = Bound::new(py, Class { i: 0 })?.into_any();\n    ///\n    ///     let class_bound: &Bound<'_, Class> = class.cast()?;\n    ///\n    ///     class_bound.borrow_mut().i += 1;\n    ///\n    ///     // Alternatively you can get a `PyRefMut` directly\n    ///     let class_ref: PyRefMut<'_, Class> = class.extract()?;\n    ///     assert_eq!(class_ref.i, 1);\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    #[inline]\n    pub fn cast<U>(&self) -> Result<&Bound<'py, U>, CastError<'_, 'py>>\n    where\n        U: PyTypeCheck,\n    {\n        #[inline]\n        fn inner<'a, 'py, U>(\n            any: &'a Bound<'py, PyAny>,\n        ) -> Result<&'a Bound<'py, U>, CastError<'a, 'py>>\n        where\n            U: PyTypeCheck,\n        {\n            if U::type_check(any) {\n                // Safety: type_check is responsible for ensuring that the type is correct\n                Ok(unsafe { any.cast_unchecked() })\n            } else {\n                Err(CastError::new(\n                    any.as_borrowed(),\n                    U::classinfo_object(any.py()),\n                ))\n            }\n        }\n\n        inner(self.as_any())\n    }\n\n    /// Like [`cast`](Self::cast) but takes ownership of `self`.\n    ///\n    /// In case of an error, it is possible to retrieve `self` again via\n    /// [`CastIntoError::into_inner`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::{PyDict, PyList};\n    ///\n    /// Python::attach(|py| {\n    ///     let obj: Bound<'_, PyAny> = PyDict::new(py).into_any();\n    ///\n    ///     let obj: Bound<'_, PyAny> = match obj.cast_into::<PyList>() {\n    ///         Ok(_) => panic!(\"obj should not be a list\"),\n    ///         Err(err) => err.into_inner(),\n    ///     };\n    ///\n    ///     // obj is a dictionary\n    ///     assert!(obj.cast_into::<PyDict>().is_ok());\n    /// })\n    /// ```\n    #[inline]\n    pub fn cast_into<U>(self) -> Result<Bound<'py, U>, CastIntoError<'py>>\n    where\n        U: PyTypeCheck,\n    {\n        #[inline]\n        fn inner<U>(any: Bound<'_, PyAny>) -> Result<Bound<'_, U>, CastIntoError<'_>>\n        where\n            U: PyTypeCheck,\n        {\n            if U::type_check(&any) {\n                // Safety: type_check is responsible for ensuring that the type is correct\n                Ok(unsafe { any.cast_into_unchecked() })\n            } else {\n                let to = U::classinfo_object(any.py());\n                Err(CastIntoError::new(any, to))\n            }\n        }\n\n        inner(self.into_any())\n    }\n\n    /// Cast this to a concrete Python type or pyclass (but not a subclass of it).\n    ///\n    /// It is almost always better to use [`cast`](Self::cast) because it accounts for Python\n    /// subtyping. Use this method only when you do not want to allow subtypes.\n    ///\n    /// The advantage of this method over [`cast`](Self::cast) is that it is faster. The\n    /// implementation of `cast_exact` uses the equivalent of the Python expression `type(self) is\n    /// U`, whereas `cast` uses `isinstance(self, U)`.\n    ///\n    /// For extracting a Rust-only type, see [`extract`](PyAnyMethods::extract).\n    ///\n    /// # Example: Casting to a specific Python object but not a subtype\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::{PyBool, PyInt};\n    ///\n    /// Python::attach(|py| {\n    ///     let b = PyBool::new(py, true);\n    ///     assert!(b.is_instance_of::<PyBool>());\n    ///     let any: &Bound<'_, PyAny> = b.as_any();\n    ///\n    ///     // `bool` is a subtype of `int`, so `cast` will accept a `bool` as an `int`\n    ///     // but `cast_exact` will not.\n    ///     assert!(any.cast::<PyInt>().is_ok());\n    ///     assert!(any.cast_exact::<PyInt>().is_err());\n    ///\n    ///     assert!(any.cast_exact::<PyBool>().is_ok());\n    /// });\n    /// ```\n    #[inline]\n    pub fn cast_exact<U>(&self) -> Result<&Bound<'py, U>, CastError<'_, 'py>>\n    where\n        U: PyTypeInfo,\n    {\n        #[inline]\n        fn inner<'a, 'py, U>(\n            any: &'a Bound<'py, PyAny>,\n        ) -> Result<&'a Bound<'py, U>, CastError<'a, 'py>>\n        where\n            U: PyTypeInfo,\n        {\n            if any.is_exact_instance_of::<U>() {\n                // Safety: is_exact_instance_of is responsible for ensuring that the type is correct\n                Ok(unsafe { any.cast_unchecked() })\n            } else {\n                Err(CastError::new(\n                    any.as_borrowed(),\n                    U::type_object(any.py()).into_any(),\n                ))\n            }\n        }\n\n        inner(self.as_any())\n    }\n\n    /// Like [`cast_exact`](Self::cast_exact) but takes ownership of `self`.\n    #[inline]\n    pub fn cast_into_exact<U>(self) -> Result<Bound<'py, U>, CastIntoError<'py>>\n    where\n        U: PyTypeInfo,\n    {\n        #[inline]\n        fn inner<U>(any: Bound<'_, PyAny>) -> Result<Bound<'_, U>, CastIntoError<'_>>\n        where\n            U: PyTypeInfo,\n        {\n            if any.is_exact_instance_of::<U>() {\n                // Safety: is_exact_instance_of is responsible for ensuring that the type is correct\n                Ok(unsafe { any.cast_into_unchecked() })\n            } else {\n                let to = U::type_object(any.py()).into_any();\n                Err(CastIntoError::new(any, to))\n            }\n        }\n\n        inner(self.into_any())\n    }\n\n    /// Converts this to a concrete Python type without checking validity.\n    ///\n    /// # Safety\n    ///\n    /// Callers must ensure that the type is valid or risk type confusion.\n    #[inline]\n    pub unsafe fn cast_unchecked<U>(&self) -> &Bound<'py, U> {\n        // SAFETY: caller has upheld the safety contract, all `Bound` have the same layout\n        unsafe { NonNull::from(self).cast().as_ref() }\n    }\n\n    /// Like [`cast_unchecked`](Self::cast_unchecked) but takes ownership of `self`.\n    ///\n    /// # Safety\n    ///\n    /// Callers must ensure that the type is valid or risk type confusion.\n    #[inline]\n    pub unsafe fn cast_into_unchecked<U>(self) -> Bound<'py, U> {\n        // SAFETY: caller has upheld the safety contract, all `Bound` have the same layout\n        unsafe { std::mem::transmute(self) }\n    }\n}\n\nimpl<'py> Bound<'py, PyAny> {\n    /// Constructs a new `Bound<'py, PyAny>` from a pointer. Panics if `ptr` is null.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object (or null, which will cause a panic)\n    /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership\n    ///\n    /// # Panics\n    ///\n    /// Panics if `ptr` is null.\n    #[inline]\n    #[track_caller]\n    pub unsafe fn from_owned_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self {\n        let non_null = NonNull::new(ptr).unwrap_or_else(|| panic_on_null(py));\n        // SAFETY: caller has upheld the safety contract, ptr is known to be non-null\n        unsafe { Py::from_non_null(non_null) }.into_bound(py)\n    }\n\n    /// Constructs a new `Bound<'py, PyAny>` from a pointer. Returns `None` if `ptr` is null.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object, or null\n    /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership\n    #[inline]\n    pub unsafe fn from_owned_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option<Self> {\n        NonNull::new(ptr).map(|nonnull_ptr| {\n            // SAFETY: caller has upheld the safety contract\n            unsafe { Py::from_non_null(nonnull_ptr) }.into_bound(py)\n        })\n    }\n\n    /// Constructs a new `Bound<'py, PyAny>` from a pointer. Returns an `Err` by calling `PyErr::fetch`\n    /// if `ptr` is null.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object, or null\n    /// - `ptr` must be an owned Python reference, as the `Bound<'py, PyAny>` will assume ownership\n    #[inline]\n    pub unsafe fn from_owned_ptr_or_err(\n        py: Python<'py>,\n        ptr: *mut ffi::PyObject,\n    ) -> PyResult<Self> {\n        match NonNull::new(ptr) {\n            Some(nonnull_ptr) => Ok(\n                // SAFETY: caller has upheld the safety contract, ptr is known to be non-null\n                unsafe { Py::from_non_null(nonnull_ptr) }.into_bound(py),\n            ),\n            None => Err(PyErr::fetch(py)),\n        }\n    }\n\n    /// Constructs a new `Bound<'py, PyAny>` from a pointer without checking for null.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object\n    /// - `ptr` must be a strong/owned reference\n    pub(crate) unsafe fn from_owned_ptr_unchecked(\n        py: Python<'py>,\n        ptr: *mut ffi::PyObject,\n    ) -> Self {\n        // SAFETY: caller has upheld the safety contract\n        unsafe { Py::from_non_null(NonNull::new_unchecked(ptr)) }.into_bound(py)\n    }\n\n    /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference.\n    /// Panics if `ptr` is null.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object\n    ///\n    /// # Panics\n    ///\n    /// Panics if `ptr` is null\n    #[inline]\n    #[track_caller]\n    pub unsafe fn from_borrowed_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self {\n        let non_null = NonNull::new(ptr).unwrap_or_else(|| panic_on_null(py));\n        // SAFETY: caller has upheld the safety contract, ptr is known to be non-null\n        unsafe { Py::from_borrowed_non_null(py, non_null) }.into_bound(py)\n    }\n\n    /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference.\n    /// Returns `None` if `ptr` is null.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object, or null\n    #[inline]\n    pub unsafe fn from_borrowed_ptr_or_opt(\n        py: Python<'py>,\n        ptr: *mut ffi::PyObject,\n    ) -> Option<Self> {\n        NonNull::new(ptr).map(|nonnull_ptr| {\n            // SAFETY: caller has upheld the safety contract\n            unsafe { Py::from_borrowed_non_null(py, nonnull_ptr) }.into_bound(py)\n        })\n    }\n\n    /// Constructs a new `Bound<'py, PyAny>` from a pointer by creating a new Python reference.\n    /// Returns an `Err` by calling `PyErr::fetch` if `ptr` is null.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object, or null\n    #[inline]\n    pub unsafe fn from_borrowed_ptr_or_err(\n        py: Python<'py>,\n        ptr: *mut ffi::PyObject,\n    ) -> PyResult<Self> {\n        match NonNull::new(ptr) {\n            Some(nonnull_ptr) => Ok(\n                // SAFETY: caller has upheld the safety contract\n                unsafe { Py::from_borrowed_non_null(py, nonnull_ptr) }.into_bound(py),\n            ),\n            None => Err(PyErr::fetch(py)),\n        }\n    }\n\n    /// This slightly strange method is used to obtain `&Bound<PyAny>` from a pointer in macro code\n    /// where we need to constrain the lifetime `'a` safely.\n    ///\n    /// Note that `'py` is required to outlive `'a` implicitly by the nature of the fact that\n    /// `&'a Bound<'py>` means that `Bound<'py>` exists for at least the lifetime `'a`.\n    ///\n    /// # Safety\n    /// - `ptr` must be a valid pointer to a Python object for the lifetime `'a`. The `ptr` can\n    ///   be either a borrowed reference or an owned reference, it does not matter, as this is\n    ///   just `&Bound` there will never be any ownership transfer.\n    #[inline]\n    pub(crate) unsafe fn ref_from_ptr<'a>(\n        _py: Python<'py>,\n        ptr: &'a *mut ffi::PyObject,\n    ) -> &'a Self {\n        let ptr = NonNull::from(ptr).cast();\n        // SAFETY: caller has upheld the safety contract,\n        // and `Bound<PyAny>` is layout-compatible with `*mut ffi::PyObject`.\n        unsafe { ptr.as_ref() }\n    }\n\n    /// Variant of the above which returns `None` for null pointers.\n    ///\n    /// # Safety\n    /// - `ptr` must be a valid pointer to a Python object for the lifetime `'a, or null.\n    #[inline]\n    pub(crate) unsafe fn ref_from_ptr_or_opt<'a>(\n        _py: Python<'py>,\n        ptr: &'a *mut ffi::PyObject,\n    ) -> &'a Option<Self> {\n        let ptr = NonNull::from(ptr).cast();\n        // SAFETY: caller has upheld the safety contract,\n        // and `Option<Bound<PyAny>>` is layout-compatible with `*mut ffi::PyObject`.\n        unsafe { ptr.as_ref() }\n    }\n\n    /// This slightly strange method is used to obtain `&Bound<PyAny>` from a [`NonNull`] in macro\n    /// code where we need to constrain the lifetime `'a` safely.\n    ///\n    /// Note that `'py` is required to outlive `'a` implicitly by the nature of the fact that `&'a\n    /// Bound<'py>` means that `Bound<'py>` exists for at least the lifetime `'a`.\n    ///\n    /// # Safety\n    /// - `ptr` must be a valid pointer to a Python object for the lifetime `'a`. The `ptr` can be\n    ///   either a borrowed reference or an owned reference, it does not matter, as this is just\n    ///   `&Bound` there will never be any ownership transfer.\n    pub(crate) unsafe fn ref_from_non_null<'a>(\n        _py: Python<'py>,\n        ptr: &'a NonNull<ffi::PyObject>,\n    ) -> &'a Self {\n        let ptr = NonNull::from(ptr).cast();\n        // SAFETY: caller has upheld the safety contract,\n        // and `Bound<PyAny>` is layout-compatible with `NonNull<ffi::PyObject>`.\n        unsafe { ptr.as_ref() }\n    }\n}\n\nimpl<'py, T> Bound<'py, T>\nwhere\n    T: PyClass,\n{\n    /// Immutably borrows the value `T`.\n    ///\n    /// This borrow lasts while the returned [`PyRef`] exists.\n    /// Multiple immutable borrows can be taken out at the same time.\n    ///\n    /// For frozen classes, the simpler [`get`][Self::get] is available.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use pyo3::prelude::*;\n    /// #\n    /// #[pyclass]\n    /// struct Foo {\n    ///     inner: u8,\n    /// }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let foo: Bound<'_, Foo> = Bound::new(py, Foo { inner: 73 })?;\n    ///     let inner: &u8 = &foo.borrow().inner;\n    ///\n    ///     assert_eq!(*inner, 73);\n    ///     Ok(())\n    /// })?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Panics\n    ///\n    /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use\n    /// [`try_borrow`](#method.try_borrow).\n    #[inline]\n    #[track_caller]\n    pub fn borrow(&self) -> PyRef<'py, T> {\n        PyRef::borrow(self)\n    }\n\n    /// Mutably borrows the value `T`.\n    ///\n    /// This borrow lasts while the returned [`PyRefMut`] exists.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use pyo3::prelude::*;\n    /// #\n    /// #[pyclass]\n    /// struct Foo {\n    ///     inner: u8,\n    /// }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let foo: Bound<'_, Foo> = Bound::new(py, Foo { inner: 73 })?;\n    ///     foo.borrow_mut().inner = 35;\n    ///\n    ///     assert_eq!(foo.borrow().inner, 35);\n    ///     Ok(())\n    /// })?;\n    /// # Ok(())\n    /// # }\n    ///  ```\n    ///\n    /// # Panics\n    /// Panics if the value is currently borrowed. For a non-panicking variant, use\n    /// [`try_borrow_mut`](#method.try_borrow_mut).\n    #[inline]\n    #[track_caller]\n    pub fn borrow_mut(&self) -> PyRefMut<'py, T>\n    where\n        T: PyClass<Frozen = False>,\n    {\n        PyRefMut::borrow(self)\n    }\n\n    /// Attempts to immutably borrow the value `T`, returning an error if the value is currently mutably borrowed.\n    ///\n    /// The borrow lasts while the returned [`PyRef`] exists.\n    ///\n    /// This is the non-panicking variant of [`borrow`](#method.borrow).\n    ///\n    /// For frozen classes, the simpler [`get`][Self::get] is available.\n    #[inline]\n    pub fn try_borrow(&self) -> Result<PyRef<'py, T>, PyBorrowError> {\n        PyRef::try_borrow(self)\n    }\n\n    /// Attempts to mutably borrow the value `T`, returning an error if the value is currently borrowed.\n    ///\n    /// The borrow lasts while the returned [`PyRefMut`] exists.\n    ///\n    /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut).\n    #[inline]\n    pub fn try_borrow_mut(&self) -> Result<PyRefMut<'py, T>, PyBorrowMutError>\n    where\n        T: PyClass<Frozen = False>,\n    {\n        PyRefMut::try_borrow(self)\n    }\n\n    /// Provide an immutable borrow of the value `T`.\n    ///\n    /// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`].\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use std::sync::atomic::{AtomicUsize, Ordering};\n    /// # use pyo3::prelude::*;\n    ///\n    /// #[pyclass(frozen)]\n    /// struct FrozenCounter {\n    ///     value: AtomicUsize,\n    /// }\n    ///\n    /// Python::attach(|py| {\n    ///     let counter = FrozenCounter { value: AtomicUsize::new(0) };\n    ///\n    ///     let py_counter = Bound::new(py, counter).unwrap();\n    ///\n    ///     py_counter.get().value.fetch_add(1, Ordering::Relaxed);\n    /// });\n    /// ```\n    #[inline]\n    pub fn get(&self) -> &T\n    where\n        T: PyClass<Frozen = True> + Sync,\n    {\n        self.as_borrowed().get()\n    }\n\n    /// Upcast this `Bound<PyClass>` to its base type by reference.\n    ///\n    /// If this type defined an explicit base class in its `pyclass` declaration\n    /// (e.g. `#[pyclass(extends = BaseType)]`), the returned type will be\n    /// `&Bound<BaseType>`. If an explicit base class was _not_ declared, the\n    /// return value will be `&Bound<PyAny>` (making this method equivalent\n    /// to [`as_any`]).\n    ///\n    /// This method is particularly useful for calling methods defined in an\n    /// extension trait that has been implemented for `Bound<BaseType>`.\n    ///\n    /// See also the [`into_super`] method to upcast by value, and the\n    /// [`PyRef::as_super`]/[`PyRefMut::as_super`] methods for upcasting a pyclass\n    /// that has already been [`borrow`]ed.\n    ///\n    /// # Example: Calling a method defined on the `Bound` base type\n    ///\n    /// ```rust\n    /// # fn main() {\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyclass(subclass)]\n    /// struct BaseClass;\n    ///\n    /// trait MyClassMethods<'py> {\n    ///     fn pyrepr(&self) -> PyResult<String>;\n    /// }\n    /// impl<'py> MyClassMethods<'py> for Bound<'py, BaseClass> {\n    ///     fn pyrepr(&self) -> PyResult<String> {\n    ///         self.call_method0(\"__repr__\")?.extract()\n    ///     }\n    /// }\n    ///\n    /// #[pyclass(extends = BaseClass)]\n    /// struct SubClass;\n    ///\n    /// Python::attach(|py| {\n    ///     let obj = Bound::new(py, (SubClass, BaseClass)).unwrap();\n    ///     assert!(obj.as_super().pyrepr().is_ok());\n    /// })\n    /// # }\n    /// ```\n    ///\n    /// [`as_any`]: Bound::as_any\n    /// [`into_super`]: Bound::into_super\n    /// [`borrow`]: Bound::borrow\n    #[inline]\n    pub fn as_super(&self) -> &Bound<'py, T::BaseType> {\n        // SAFETY: a pyclass can always be safely \"cast\" to its base type\n        unsafe { self.cast_unchecked() }\n    }\n\n    /// Upcast this `Bound<PyClass>` to its base type by value.\n    ///\n    /// If this type defined an explicit base class in its `pyclass` declaration\n    /// (e.g. `#[pyclass(extends = BaseType)]`), the returned type will be\n    /// `Bound<BaseType>`. If an explicit base class was _not_ declared, the\n    /// return value will be `Bound<PyAny>` (making this method equivalent\n    /// to [`into_any`]).\n    ///\n    /// This method is particularly useful for calling methods defined in an\n    /// extension trait that has been implemented for `Bound<BaseType>`.\n    ///\n    /// See also the [`as_super`] method to upcast by reference, and the\n    /// [`PyRef::into_super`]/[`PyRefMut::into_super`] methods for upcasting a pyclass\n    /// that has already been [`borrow`]ed.\n    ///\n    /// # Example: Calling a method defined on the `Bound` base type\n    ///\n    /// ```rust\n    /// # fn main() {\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyclass(subclass)]\n    /// struct BaseClass;\n    ///\n    /// trait MyClassMethods<'py> {\n    ///     fn pyrepr(self) -> PyResult<String>;\n    /// }\n    /// impl<'py> MyClassMethods<'py> for Bound<'py, BaseClass> {\n    ///     fn pyrepr(self) -> PyResult<String> {\n    ///         self.call_method0(\"__repr__\")?.extract()\n    ///     }\n    /// }\n    ///\n    /// #[pyclass(extends = BaseClass)]\n    /// struct SubClass;\n    ///\n    /// Python::attach(|py| {\n    ///     let obj = Bound::new(py, (SubClass, BaseClass)).unwrap();\n    ///     assert!(obj.into_super().pyrepr().is_ok());\n    /// })\n    /// # }\n    /// ```\n    ///\n    /// [`into_any`]: Bound::into_any\n    /// [`as_super`]: Bound::as_super\n    /// [`borrow`]: Bound::borrow\n    #[inline]\n    pub fn into_super(self) -> Bound<'py, T::BaseType> {\n        // SAFETY: a pyclass can always be safely \"cast\" to its base type\n        unsafe { self.cast_into_unchecked() }\n    }\n\n    #[inline]\n    pub(crate) fn get_class_object(&self) -> &<T as PyClassImpl>::Layout {\n        self.1.get_class_object()\n    }\n}\n\nimpl<T> std::fmt::Debug for Bound<'_, T> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {\n        let any = self.as_any();\n        python_format(any, any.repr(), f)\n    }\n}\n\nimpl<T> std::fmt::Display for Bound<'_, T> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {\n        let any = self.as_any();\n        python_format(any, any.str(), f)\n    }\n}\n\nfn python_format(\n    any: &Bound<'_, PyAny>,\n    format_result: PyResult<Bound<'_, PyString>>,\n    f: &mut std::fmt::Formatter<'_>,\n) -> Result<(), std::fmt::Error> {\n    match format_result {\n        Result::Ok(s) => return f.write_str(&s.to_string_lossy()),\n        Result::Err(err) => err.write_unraisable(any.py(), Some(any)),\n    }\n\n    match any.get_type().name() {\n        Result::Ok(name) => std::write!(f, \"<unprintable {name} object>\"),\n        Result::Err(_err) => f.write_str(\"<unprintable object>\"),\n    }\n}\n\n// The trait bound is needed to avoid running into the auto-deref recursion\n// limit (error[E0055]), because `Bound<PyAny>` would deref into itself. See:\n// https://github.com/rust-lang/rust/issues/19509\nimpl<'py, T> Deref for Bound<'py, T>\nwhere\n    T: DerefToPyAny,\n{\n    type Target = Bound<'py, PyAny>;\n\n    #[inline]\n    fn deref(&self) -> &Bound<'py, PyAny> {\n        self.as_any()\n    }\n}\n\nimpl<'py, T> AsRef<Bound<'py, PyAny>> for Bound<'py, T> {\n    #[inline]\n    fn as_ref(&self) -> &Bound<'py, PyAny> {\n        self.as_any()\n    }\n}\n\nimpl<T> AsRef<Py<PyAny>> for Bound<'_, T> {\n    #[inline]\n    fn as_ref(&self) -> &Py<PyAny> {\n        self.as_any().as_unbound()\n    }\n}\n\nimpl<T> Clone for Bound<'_, T> {\n    #[inline]\n    fn clone(&self) -> Self {\n        Self(self.0, ManuallyDrop::new(self.1.clone_ref(self.0)))\n    }\n}\n\nimpl<T> Drop for Bound<'_, T> {\n    #[inline]\n    fn drop(&mut self) {\n        // SAFETY: self is an owned reference and the `Bound` implies the thread\n        // is attached to the interpreter\n        unsafe { ffi::Py_DECREF(self.as_ptr()) }\n    }\n}\n\nimpl<'py, T> Bound<'py, T> {\n    /// Returns the [`Python`] token associated with this object.\n    #[inline]\n    pub fn py(&self) -> Python<'py> {\n        self.0\n    }\n\n    /// Returns the raw FFI pointer represented by self.\n    ///\n    /// # Safety\n    ///\n    /// Callers are responsible for ensuring that the pointer does not outlive self.\n    ///\n    /// The reference is borrowed; callers should not decrease the reference count\n    /// when they are finished with the pointer.\n    #[inline]\n    pub fn as_ptr(&self) -> *mut ffi::PyObject {\n        self.1.as_ptr()\n    }\n\n    /// Returns an owned raw FFI pointer represented by self.\n    ///\n    /// # Safety\n    ///\n    /// The reference is owned; when finished the caller should either transfer ownership\n    /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)).\n    #[inline]\n    pub fn into_ptr(self) -> *mut ffi::PyObject {\n        ManuallyDrop::new(self).as_ptr()\n    }\n\n    /// Helper to cast to `Bound<'py, PyAny>`.\n    #[inline]\n    pub fn as_any(&self) -> &Bound<'py, PyAny> {\n        let ptr = NonNull::from(self).cast();\n        // Safety: all Bound<T> have the same memory layout, and all Bound<T> are valid\n        // Bound<PyAny>, so pointer casting is valid.\n        unsafe { ptr.as_ref() }\n    }\n\n    /// Helper to cast to `Bound<'py, PyAny>`, transferring ownership.\n    #[inline]\n    pub fn into_any(self) -> Bound<'py, PyAny> {\n        // Safety: all Bound<T> are valid Bound<PyAny>\n        Bound(self.0, ManuallyDrop::new(self.unbind().into_any()))\n    }\n\n    /// Casts this `Bound<T>` to a `Borrowed<T>` smart pointer.\n    #[inline]\n    pub fn as_borrowed<'a>(&'a self) -> Borrowed<'a, 'py, T> {\n        // SAFETY: self is known to be a valid pointer to T and will be borrowed from the lifetime 'a\n        unsafe { Borrowed::from_non_null(self.py(), (self.1).0).cast_unchecked() }\n    }\n\n    /// Removes the connection for this `Bound<T>` from the [`Python<'py>`] token,\n    /// allowing it to cross thread boundaries.\n    #[inline]\n    pub fn unbind(self) -> Py<T> {\n        let non_null = (ManuallyDrop::new(self).1).0;\n        // SAFETY: the type T is known to be correct and the `ManuallyDrop` ensures\n        // the ownership of the reference is transferred into the `Py<T>`.\n        unsafe { Py::from_non_null(non_null) }\n    }\n\n    /// Removes the connection for this `Bound<T>` from the [`Python<'py>`] token,\n    /// allowing it to cross thread boundaries, without transferring ownership.\n    #[inline]\n    pub fn as_unbound(&self) -> &Py<T> {\n        &self.1\n    }\n}\n\nimpl<'py, T> BoundObject<'py, T> for Bound<'py, T> {\n    type Any = Bound<'py, PyAny>;\n\n    fn as_borrowed(&self) -> Borrowed<'_, 'py, T> {\n        Bound::as_borrowed(self)\n    }\n\n    fn into_bound(self) -> Bound<'py, T> {\n        self\n    }\n\n    fn into_any(self) -> Self::Any {\n        self.into_any()\n    }\n\n    fn into_ptr(self) -> *mut ffi::PyObject {\n        self.into_ptr()\n    }\n\n    fn as_ptr(&self) -> *mut ffi::PyObject {\n        self.as_ptr()\n    }\n\n    fn unbind(self) -> Py<T> {\n        self.unbind()\n    }\n}\n\n/// A borrowed equivalent to [`Bound`].\n///\n/// [`Borrowed<'a, 'py, T>`] is an advanced type used just occasionally at the edge of interaction\n/// with the Python interpreter. It can be thought of as analogous to the shared reference `&'a\n/// Bound<'py, T>`, similarly this type is `Copy` and `Clone`. The difference is that [`Borrowed<'a,\n/// 'py, T>`] is just a smart pointer rather than a reference-to-a-smart-pointer. For one this\n/// reduces one level of pointer indirection, but additionally it removes the implicit lifetime\n/// relation that `'py` has to outlive `'a` (`'py: 'a`). This opens the possibility to borrow from\n/// the underlying Python object without necessarily requiring attachment to the interpreter for\n/// that duration. Within PyO3 this is used for example for the byte slice (`&[u8]`) extraction.\n///\n/// [`Borrowed<'a, 'py, T>`] dereferences to [`Bound<'py, T>`], so all methods on [`Bound<'py, T>`]\n/// are available on [`Borrowed<'a, 'py, T>`].\n///\n/// Some Python C APIs also return \"borrowed\" pointers, which need to be increfd by the caller to\n/// keep them alive. This can also be modelled using [`Borrowed`]. However with free-threading these\n/// APIs are gradually replaced, because in absence of the GIL it is very hard to guarantee that the\n/// referred to object is not deallocated between receiving the pointer and incrementing the\n/// reference count. When possible APIs which return a \"strong\" reference (modelled by [`Bound`])\n/// should be using instead and otherwise great care needs to be taken to ensure safety.\n#[repr(transparent)]\npub struct Borrowed<'a, 'py, T>(NonNull<ffi::PyObject>, PhantomData<&'a Py<T>>, Python<'py>);\n\nimpl<'a, 'py, T> Borrowed<'a, 'py, T> {\n    /// Creates a new owned [`Bound<T>`] from this borrowed reference by\n    /// increasing the reference count.\n    ///\n    /// # Example\n    /// ```\n    /// use pyo3::{prelude::*, types::PyTuple};\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let tuple = PyTuple::new(py, [1, 2, 3])?;\n    ///\n    ///     // borrows from `tuple`, so can only be\n    ///     // used while `tuple` stays alive\n    ///     let borrowed = tuple.get_borrowed_item(0)?;\n    ///\n    ///     // creates a new owned reference, which\n    ///     // can be used indendently of `tuple`\n    ///     let bound = borrowed.to_owned();\n    ///     drop(tuple);\n    ///\n    ///     assert_eq!(bound.extract::<i32>().unwrap(), 1);\n    ///     Ok(())\n    /// })\n    /// # }\n    pub fn to_owned(self) -> Bound<'py, T> {\n        (*self).clone()\n    }\n\n    /// Returns the raw FFI pointer represented by self.\n    ///\n    /// # Safety\n    ///\n    /// Callers are responsible for ensuring that the pointer does not outlive self.\n    ///\n    /// The reference is borrowed; callers should not decrease the reference count\n    /// when they are finished with the pointer.\n    #[inline]\n    pub fn as_ptr(self) -> *mut ffi::PyObject {\n        self.0.as_ptr()\n    }\n\n    pub(crate) fn to_any(self) -> Borrowed<'a, 'py, PyAny> {\n        Borrowed(self.0, PhantomData, self.2)\n    }\n\n    /// Extracts some type from the Python object.\n    ///\n    /// This is a wrapper function around [`FromPyObject::extract()`](crate::FromPyObject::extract).\n    pub fn extract<O>(self) -> Result<O, O::Error>\n    where\n        O: FromPyObject<'a, 'py>,\n    {\n        FromPyObject::extract(self.to_any())\n    }\n\n    /// Cast this to a concrete Python type or pyclass.\n    ///\n    /// This performs a runtime type check using the equivalent of Python's\n    /// `isinstance(self, U)`.\n    #[inline]\n    pub fn cast<U>(self) -> Result<Borrowed<'a, 'py, U>, CastError<'a, 'py>>\n    where\n        U: PyTypeCheck,\n    {\n        fn inner<'a, 'py, U>(\n            any: Borrowed<'a, 'py, PyAny>,\n        ) -> Result<Borrowed<'a, 'py, U>, CastError<'a, 'py>>\n        where\n            U: PyTypeCheck,\n        {\n            if U::type_check(&any) {\n                // Safety: type_check is responsible for ensuring that the type is correct\n                Ok(unsafe { any.cast_unchecked() })\n            } else {\n                Err(CastError::new(any, U::classinfo_object(any.py())))\n            }\n        }\n        inner(self.to_any())\n    }\n\n    /// Cast this to a concrete Python type or pyclass (but not a subclass of it).\n    ///\n    /// It is almost always better to use [`cast`](Self::cast) because it accounts for Python\n    /// subtyping. Use this method only when you do not want to allow subtypes.\n    ///\n    /// The advantage of this method over [`cast`](Self::cast) is that it is faster. The\n    /// implementation of `cast_exact` uses the equivalent of the Python expression `type(self) is\n    /// U`, whereas `cast` uses `isinstance(self, U)`.\n    #[inline]\n    pub fn cast_exact<U>(self) -> Result<Borrowed<'a, 'py, U>, CastError<'a, 'py>>\n    where\n        U: PyTypeInfo,\n    {\n        fn inner<'a, 'py, U>(\n            any: Borrowed<'a, 'py, PyAny>,\n        ) -> Result<Borrowed<'a, 'py, U>, CastError<'a, 'py>>\n        where\n            U: PyTypeInfo,\n        {\n            if any.is_exact_instance_of::<U>() {\n                // Safety: is_exact_instance_of is responsible for ensuring that the type is correct\n                Ok(unsafe { any.cast_unchecked() })\n            } else {\n                Err(CastError::new(any, U::classinfo_object(any.py())))\n            }\n        }\n        inner(self.to_any())\n    }\n\n    /// Converts this to a concrete Python type without checking validity.\n    ///\n    /// # Safety\n    /// Callers must ensure that the type is valid or risk type confusion.\n    #[inline]\n    pub unsafe fn cast_unchecked<U>(self) -> Borrowed<'a, 'py, U> {\n        Borrowed(self.0, PhantomData, self.2)\n    }\n\n    /// Provide an immutable borrow of the value `T`.\n    ///\n    /// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`].\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use std::sync::atomic::{AtomicUsize, Ordering};\n    /// # use pyo3::prelude::*;\n    ///\n    /// #[pyclass(frozen)]\n    /// struct FrozenCounter {\n    ///     value: AtomicUsize,\n    /// }\n    ///\n    /// Python::attach(|py| {\n    ///     let counter = FrozenCounter { value: AtomicUsize::new(0) };\n    ///\n    ///     let py_counter = Bound::new(py, counter).unwrap();\n    ///\n    ///     let py_counter_borrowed = py_counter.as_borrowed();\n    ///\n    ///     py_counter_borrowed.get().value.fetch_add(1, Ordering::Relaxed);\n    /// });\n    /// ```\n    #[inline]\n    pub fn get(self) -> &'a T\n    where\n        T: PyClass<Frozen = True> + Sync,\n    {\n        // Safety: The class itself is frozen and `Sync`\n        unsafe { &*self.get_class_object().get_ptr() }\n    }\n}\n\nimpl<'a, T: PyClass> Borrowed<'a, '_, T> {\n    /// Get a view on the underlying `PyClass` contents.\n    #[inline]\n    pub(crate) fn get_class_object(self) -> &'a <T as PyClassImpl>::Layout {\n        // Safety: Borrowed<'a, '_, T: PyClass> is known to contain an object\n        // which is laid out in memory as a PyClassObject<T> and lives for at\n        // least 'a.\n        unsafe { &*self.as_ptr().cast::<<T as PyClassImpl>::Layout>() }\n    }\n}\n\nimpl<'a, 'py> Borrowed<'a, 'py, PyAny> {\n    /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Panics if `ptr` is null.\n    ///\n    /// Prefer to use [`Bound::from_borrowed_ptr`], as that avoids the major safety risk\n    /// of needing to precisely define the lifetime `'a` for which the borrow is valid.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object (or null, which will cause a panic)\n    /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by\n    ///   the caller and it is the caller's responsibility to ensure that the reference this is\n    ///   derived from is valid for the lifetime `'a`.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `ptr` is null\n    #[inline]\n    #[track_caller]\n    pub unsafe fn from_ptr(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self {\n        let non_null = NonNull::new(ptr).unwrap_or_else(|| panic_on_null(py));\n        // SAFETY: caller has upheld the safety contract\n        unsafe { Self::from_non_null(py, non_null) }\n    }\n\n    /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Returns `None` if `ptr` is null.\n    ///\n    /// Prefer to use [`Bound::from_borrowed_ptr_or_opt`], as that avoids the major safety risk\n    /// of needing to precisely define the lifetime `'a` for which the borrow is valid.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object, or null\n    /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by\n    ///   the caller and it is the caller's responsibility to ensure that the reference this is\n    ///   derived from is valid for the lifetime `'a`.\n    #[inline]\n    pub unsafe fn from_ptr_or_opt(py: Python<'py>, ptr: *mut ffi::PyObject) -> Option<Self> {\n        NonNull::new(ptr).map(|ptr|\n            // SAFETY: caller has upheld the safety contract\n            unsafe { Self::from_non_null(py, ptr) })\n    }\n\n    /// Constructs a new `Borrowed<'a, 'py, PyAny>` from a pointer. Returns an `Err` by calling `PyErr::fetch`\n    /// if `ptr` is null.\n    ///\n    /// Prefer to use [`Bound::from_borrowed_ptr_or_err`], as that avoids the major safety risk\n    /// of needing to precisely define the lifetime `'a` for which the borrow is valid.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object, or null\n    /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by\n    ///   the caller and it is the caller's responsibility to ensure that the reference this is\n    ///   derived from is valid for the lifetime `'a`.\n    #[inline]\n    pub unsafe fn from_ptr_or_err(py: Python<'py>, ptr: *mut ffi::PyObject) -> PyResult<Self> {\n        NonNull::new(ptr).map_or_else(\n            || Err(PyErr::fetch(py)),\n            |ptr| {\n                Ok(\n                    // SAFETY: ptr is known to be non-null, caller has upheld the safety contract\n                    unsafe { Self::from_non_null(py, ptr) },\n                )\n            },\n        )\n    }\n\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object. It must not be null.\n    /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by\n    ///   the caller and it is the caller's responsibility to ensure that the reference this is\n    ///   derived from is valid for the lifetime `'a`.\n    #[inline]\n    pub(crate) unsafe fn from_ptr_unchecked(py: Python<'py>, ptr: *mut ffi::PyObject) -> Self {\n        // SAFETY: caller has upheld the safety contract\n        unsafe { Self::from_non_null(py, NonNull::new_unchecked(ptr)) }\n    }\n\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object.\n    /// - similar to `std::slice::from_raw_parts`, the lifetime `'a` is completely defined by\n    ///   the caller and it is the caller's responsibility to ensure that the reference this is\n    ///   derived from is valid for the lifetime `'a`.\n    #[inline]\n    pub(crate) unsafe fn from_non_null(py: Python<'py>, ptr: NonNull<ffi::PyObject>) -> Self {\n        Self(ptr, PhantomData, py)\n    }\n}\n\nimpl<'a, 'py, T> From<&'a Bound<'py, T>> for Borrowed<'a, 'py, T> {\n    /// Create borrow on a Bound\n    #[inline]\n    fn from(instance: &'a Bound<'py, T>) -> Self {\n        instance.as_borrowed()\n    }\n}\n\nimpl<T> AsRef<Py<PyAny>> for Borrowed<'_, '_, T> {\n    #[inline]\n    fn as_ref(&self) -> &Py<PyAny> {\n        self.as_any().as_unbound()\n    }\n}\n\nimpl<T> std::fmt::Debug for Borrowed<'_, '_, T> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        Bound::fmt(self, f)\n    }\n}\n\nimpl<'py, T> Deref for Borrowed<'_, 'py, T> {\n    type Target = Bound<'py, T>;\n\n    #[inline]\n    fn deref(&self) -> &Bound<'py, T> {\n        // SAFETY: self.0 is a valid object of type T\n        unsafe { Bound::ref_from_non_null(self.2, &self.0).cast_unchecked() }\n    }\n}\n\nimpl<T> Clone for Borrowed<'_, '_, T> {\n    #[inline]\n    fn clone(&self) -> Self {\n        *self\n    }\n}\n\nimpl<T> Copy for Borrowed<'_, '_, T> {}\n\nimpl<'a, 'py, T> BoundObject<'py, T> for Borrowed<'a, 'py, T> {\n    type Any = Borrowed<'a, 'py, PyAny>;\n\n    fn as_borrowed(&self) -> Borrowed<'a, 'py, T> {\n        *self\n    }\n\n    fn into_bound(self) -> Bound<'py, T> {\n        (*self).to_owned()\n    }\n\n    fn into_any(self) -> Self::Any {\n        self.to_any()\n    }\n\n    fn into_ptr(self) -> *mut ffi::PyObject {\n        (*self).to_owned().into_ptr()\n    }\n\n    fn as_ptr(&self) -> *mut ffi::PyObject {\n        (*self).as_ptr()\n    }\n\n    fn unbind(self) -> Py<T> {\n        (*self).to_owned().unbind()\n    }\n}\n\n/// A reference to an object allocated on the Python heap.\n///\n/// To access the contained data use the following methods:\n///  - [`Py::bind`] or [`Py::into_bound`], to bind the reference to the lifetime of the [`Python<'py>`] token.\n///  - [`Py::borrow`], [`Py::try_borrow`], [`Py::borrow_mut`], or [`Py::try_borrow_mut`],\n///\n/// to get a (mutable) reference to a contained pyclass, using a scheme similar to std's [`RefCell`].\n/// See the\n#[doc = concat!(\"[guide entry](https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#bound-and-interior-mutability)\")]\n/// for more information.\n///  - You can call methods directly on `Py` with [`Py::call`], [`Py::call_method`] and friends.\n///\n/// These require passing in the [`Python<'py>`](crate::Python) token but are otherwise similar to the corresponding\n/// methods on [`PyAny`].\n///\n/// # Example: Storing Python objects in `#[pyclass]` structs\n///\n/// Usually `Bound<'py, T>` is recommended for interacting with Python objects as its lifetime `'py`\n/// proves the thread is attached to the Python interpreter and that enables many operations to be\n/// done as efficiently as possible.\n///\n/// However, `#[pyclass]` structs cannot carry a lifetime, so `Py<T>` is the only way to store\n/// a Python object in a `#[pyclass]` struct.\n///\n/// For example, this won't compile:\n///\n/// ```compile_fail\n/// # use pyo3::prelude::*;\n/// # use pyo3::types::PyDict;\n/// #\n/// #[pyclass]\n/// struct Foo<'py> {\n///     inner: Bound<'py, PyDict>,\n/// }\n///\n/// impl Foo {\n///     fn new() -> Foo {\n///         let foo = Python::attach(|py| {\n///             // `py` will only last for this scope.\n///\n///             // `Bound<'py, PyDict>` inherits the Python token lifetime from `py`\n///             // and so won't be able to outlive this closure.\n///             let dict: Bound<'_, PyDict> = PyDict::new(py);\n///\n///             // because `Foo` contains `dict` its lifetime\n///             // is now also tied to `py`.\n///             Foo { inner: dict }\n///         });\n///         // Foo is no longer valid.\n///         // Returning it from this function is a 💥 compiler error 💥\n///         foo\n///     }\n/// }\n/// ```\n///\n/// [`Py`]`<T>` can be used to get around this by removing the lifetime from `dict` and with it the proof of attachment.\n///\n/// ```rust\n/// use pyo3::prelude::*;\n/// use pyo3::types::PyDict;\n///\n/// #[pyclass]\n/// struct Foo {\n///     inner: Py<PyDict>,\n/// }\n///\n/// #[pymethods]\n/// impl Foo {\n///     #[new]\n///     fn __new__() -> Foo {\n///         Python::attach(|py| {\n///             let dict: Py<PyDict> = PyDict::new(py).unbind();\n///             Foo { inner: dict }\n///         })\n///     }\n/// }\n/// #\n/// # fn main() -> PyResult<()> {\n/// #     Python::attach(|py| {\n/// #         let m = pyo3::types::PyModule::new(py, \"test\")?;\n/// #         m.add_class::<Foo>()?;\n/// #\n/// #         let foo: Bound<'_, Foo> = m.getattr(\"Foo\")?.call0()?.cast_into()?;\n/// #         let dict = &foo.borrow().inner;\n/// #         let dict: &Bound<'_, PyDict> = dict.bind(py);\n/// #\n/// #         Ok(())\n/// #     })\n/// # }\n/// ```\n///\n/// This can also be done with other pyclasses:\n/// ```rust\n/// use pyo3::prelude::*;\n///\n/// #[pyclass]\n/// struct Bar {/* ... */}\n///\n/// #[pyclass]\n/// struct Foo {\n///     inner: Py<Bar>,\n/// }\n///\n/// #[pymethods]\n/// impl Foo {\n///     #[new]\n///     fn __new__() -> PyResult<Foo> {\n///         Python::attach(|py| {\n///             let bar: Py<Bar> = Py::new(py, Bar {})?;\n///             Ok(Foo { inner: bar })\n///         })\n///     }\n/// }\n/// #\n/// # fn main() -> PyResult<()> {\n/// #     Python::attach(|py| {\n/// #         let m = pyo3::types::PyModule::new(py, \"test\")?;\n/// #         m.add_class::<Foo>()?;\n/// #\n/// #         let foo: Bound<'_, Foo> = m.getattr(\"Foo\")?.call0()?.cast_into()?;\n/// #         let bar = &foo.borrow().inner;\n/// #         let bar: &Bar = &*bar.borrow(py);\n/// #\n/// #         Ok(())\n/// #     })\n/// # }\n/// ```\n///\n/// # Example: Shared ownership of Python objects\n///\n/// `Py<T>` can be used to share ownership of a Python object, similar to std's [`Rc`]`<T>`.\n/// As with [`Rc`]`<T>`, cloning it increases its reference count rather than duplicating\n/// the underlying object.\n///\n/// This can be done using either [`Py::clone_ref`] or [`Py<T>`]'s [`Clone`] trait implementation.\n/// [`Py::clone_ref`] is recommended; the [`Clone`] implementation will panic if the thread\n/// is not attached to the Python interpreter (and is gated behind the `py-clone` feature flag).\n///\n/// ```rust\n/// use pyo3::prelude::*;\n/// use pyo3::types::PyDict;\n///\n/// # fn main() {\n/// Python::attach(|py| {\n///     let first: Py<PyDict> = PyDict::new(py).unbind();\n///\n///     // All of these are valid syntax\n///     let second = Py::clone_ref(&first, py);\n///     let third = first.clone_ref(py);\n///     #[cfg(feature = \"py-clone\")]\n///     let fourth = Py::clone(&first);\n///     #[cfg(feature = \"py-clone\")]\n///     let fifth = first.clone();\n///\n///     // Disposing of our original `Py<PyDict>` just decrements the reference count.\n///     drop(first);\n///\n///     // They all point to the same object\n///     assert!(second.is(&third));\n///     #[cfg(feature = \"py-clone\")]\n///     assert!(fourth.is(&fifth));\n///     #[cfg(feature = \"py-clone\")]\n///     assert!(second.is(&fourth));\n/// });\n/// # }\n/// ```\n///\n/// # Preventing reference cycles\n///\n/// It is easy to accidentally create reference cycles using [`Py`]`<T>`.\n/// The Python interpreter can break these reference cycles within pyclasses if they\n/// [integrate with the garbage collector][gc]. If your pyclass contains other Python\n/// objects you should implement it to avoid leaking memory.\n///\n/// # A note on Python reference counts\n///\n/// Dropping a [`Py`]`<T>` will eventually decrease Python's reference count\n/// of the pointed-to variable, allowing Python's garbage collector to free\n/// the associated memory, but this may not happen immediately.  This is\n/// because a [`Py`]`<T>` can be dropped at any time, but the Python reference\n/// count can only be modified when the thread is attached to the Python interpreter.\n///\n/// If a [`Py`]`<T>` is dropped while its thread is attached to the Python interpreter\n/// then the Python reference count will be decreased immediately.\n/// Otherwise, the reference count will be decreased the next time the thread is\n/// attached to the interpreter.\n///\n/// If you have a [`Python<'py>`] token, [`Py::drop_ref`] will decrease\n/// the Python reference count immediately and will execute slightly faster than\n/// relying on implicit [`Drop`]s.\n///\n/// # A note on `Send` and `Sync`\n///\n/// [`Py<T>`] implements [`Send`] and [`Sync`], as Python allows objects to be freely\n/// shared between threads.\n///\n/// [`Rc`]: std::rc::Rc\n/// [`RefCell`]: std::cell::RefCell\n/// [gc]: https://pyo3.rs/main/class/protocols.html#garbage-collector-integration\n#[repr(transparent)]\npub struct Py<T>(NonNull<ffi::PyObject>, PhantomData<T>);\n\n#[cfg(feature = \"nightly\")]\nunsafe impl<T> crate::marker::Ungil for Py<T> {}\n// SAFETY: Python objects can be sent between threads\nunsafe impl<T> Send for Py<T> {}\n// SAFETY: Python objects can be shared between threads. Any thread safety is\n// implemented in the object type itself; `Py<T>` only allows synchronized access\n// to `T` through:\n// - `borrow`/`borrow_mut` for `#[pyclass]` types\n// - `get()` for frozen `#[pyclass(frozen)]` types\n// - Python native types have their own thread safety mechanisms\nunsafe impl<T> Sync for Py<T> {}\n\nimpl<T> Py<T>\nwhere\n    T: PyClass,\n{\n    /// Creates a new instance `Py<T>` of a `#[pyclass]` on the Python heap.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyclass]\n    /// struct Foo {/* fields omitted */}\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// let foo = Python::attach(|py| -> PyResult<_> {\n    ///     let foo: Py<Foo> = Py::new(py, Foo {})?;\n    ///     Ok(foo)\n    /// })?;\n    /// # Python::attach(move |_py| drop(foo));\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn new(py: Python<'_>, value: impl Into<PyClassInitializer<T>>) -> PyResult<Py<T>> {\n        Bound::new(py, value).map(Bound::unbind)\n    }\n}\n\nimpl<T> Py<T> {\n    /// Returns the raw FFI pointer represented by self.\n    ///\n    /// # Safety\n    ///\n    /// Callers are responsible for ensuring that the pointer does not outlive self.\n    ///\n    /// The reference is borrowed; callers should not decrease the reference count\n    /// when they are finished with the pointer.\n    #[inline]\n    pub fn as_ptr(&self) -> *mut ffi::PyObject {\n        self.0.as_ptr()\n    }\n\n    /// Returns an owned raw FFI pointer represented by self.\n    ///\n    /// # Safety\n    ///\n    /// The reference is owned; when finished the caller should either transfer ownership\n    /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)).\n    #[inline]\n    pub fn into_ptr(self) -> *mut ffi::PyObject {\n        ManuallyDrop::new(self).0.as_ptr()\n    }\n\n    /// Helper to cast to `Py<PyAny>`.\n    #[inline]\n    pub fn as_any(&self) -> &Py<PyAny> {\n        let ptr = NonNull::from(self).cast();\n        // Safety: all Py<T> have the same memory layout, and all Py<T> are valid\n        // Py<PyAny>, so pointer casting is valid.\n        unsafe { ptr.as_ref() }\n    }\n\n    /// Helper to cast to `Py<PyAny>`, transferring ownership.\n    #[inline]\n    pub fn into_any(self) -> Py<PyAny> {\n        // Safety: all Py<T> are valid Py<PyAny>\n        unsafe { Py::from_non_null(ManuallyDrop::new(self).0) }\n    }\n}\n\nimpl<T> Py<T>\nwhere\n    T: PyClass,\n{\n    /// Immutably borrows the value `T`.\n    ///\n    /// This borrow lasts while the returned [`PyRef`] exists.\n    /// Multiple immutable borrows can be taken out at the same time.\n    ///\n    /// For frozen classes, the simpler [`get`][Self::get] is available.\n    ///\n    /// Equivalent to `self.bind(py).borrow()` - see [`Bound::borrow`].\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// # use pyo3::prelude::*;\n    /// #\n    /// #[pyclass]\n    /// struct Foo {\n    ///     inner: u8,\n    /// }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let foo: Py<Foo> = Py::new(py, Foo { inner: 73 })?;\n    ///     let inner: &u8 = &foo.borrow(py).inner;\n    ///\n    ///     assert_eq!(*inner, 73);\n    ///     Ok(())\n    /// })?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Panics\n    ///\n    /// Panics if the value is currently mutably borrowed. For a non-panicking variant, use\n    /// [`try_borrow`](#method.try_borrow).\n    #[inline]\n    #[track_caller]\n    pub fn borrow<'py>(&'py self, py: Python<'py>) -> PyRef<'py, T> {\n        self.bind(py).borrow()\n    }\n\n    /// Mutably borrows the value `T`.\n    ///\n    /// This borrow lasts while the returned [`PyRefMut`] exists.\n    ///\n    /// Equivalent to `self.bind(py).borrow_mut()` - see [`Bound::borrow_mut`].\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use pyo3::prelude::*;\n    /// #\n    /// #[pyclass]\n    /// struct Foo {\n    ///     inner: u8,\n    /// }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let foo: Py<Foo> = Py::new(py, Foo { inner: 73 })?;\n    ///     foo.borrow_mut(py).inner = 35;\n    ///\n    ///     assert_eq!(foo.borrow(py).inner, 35);\n    ///     Ok(())\n    /// })?;\n    /// # Ok(())\n    /// # }\n    ///  ```\n    ///\n    /// # Panics\n    /// Panics if the value is currently borrowed. For a non-panicking variant, use\n    /// [`try_borrow_mut`](#method.try_borrow_mut).\n    #[inline]\n    #[track_caller]\n    pub fn borrow_mut<'py>(&'py self, py: Python<'py>) -> PyRefMut<'py, T>\n    where\n        T: PyClass<Frozen = False>,\n    {\n        self.bind(py).borrow_mut()\n    }\n\n    /// Attempts to immutably borrow the value `T`, returning an error if the value is currently mutably borrowed.\n    ///\n    /// The borrow lasts while the returned [`PyRef`] exists.\n    ///\n    /// This is the non-panicking variant of [`borrow`](#method.borrow).\n    ///\n    /// For frozen classes, the simpler [`get`][Self::get] is available.\n    ///\n    /// Equivalent to `self.bind(py).try_borrow()` - see [`Bound::try_borrow`].\n    #[inline]\n    pub fn try_borrow<'py>(&'py self, py: Python<'py>) -> Result<PyRef<'py, T>, PyBorrowError> {\n        self.bind(py).try_borrow()\n    }\n\n    /// Attempts to mutably borrow the value `T`, returning an error if the value is currently borrowed.\n    ///\n    /// The borrow lasts while the returned [`PyRefMut`] exists.\n    ///\n    /// This is the non-panicking variant of [`borrow_mut`](#method.borrow_mut).\n    ///\n    /// Equivalent to `self.bind(py).try_borrow_mut()` - see [`Bound::try_borrow_mut`].\n    #[inline]\n    pub fn try_borrow_mut<'py>(\n        &'py self,\n        py: Python<'py>,\n    ) -> Result<PyRefMut<'py, T>, PyBorrowMutError>\n    where\n        T: PyClass<Frozen = False>,\n    {\n        self.bind(py).try_borrow_mut()\n    }\n\n    /// Provide an immutable borrow of the value `T`.\n    ///\n    /// This is available if the class is [`frozen`][macro@crate::pyclass] and [`Sync`], and\n    /// does not require attaching to the Python interpreter.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use std::sync::atomic::{AtomicUsize, Ordering};\n    /// # use pyo3::prelude::*;\n    ///\n    /// #[pyclass(frozen)]\n    /// struct FrozenCounter {\n    ///     value: AtomicUsize,\n    /// }\n    ///\n    /// let cell  = Python::attach(|py| {\n    ///     let counter = FrozenCounter { value: AtomicUsize::new(0) };\n    ///\n    ///     Py::new(py, counter).unwrap()\n    /// });\n    ///\n    /// cell.get().value.fetch_add(1, Ordering::Relaxed);\n    /// # Python::attach(move |_py| drop(cell));\n    /// ```\n    #[inline]\n    pub fn get(&self) -> &T\n    where\n        T: PyClass<Frozen = True> + Sync,\n    {\n        // Safety: The class itself is frozen and `Sync`\n        unsafe { &*self.get_class_object().get_ptr() }\n    }\n\n    /// Get a view on the underlying `PyClass` contents.\n    #[inline]\n    pub(crate) fn get_class_object(&self) -> &<T as PyClassImpl>::Layout {\n        let class_object = self.as_ptr().cast::<<T as PyClassImpl>::Layout>();\n        // Safety: Bound<T: PyClass> is known to contain an object which is laid out in memory as a\n        // <T as PyClassImpl>::Layout object\n        unsafe { &*class_object }\n    }\n}\n\nimpl<T> Py<T> {\n    /// Attaches this `Py` to the given Python context, allowing access to further Python APIs.\n    #[inline]\n    pub fn bind<'py>(&self, _py: Python<'py>) -> &Bound<'py, T> {\n        // SAFETY: `Bound` has the same layout as `Py`\n        unsafe { NonNull::from(self).cast().as_ref() }\n    }\n\n    /// Same as `bind` but takes ownership of `self`.\n    #[inline]\n    pub fn into_bound(self, py: Python<'_>) -> Bound<'_, T> {\n        Bound(py, ManuallyDrop::new(self))\n    }\n\n    /// Same as `bind` but produces a `Borrowed<T>` instead of a `Bound<T>`.\n    #[inline]\n    pub fn bind_borrowed<'a, 'py>(&'a self, py: Python<'py>) -> Borrowed<'a, 'py, T> {\n        // NB cannot go via `self.bind(py)` because the `&Bound` would imply `'a: 'py`\n\n        // SAFETY: `self.0` is a valid pointer to a PyObject for the lifetime 'a\n        let borrowed = unsafe { Borrowed::from_non_null(py, self.0) };\n        // SAFETY: object is known to be of type T\n        unsafe { borrowed.cast_unchecked() }\n    }\n\n    /// Returns whether `self` and `other` point to the same object. To compare\n    /// the equality of two objects (the `==` operator), use [`eq`](PyAnyMethods::eq).\n    ///\n    /// This is equivalent to the Python expression `self is other`.\n    #[inline]\n    pub fn is<U: AsRef<Py<PyAny>>>(&self, o: U) -> bool {\n        ptr::eq(self.as_ptr(), o.as_ref().as_ptr())\n    }\n\n    /// Gets the reference count of the `ffi::PyObject` pointer.\n    #[inline]\n    #[deprecated(\n        since = \"0.29.0\",\n        note = \"use `pyo3::ffi::Py_REFCNT(obj.as_ptr())` instead\"\n    )]\n    pub fn get_refcnt(&self, py: Python<'_>) -> isize {\n        self._get_refcnt(py)\n    }\n\n    #[inline]\n    pub(crate) fn _get_refcnt(&self, _py: Python<'_>) -> isize {\n        // SAFETY: Self is a valid pointer to a PyObject\n        unsafe { ffi::Py_REFCNT(self.0.as_ptr()) }\n    }\n\n    /// Makes a clone of `self`.\n    ///\n    /// This creates another pointer to the same object, increasing its reference count.\n    ///\n    /// You should prefer using this method over [`Clone`].\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyDict;\n    ///\n    /// # fn main() {\n    /// Python::attach(|py| {\n    ///     let first: Py<PyDict> = PyDict::new(py).unbind();\n    ///     let second = Py::clone_ref(&first, py);\n    ///\n    ///     // Both point to the same object\n    ///     assert!(first.is(&second));\n    /// });\n    /// # }\n    /// ```\n    #[inline]\n    pub fn clone_ref(&self, _py: Python<'_>) -> Py<T> {\n        // NB cannot use self.bind(py) because Bound::clone is implemented using Py::clone_ref\n        // (infinite recursion)\n\n        // SAFETY: object is known to be valid\n        unsafe { ffi::Py_INCREF(self.0.as_ptr()) };\n        // SAFETY: newly created reference is transferred to the new Py<T>\n        unsafe { Self::from_non_null(self.0) }\n    }\n\n    /// Drops `self` and immediately decreases its reference count.\n    ///\n    /// This method is a micro-optimisation over [`Drop`] if you happen to have a [`Python<'py>`]\n    /// token to prove attachment to the Python interpreter.\n    ///\n    /// Note that if you are using [`Bound`], you do not need to use [`Self::drop_ref`] since\n    /// [`Bound`] guarantees that the thread is attached to the interpreter.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyDict;\n    ///\n    /// # fn main() {\n    /// Python::attach(|py| {\n    ///     let object: Py<PyDict> = PyDict::new(py).unbind();\n    ///\n    ///     // some usage of object\n    ///\n    ///     object.drop_ref(py);\n    /// });\n    /// # }\n    /// ```\n    #[inline]\n    pub fn drop_ref(self, py: Python<'_>) {\n        let _ = self.into_bound(py);\n    }\n\n    /// Returns whether the object is considered to be None.\n    ///\n    /// This is equivalent to the Python expression `self is None`.\n    pub fn is_none(&self, py: Python<'_>) -> bool {\n        self.bind(py).as_any().is_none()\n    }\n\n    /// Returns whether the object is considered to be true.\n    ///\n    /// This applies truth value testing equivalent to the Python expression `bool(self)`.\n    pub fn is_truthy(&self, py: Python<'_>) -> PyResult<bool> {\n        self.bind(py).as_any().is_truthy()\n    }\n\n    /// Extracts some type from the Python object.\n    ///\n    /// This is a wrapper function around `FromPyObject::extract()`.\n    pub fn extract<'a, 'py, D>(&'a self, py: Python<'py>) -> Result<D, D::Error>\n    where\n        D: FromPyObject<'a, 'py>,\n    {\n        self.bind_borrowed(py).extract()\n    }\n\n    /// Retrieves an attribute value.\n    ///\n    /// This is equivalent to the Python expression `self.attr_name`.\n    ///\n    /// If calling this method becomes performance-critical, the [`intern!`](crate::intern) macro\n    /// can be used to intern `attr_name`, thereby avoiding repeated temporary allocations of\n    /// Python strings.\n    ///\n    /// # Example: `intern!`ing the attribute name\n    ///\n    /// ```\n    /// # use pyo3::{prelude::*, intern};\n    /// #\n    /// #[pyfunction]\n    /// fn version(sys: Py<PyModule>, py: Python<'_>) -> PyResult<Py<PyAny>> {\n    ///     sys.getattr(py, intern!(py, \"version\"))\n    /// }\n    /// #\n    /// # Python::attach(|py| {\n    /// #    let sys = py.import(\"sys\").unwrap().unbind();\n    /// #    version(sys, py).unwrap();\n    /// # });\n    /// ```\n    pub fn getattr<'py, N>(&self, py: Python<'py>, attr_name: N) -> PyResult<Py<PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n    {\n        self.bind(py).as_any().getattr(attr_name).map(Bound::unbind)\n    }\n\n    /// Sets an attribute value.\n    ///\n    /// This is equivalent to the Python expression `self.attr_name = value`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern)\n    /// macro can be used to intern `attr_name`.\n    ///\n    /// # Example: `intern!`ing the attribute name\n    ///\n    /// ```\n    /// # use pyo3::{intern, pyfunction, types::PyModule, IntoPyObjectExt, Py, PyAny, Python, PyResult};\n    /// #\n    /// #[pyfunction]\n    /// fn set_answer(ob: Py<PyAny>, py: Python<'_>) -> PyResult<()> {\n    ///     ob.setattr(py, intern!(py, \"answer\"), 42)\n    /// }\n    /// #\n    /// # Python::attach(|py| {\n    /// #    let ob = PyModule::new(py, \"empty\").unwrap().into_py_any(py).unwrap();\n    /// #    set_answer(ob, py).unwrap();\n    /// # });\n    /// ```\n    pub fn setattr<'py, N, V>(&self, py: Python<'py>, attr_name: N, value: V) -> PyResult<()>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n        V: IntoPyObject<'py>,\n    {\n        self.bind(py).as_any().setattr(attr_name, value)\n    }\n\n    /// Calls the object.\n    ///\n    /// This is equivalent to the Python expression `self(*args, **kwargs)`.\n    pub fn call<'py, A>(\n        &self,\n        py: Python<'py>,\n        args: A,\n        kwargs: Option<&Bound<'py, PyDict>>,\n    ) -> PyResult<Py<PyAny>>\n    where\n        A: PyCallArgs<'py>,\n    {\n        self.bind(py).as_any().call(args, kwargs).map(Bound::unbind)\n    }\n\n    /// Calls the object with only positional arguments.\n    ///\n    /// This is equivalent to the Python expression `self(*args)`.\n    pub fn call1<'py, A>(&self, py: Python<'py>, args: A) -> PyResult<Py<PyAny>>\n    where\n        A: PyCallArgs<'py>,\n    {\n        self.bind(py).as_any().call1(args).map(Bound::unbind)\n    }\n\n    /// Calls the object without arguments.\n    ///\n    /// This is equivalent to the Python expression `self()`.\n    pub fn call0(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {\n        self.bind(py).as_any().call0().map(Bound::unbind)\n    }\n\n    /// Calls a method on the object.\n    ///\n    /// This is equivalent to the Python expression `self.name(*args, **kwargs)`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern)\n    /// macro can be used to intern `name`.\n    pub fn call_method<'py, N, A>(\n        &self,\n        py: Python<'py>,\n        name: N,\n        args: A,\n        kwargs: Option<&Bound<'py, PyDict>>,\n    ) -> PyResult<Py<PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n        A: PyCallArgs<'py>,\n    {\n        self.bind(py)\n            .as_any()\n            .call_method(name, args, kwargs)\n            .map(Bound::unbind)\n    }\n\n    /// Calls a method on the object with only positional arguments.\n    ///\n    /// This is equivalent to the Python expression `self.name(*args)`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern)\n    /// macro can be used to intern `name`.\n    pub fn call_method1<'py, N, A>(&self, py: Python<'py>, name: N, args: A) -> PyResult<Py<PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n        A: PyCallArgs<'py>,\n    {\n        self.bind(py)\n            .as_any()\n            .call_method1(name, args)\n            .map(Bound::unbind)\n    }\n\n    /// Calls a method on the object with no arguments.\n    ///\n    /// This is equivalent to the Python expression `self.name()`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`](crate::intern)\n    /// macro can be used to intern `name`.\n    pub fn call_method0<'py, N>(&self, py: Python<'py>, name: N) -> PyResult<Py<PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n    {\n        self.bind(py).as_any().call_method0(name).map(Bound::unbind)\n    }\n\n    /// Create a `Py<T>` instance by taking ownership of the given FFI pointer.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object (or null, which will cause a panic)\n    /// - `ptr` must be an owned Python reference, as the `Py<T>` will assume ownership\n    ///\n    /// # Panics\n    ///\n    /// Panics if `ptr` is null.\n    #[inline]\n    #[track_caller]\n    #[deprecated(note = \"use `Bound::from_owned_ptr` instead\", since = \"0.28.0\")]\n    pub unsafe fn from_owned_ptr(py: Python<'_>, ptr: *mut ffi::PyObject) -> Py<T> {\n        match NonNull::new(ptr) {\n            Some(nonnull_ptr) => {\n                // SAFETY: caller has upheld the safety contract, ptr is known to be non-null\n                unsafe { Self::from_non_null(nonnull_ptr) }\n            }\n            None => panic_on_null(py),\n        }\n    }\n\n    /// Create a `Py<T>` instance by taking ownership of the given FFI pointer.\n    ///\n    /// If `ptr` is null then the current Python exception is fetched as a [`PyErr`].\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object, or null\n    /// - a non-null `ptr` must be an owned Python reference, as the `Py<T>` will assume ownership\n    #[inline]\n    #[deprecated(note = \"use `Bound::from_owned_ptr_or_err` instead\", since = \"0.28.0\")]\n    pub unsafe fn from_owned_ptr_or_err(\n        py: Python<'_>,\n        ptr: *mut ffi::PyObject,\n    ) -> PyResult<Py<T>> {\n        match NonNull::new(ptr) {\n            Some(nonnull_ptr) => Ok(\n                // SAFETY: caller has upheld the safety contract, ptr is known to be non-null\n                unsafe { Self::from_non_null(nonnull_ptr) },\n            ),\n            None => Err(PyErr::fetch(py)),\n        }\n    }\n\n    /// Create a `Py<T>` instance by taking ownership of the given FFI pointer.\n    ///\n    /// If `ptr` is null then `None` is returned.\n    ///\n    /// # Safety\n    ///\n    /// - `ptr` must be a valid pointer to a Python object, or null\n    /// - a non-null `ptr` must be an owned Python reference, as the `Py<T>` will assume ownership\n    #[inline]\n    #[deprecated(note = \"use `Bound::from_owned_ptr_or_opt` instead\", since = \"0.28.0\")]\n    pub unsafe fn from_owned_ptr_or_opt(_py: Python<'_>, ptr: *mut ffi::PyObject) -> Option<Self> {\n        NonNull::new(ptr).map(|nonnull_ptr| {\n            // SAFETY: caller has upheld the safety contract\n            unsafe { Self::from_non_null(nonnull_ptr) }\n        })\n    }\n\n    /// Create a `Py<T>` instance by creating a new reference from the given FFI pointer.\n    ///\n    /// # Safety\n    /// `ptr` must be a pointer to a Python object of type T.\n    ///\n    /// # Panics\n    ///\n    /// Panics if `ptr` is null.\n    #[inline]\n    #[track_caller]\n    #[deprecated(note = \"use `Borrowed::from_borrowed_ptr` instead\", since = \"0.28.0\")]\n    pub unsafe fn from_borrowed_ptr(py: Python<'_>, ptr: *mut ffi::PyObject) -> Py<T> {\n        // SAFETY: caller has upheld the safety contract\n        #[allow(deprecated)]\n        unsafe { Self::from_borrowed_ptr_or_opt(py, ptr) }.unwrap_or_else(|| panic_on_null(py))\n    }\n\n    /// Create a `Py<T>` instance by creating a new reference from the given FFI pointer.\n    ///\n    /// If `ptr` is null then the current Python exception is fetched as a `PyErr`.\n    ///\n    /// # Safety\n    /// `ptr` must be a pointer to a Python object of type T.\n    #[inline]\n    #[deprecated(\n        note = \"use `Borrowed::from_borrowed_ptr_or_err` instead\",\n        since = \"0.28.0\"\n    )]\n    pub unsafe fn from_borrowed_ptr_or_err(\n        py: Python<'_>,\n        ptr: *mut ffi::PyObject,\n    ) -> PyResult<Self> {\n        // SAFETY: caller has upheld the safety contract\n        #[allow(deprecated)]\n        unsafe { Self::from_borrowed_ptr_or_opt(py, ptr) }.ok_or_else(|| PyErr::fetch(py))\n    }\n\n    /// Create a `Py<T>` instance by creating a new reference from the given FFI pointer.\n    ///\n    /// If `ptr` is null then `None` is returned.\n    ///\n    /// # Safety\n    /// `ptr` must be a pointer to a Python object of type T, or null.\n    #[inline]\n    #[deprecated(\n        note = \"use `Borrowed::from_borrowed_ptr_or_opt` instead\",\n        since = \"0.28.0\"\n    )]\n    pub unsafe fn from_borrowed_ptr_or_opt(\n        _py: Python<'_>,\n        ptr: *mut ffi::PyObject,\n    ) -> Option<Self> {\n        NonNull::new(ptr).map(|nonnull_ptr| {\n            // SAFETY: ptr is a valid python object, thread is attached to the interpreter\n            unsafe { ffi::Py_INCREF(ptr) };\n            // SAFETY: caller has upheld the safety contract, and object was just made owned\n            unsafe { Self::from_non_null(nonnull_ptr) }\n        })\n    }\n\n    /// For internal conversions.\n    ///\n    /// # Safety\n    ///\n    /// `ptr` must point to an owned Python object type T.\n    #[inline(always)]\n    unsafe fn from_non_null(ptr: NonNull<ffi::PyObject>) -> Self {\n        Self(ptr, PhantomData)\n    }\n\n    /// As with `from_non_null`, while calling incref.\n    ///\n    /// # Safety\n    ///\n    /// `ptr` must point to a valid Python object type T.\n    #[inline(always)]\n    unsafe fn from_borrowed_non_null(_py: Python<'_>, ptr: NonNull<ffi::PyObject>) -> Self {\n        // SAFETY: caller has upheld the safety contract, thread is attached to the interpreter\n        unsafe { ffi::Py_INCREF(ptr.as_ptr()) };\n        // SAFETY: caller has upheld the safety contract\n        unsafe { Self::from_non_null(ptr) }\n    }\n}\n\nimpl<T> AsRef<Py<PyAny>> for Py<T> {\n    #[inline]\n    fn as_ref(&self) -> &Py<PyAny> {\n        self.as_any()\n    }\n}\n\nimpl<T> std::convert::From<Py<T>> for Py<PyAny>\nwhere\n    T: DerefToPyAny,\n{\n    #[inline]\n    fn from(other: Py<T>) -> Self {\n        other.into_any()\n    }\n}\n\nimpl<T> std::convert::From<Bound<'_, T>> for Py<PyAny>\nwhere\n    T: DerefToPyAny,\n{\n    #[inline]\n    fn from(other: Bound<'_, T>) -> Self {\n        other.into_any().unbind()\n    }\n}\n\nimpl<T> std::convert::From<Bound<'_, T>> for Py<T> {\n    #[inline]\n    fn from(other: Bound<'_, T>) -> Self {\n        other.unbind()\n    }\n}\n\nimpl<T> std::convert::From<Borrowed<'_, '_, T>> for Py<T> {\n    fn from(value: Borrowed<'_, '_, T>) -> Self {\n        value.unbind()\n    }\n}\n\nimpl<'py, T> std::convert::From<PyRef<'py, T>> for Py<T>\nwhere\n    T: PyClass,\n{\n    fn from(pyref: PyRef<'py, T>) -> Self {\n        // SAFETY: PyRef::as_ptr returns a borrowed reference to a valid object of type T\n        unsafe { Bound::from_borrowed_ptr(pyref.py(), pyref.as_ptr()).cast_into_unchecked() }\n            .unbind()\n    }\n}\n\nimpl<'py, T> std::convert::From<PyRefMut<'py, T>> for Py<T>\nwhere\n    T: PyClass<Frozen = False>,\n{\n    fn from(pyref: PyRefMut<'py, T>) -> Self {\n        // SAFETY: PyRefMut::as_ptr returns a borrowed reference to a valid object of type T\n        unsafe { Bound::from_borrowed_ptr(pyref.py(), pyref.as_ptr()).cast_into_unchecked() }\n            .unbind()\n    }\n}\n\n/// If the thread is attached to the Python interpreter this increments `self`'s reference count.\n/// Otherwise, it will panic.\n///\n/// Only available if the `py-clone` feature is enabled.\n#[cfg(feature = \"py-clone\")]\nimpl<T> Clone for Py<T> {\n    #[track_caller]\n    #[inline]\n    fn clone(&self) -> Self {\n        #[track_caller]\n        #[inline]\n        fn try_incref(obj: NonNull<ffi::PyObject>) {\n            use crate::internal::state::thread_is_attached;\n\n            if thread_is_attached() {\n                // SAFETY: Py_INCREF is safe to call on a valid Python object if the thread is attached.\n                unsafe { ffi::Py_INCREF(obj.as_ptr()) }\n            } else {\n                incref_failed()\n            }\n        }\n\n        #[cold]\n        #[track_caller]\n        fn incref_failed() -> ! {\n            panic!(\"Cannot clone pointer into Python heap without the thread being attached.\");\n        }\n\n        try_incref(self.0);\n\n        Self(self.0, PhantomData)\n    }\n}\n\n/// Dropping a `Py` instance decrements the reference count\n/// on the object by one if the thread is attached to the Python interpreter.\n///\n/// Otherwise and by default, this registers the underlying pointer to have its reference count\n/// decremented the next time PyO3 attaches to the Python interpreter.\n///\n/// However, if the `pyo3_disable_reference_pool` conditional compilation flag\n/// is enabled, it will abort the process.\nimpl<T> Drop for Py<T> {\n    #[inline]\n    fn drop(&mut self) {\n        // non generic inlineable inner function to reduce code bloat\n        #[inline]\n        fn inner(obj: NonNull<ffi::PyObject>) {\n            use crate::internal::state::thread_is_attached;\n\n            if thread_is_attached() {\n                // SAFETY: Py_DECREF is safe to call on a valid Python object if the thread is attached.\n                unsafe { ffi::Py_DECREF(obj.as_ptr()) }\n            } else {\n                drop_slow(obj)\n            }\n        }\n\n        #[cold]\n        fn drop_slow(obj: NonNull<ffi::PyObject>) {\n            // SAFETY: handing ownership of the reference to `register_decref`.\n            unsafe {\n                state::register_decref(obj);\n            }\n        }\n\n        inner(self.0)\n    }\n}\n\nimpl<'a, 'py, T> FromPyObject<'a, 'py> for Py<T>\nwhere\n    T: PyTypeCheck + 'a,\n{\n    type Error = CastError<'a, 'py>;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    /// Extracts `Self` from the source `PyObject`.\n    fn extract(ob: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        ob.extract::<Bound<'py, T>>().map(Bound::unbind)\n    }\n}\n\nimpl<'a, 'py, T> FromPyObject<'a, 'py> for Bound<'py, T>\nwhere\n    T: PyTypeCheck + 'a,\n{\n    type Error = CastError<'a, 'py>;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    /// Extracts `Self` from the source `PyObject`.\n    fn extract(ob: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        ob.cast().map(Borrowed::to_owned)\n    }\n}\n\nimpl<T> std::fmt::Display for Py<T>\nwhere\n    T: PyTypeInfo,\n{\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        Python::attach(|py| std::fmt::Display::fmt(self.bind(py), f))\n    }\n}\n\nimpl<T> std::fmt::Debug for Py<T> {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.debug_tuple(\"Py\").field(&self.0.as_ptr()).finish()\n    }\n}\n\nimpl Py<PyAny> {\n    /// Downcast this `Py<PyAny>` to a concrete Python type or pyclass.\n    ///\n    /// Note that you can often avoid casting yourself by just specifying the desired type in\n    /// function or method signatures. However, manual casting is sometimes necessary.\n    ///\n    /// For extracting a Rust-only type, see [`Py::extract`].\n    ///\n    ///  # Example: Downcasting to a specific Python object\n    ///\n    /// ```rust\n    /// # #![allow(deprecated)]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::{PyDict, PyList};\n    ///\n    /// Python::attach(|py| {\n    ///     let any = PyDict::new(py).into_any().unbind();\n    ///\n    ///     assert!(any.downcast_bound::<PyDict>(py).is_ok());\n    ///     assert!(any.downcast_bound::<PyList>(py).is_err());\n    /// });\n    /// ```\n    ///\n    /// # Example: Getting a reference to a pyclass\n    ///\n    /// This is useful if you want to mutate a `Py<PyAny>` that might actually be a pyclass.\n    ///\n    /// ```rust\n    /// # #![allow(deprecated)]\n    /// # fn main() -> Result<(), pyo3::PyErr> {\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyclass]\n    /// struct Class {\n    ///     i: i32,\n    /// }\n    ///\n    /// Python::attach(|py| {\n    ///     let class = Py::new(py, Class { i: 0 })?.into_any();\n    ///\n    ///     let class_bound = class.downcast_bound::<Class>(py)?;\n    ///\n    ///     class_bound.borrow_mut().i += 1;\n    ///\n    ///     // Alternatively you can get a `PyRefMut` directly\n    ///     let class_ref: PyRefMut<'_, Class> = class.extract(py)?;\n    ///     assert_eq!(class_ref.i, 1);\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    #[deprecated(since = \"0.27.0\", note = \"use `Py::cast_bound` instead\")]\n    #[inline]\n    #[allow(deprecated)]\n    pub fn downcast_bound<'py, T>(\n        &self,\n        py: Python<'py>,\n    ) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>>\n    where\n        T: PyTypeCheck,\n    {\n        #[allow(deprecated)]\n        self.bind(py).downcast()\n    }\n\n    /// Casts the `Py<PyAny>` to a concrete Python object type without checking validity.\n    ///\n    /// # Safety\n    ///\n    /// Callers must ensure that the type is valid or risk type confusion.\n    #[deprecated(since = \"0.27.0\", note = \"use `Py::cast_bound_unchecked` instead\")]\n    #[inline]\n    pub unsafe fn downcast_bound_unchecked<'py, T>(&self, py: Python<'py>) -> &Bound<'py, T> {\n        // SAFETY: caller has upheld the safety contract\n        unsafe { self.cast_bound_unchecked(py) }\n    }\n}\n\nimpl<T> Py<T> {\n    /// Cast this `Py<T>` to a concrete Python type or pyclass.\n    ///\n    /// Note that you can often avoid casting yourself by just specifying the desired type in\n    /// function or method signatures. However, manual casting is sometimes necessary.\n    ///\n    /// For extracting a Rust-only type, see [`Py::extract`].\n    ///\n    /// # Example: Casting to a specific Python object\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::{PyDict, PyList};\n    ///\n    /// Python::attach(|py| {\n    ///     let any = PyDict::new(py).into_any().unbind();\n    ///\n    ///     assert!(any.cast_bound::<PyDict>(py).is_ok());\n    ///     assert!(any.cast_bound::<PyList>(py).is_err());\n    /// });\n    /// ```\n    ///\n    /// # Example: Getting a reference to a pyclass\n    ///\n    /// This is useful if you want to mutate a `Py<PyAny>` that might actually be a pyclass.\n    ///\n    /// ```rust\n    /// # fn main() -> Result<(), pyo3::PyErr> {\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyclass]\n    /// struct Class {\n    ///     i: i32,\n    /// }\n    ///\n    /// Python::attach(|py| {\n    ///     let class = Py::new(py, Class { i: 0 })?.into_any();\n    ///\n    ///     let class_bound = class.cast_bound::<Class>(py)?;\n    ///\n    ///     class_bound.borrow_mut().i += 1;\n    ///\n    ///     // Alternatively you can get a `PyRefMut` directly\n    ///     let class_ref: PyRefMut<'_, Class> = class.extract(py)?;\n    ///     assert_eq!(class_ref.i, 1);\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    pub fn cast_bound<'py, U>(&self, py: Python<'py>) -> Result<&Bound<'py, U>, CastError<'_, 'py>>\n    where\n        U: PyTypeCheck,\n    {\n        self.bind(py).cast()\n    }\n\n    /// Casts the `Py<T>` to a concrete Python object type without checking validity.\n    ///\n    /// # Safety\n    ///\n    /// Callers must ensure that the type is valid or risk type confusion.\n    #[inline]\n    pub unsafe fn cast_bound_unchecked<'py, U>(&self, py: Python<'py>) -> &Bound<'py, U> {\n        // Safety: caller has upheld the safety contract\n        unsafe { self.bind(py).cast_unchecked() }\n    }\n}\n\n#[track_caller]\n#[cold]\nfn panic_on_null(py: Python<'_>) -> ! {\n    if let Some(err) = PyErr::take(py) {\n        err.write_unraisable(py, None);\n    }\n    panic!(\"PyObject pointer is null\");\n}\n\n#[cfg(test)]\nmod tests {\n    use super::{Bound, IntoPyObject, Py};\n    #[cfg(all(feature = \"macros\", Py_3_8, panic = \"unwind\"))]\n    use crate::exceptions::PyValueError;\n    use crate::test_utils::generate_unique_module_name;\n    #[cfg(all(feature = \"macros\", Py_3_8, panic = \"unwind\"))]\n    use crate::test_utils::UnraisableCapture;\n    use crate::types::{dict::IntoPyDict, PyAnyMethods, PyCapsule, PyDict, PyString};\n    use crate::{ffi, Borrowed, IntoPyObjectExt, PyAny, PyResult, Python};\n    use std::ffi::CStr;\n\n    #[test]\n    fn test_call() {\n        Python::attach(|py| {\n            let obj = py.get_type::<PyDict>().into_pyobject(py).unwrap();\n\n            let assert_repr = |obj: Bound<'_, PyAny>, expected: &str| {\n                assert_eq!(obj.repr().unwrap(), expected);\n            };\n\n            assert_repr(obj.call0().unwrap(), \"{}\");\n            assert_repr(obj.call1(()).unwrap(), \"{}\");\n            assert_repr(obj.call((), None).unwrap(), \"{}\");\n\n            assert_repr(obj.call1(((('x', 1),),)).unwrap(), \"{'x': 1}\");\n            assert_repr(\n                obj.call((), Some(&[('x', 1)].into_py_dict(py).unwrap()))\n                    .unwrap(),\n                \"{'x': 1}\",\n            );\n        })\n    }\n\n    #[test]\n    fn test_call_tuple_ref() {\n        let assert_repr = |obj: &Bound<'_, PyAny>, expected: &str| {\n            use crate::prelude::PyStringMethods;\n            assert_eq!(\n                obj.repr()\n                    .unwrap()\n                    .to_cow()\n                    .unwrap()\n                    .trim_matches(|c| c == '{' || c == '}'),\n                expected.trim_matches(|c| c == ',' || c == ' ')\n            );\n        };\n\n        macro_rules! tuple {\n            ($py:ident, $($key: literal => $value: literal),+) => {\n                let ty_obj = $py.get_type::<PyDict>().into_pyobject($py).unwrap();\n                assert!(ty_obj.call1(&(($(($key),)+),)).is_err());\n                let obj = ty_obj.call1(&(($(($key, i32::from($value)),)+),)).unwrap();\n                assert_repr(&obj, concat!($(\"'\", $key, \"'\", \": \", stringify!($value), \", \",)+));\n                assert!(obj.call_method1(\"update\", &(($(($key),)+),)).is_err());\n                obj.call_method1(\"update\", &(($((i32::from($value), $key),)+),)).unwrap();\n                assert_repr(&obj, concat!(\n                    concat!($(\"'\", $key, \"'\", \": \", stringify!($value), \", \",)+),\n                    concat!($(stringify!($value), \": \", \"'\", $key, \"'\", \", \",)+)\n                ));\n            };\n        }\n\n        Python::attach(|py| {\n            tuple!(py, \"a\" => 1);\n            tuple!(py, \"a\" => 1, \"b\" => 2);\n            tuple!(py, \"a\" => 1, \"b\" => 2, \"c\" => 3);\n            tuple!(py, \"a\" => 1, \"b\" => 2, \"c\" => 3, \"d\" => 4);\n            tuple!(py, \"a\" => 1, \"b\" => 2, \"c\" => 3, \"d\" => 4, \"e\" => 5);\n            tuple!(py, \"a\" => 1, \"b\" => 2, \"c\" => 3, \"d\" => 4, \"e\" => 5, \"f\" => 6);\n            tuple!(py, \"a\" => 1, \"b\" => 2, \"c\" => 3, \"d\" => 4, \"e\" => 5, \"f\" => 6, \"g\" => 7);\n            tuple!(py, \"a\" => 1, \"b\" => 2, \"c\" => 3, \"d\" => 4, \"e\" => 5, \"f\" => 6, \"g\" => 7, \"h\" => 8);\n            tuple!(py, \"a\" => 1, \"b\" => 2, \"c\" => 3, \"d\" => 4, \"e\" => 5, \"f\" => 6, \"g\" => 7, \"h\" => 8, \"i\" => 9);\n            tuple!(py, \"a\" => 1, \"b\" => 2, \"c\" => 3, \"d\" => 4, \"e\" => 5, \"f\" => 6, \"g\" => 7, \"h\" => 8, \"i\" => 9, \"j\" => 10, \"k\" => 11);\n            tuple!(py, \"a\" => 1, \"b\" => 2, \"c\" => 3, \"d\" => 4, \"e\" => 5, \"f\" => 6, \"g\" => 7, \"h\" => 8, \"i\" => 9, \"j\" => 10, \"k\" => 11, \"l\" => 12);\n        })\n    }\n\n    #[test]\n    fn test_call_for_non_existing_method() {\n        Python::attach(|py| {\n            let obj: Py<PyAny> = PyDict::new(py).into();\n            assert!(obj.call_method0(py, \"asdf\").is_err());\n            assert!(obj\n                .call_method(py, \"nonexistent_method\", (1,), None)\n                .is_err());\n            assert!(obj.call_method0(py, \"nonexistent_method\").is_err());\n            assert!(obj.call_method1(py, \"nonexistent_method\", (1,)).is_err());\n        });\n    }\n\n    #[test]\n    fn py_from_dict() {\n        let dict: Py<PyDict> = Python::attach(|py| {\n            let native = PyDict::new(py);\n            Py::from(native)\n        });\n\n        Python::attach(move |py| {\n            assert_eq!(dict._get_refcnt(py), 1);\n        });\n    }\n\n    #[test]\n    fn pyobject_from_py() {\n        Python::attach(|py| {\n            let dict: Py<PyDict> = PyDict::new(py).unbind();\n            let cnt = dict._get_refcnt(py);\n            let p: Py<PyAny> = dict.into();\n            assert_eq!(p._get_refcnt(py), cnt);\n        });\n    }\n\n    #[test]\n    fn attr() -> PyResult<()> {\n        use crate::types::PyModule;\n\n        Python::attach(|py| {\n            const CODE: &CStr = cr#\"\nclass A:\n    pass\na = A()\n   \"#;\n            let module = PyModule::from_code(py, CODE, c\"\", &generate_unique_module_name(\"\"))?;\n            let instance: Py<PyAny> = module.getattr(\"a\")?.into();\n\n            instance.getattr(py, \"foo\").unwrap_err();\n\n            instance.setattr(py, \"foo\", \"bar\")?;\n\n            assert!(instance\n                .getattr(py, \"foo\")?\n                .bind(py)\n                .eq(PyString::new(py, \"bar\"))?);\n\n            instance.getattr(py, \"foo\")?;\n            Ok(())\n        })\n    }\n\n    #[test]\n    fn pystring_attr() -> PyResult<()> {\n        use crate::types::PyModule;\n\n        Python::attach(|py| {\n            const CODE: &CStr = cr#\"\nclass A:\n    pass\na = A()\n   \"#;\n            let module = PyModule::from_code(py, CODE, c\"\", &generate_unique_module_name(\"\"))?;\n            let instance: Py<PyAny> = module.getattr(\"a\")?.into();\n\n            let foo = crate::intern!(py, \"foo\");\n            let bar = crate::intern!(py, \"bar\");\n\n            instance.getattr(py, foo).unwrap_err();\n            instance.setattr(py, foo, bar)?;\n            assert!(instance.getattr(py, foo)?.bind(py).eq(bar)?);\n            Ok(())\n        })\n    }\n\n    #[test]\n    fn invalid_attr() -> PyResult<()> {\n        Python::attach(|py| {\n            let instance: Py<PyAny> = py.eval(c\"object()\", None, None)?.into();\n\n            instance.getattr(py, \"foo\").unwrap_err();\n\n            // Cannot assign arbitrary attributes to `object`\n            instance.setattr(py, \"foo\", \"bar\").unwrap_err();\n            Ok(())\n        })\n    }\n\n    #[test]\n    fn test_py2_from_py_object() {\n        Python::attach(|py| {\n            let instance = py.eval(c\"object()\", None, None).unwrap();\n            let ptr = instance.as_ptr();\n            let instance: Bound<'_, PyAny> = instance.extract().unwrap();\n            assert_eq!(instance.as_ptr(), ptr);\n        })\n    }\n\n    #[test]\n    fn test_py2_into_py_object() {\n        Python::attach(|py| {\n            let instance = py.eval(c\"object()\", None, None).unwrap();\n            let ptr = instance.as_ptr();\n            let instance: Py<PyAny> = instance.clone().unbind();\n            assert_eq!(instance.as_ptr(), ptr);\n        })\n    }\n\n    #[test]\n    fn test_debug_fmt() {\n        Python::attach(|py| {\n            let obj = \"hello world\".into_pyobject(py).unwrap();\n            assert_eq!(format!(\"{obj:?}\"), \"'hello world'\");\n        });\n    }\n\n    #[test]\n    fn test_display_fmt() {\n        Python::attach(|py| {\n            let obj = \"hello world\".into_pyobject(py).unwrap();\n            assert_eq!(format!(\"{obj}\"), \"hello world\");\n        });\n    }\n\n    #[test]\n    fn test_bound_as_any() {\n        Python::attach(|py| {\n            let obj = PyString::new(py, \"hello world\");\n            let any = obj.as_any();\n            assert_eq!(any.as_ptr(), obj.as_ptr());\n        });\n    }\n\n    #[test]\n    fn test_bound_into_any() {\n        Python::attach(|py| {\n            let obj = PyString::new(py, \"hello world\");\n            let any = obj.clone().into_any();\n            assert_eq!(any.as_ptr(), obj.as_ptr());\n        });\n    }\n\n    #[test]\n    fn test_bound_py_conversions() {\n        Python::attach(|py| {\n            let obj: Bound<'_, PyString> = PyString::new(py, \"hello world\");\n            let obj_unbound: &Py<PyString> = obj.as_unbound();\n            let _: &Bound<'_, PyString> = obj_unbound.bind(py);\n\n            let obj_unbound: Py<PyString> = obj.unbind();\n            let obj: Bound<'_, PyString> = obj_unbound.into_bound(py);\n\n            assert_eq!(obj, \"hello world\");\n        });\n    }\n\n    #[test]\n    fn test_borrowed_identity() {\n        Python::attach(|py| {\n            let yes = true.into_pyobject(py).unwrap();\n            let no = false.into_pyobject(py).unwrap();\n\n            assert!(yes.is(yes));\n            assert!(!yes.is(no));\n        });\n    }\n\n    #[test]\n    #[expect(\n        clippy::undocumented_unsafe_blocks,\n        reason = \"Doing evil things to try to make `Bound` blow up\"\n    )]\n    fn bound_from_borrowed_ptr_constructors() {\n        Python::attach(|py| {\n            fn check_drop<'py>(\n                py: Python<'py>,\n                method: impl FnOnce(*mut ffi::PyObject) -> Bound<'py, PyAny>,\n            ) {\n                let mut dropped = false;\n                let capsule = PyCapsule::new_with_destructor(\n                    py,\n                    (&mut dropped) as *mut _ as usize,\n                    None,\n                    |ptr, _| unsafe { std::ptr::write(ptr as *mut bool, true) },\n                )\n                .unwrap();\n\n                let bound = method(capsule.as_ptr());\n                assert!(!dropped);\n\n                // creating the bound should have increased the refcount\n                drop(capsule);\n                assert!(!dropped);\n\n                // dropping the bound should now also decrease the refcount and free the object\n                drop(bound);\n                assert!(dropped);\n            }\n\n            check_drop(py, |ptr| unsafe { Bound::from_borrowed_ptr(py, ptr) });\n            check_drop(py, |ptr| unsafe {\n                Bound::from_borrowed_ptr_or_opt(py, ptr).unwrap()\n            });\n            check_drop(py, |ptr| unsafe {\n                Bound::from_borrowed_ptr_or_err(py, ptr).unwrap()\n            });\n        })\n    }\n\n    #[test]\n    #[expect(\n        clippy::undocumented_unsafe_blocks,\n        reason = \"Doing evil things to try to make `Borrowed` blow up\"\n    )]\n    fn borrowed_ptr_constructors() {\n        Python::attach(|py| {\n            fn check_drop<'py>(\n                py: Python<'py>,\n                method: impl FnOnce(&*mut ffi::PyObject) -> Borrowed<'_, 'py, PyAny>,\n            ) {\n                let mut dropped = false;\n                let capsule = PyCapsule::new_with_destructor(\n                    py,\n                    (&mut dropped) as *mut _ as usize,\n                    None,\n                    |ptr, _| unsafe { std::ptr::write(ptr as *mut bool, true) },\n                )\n                .unwrap();\n\n                let ptr = &capsule.as_ptr();\n                let _borrowed = method(ptr);\n                assert!(!dropped);\n\n                // creating the borrow should not have increased the refcount\n                drop(capsule);\n                assert!(dropped);\n            }\n\n            check_drop(py, |&ptr| unsafe { Borrowed::from_ptr(py, ptr) });\n            check_drop(py, |&ptr| unsafe {\n                Borrowed::from_ptr_or_opt(py, ptr).unwrap()\n            });\n            check_drop(py, |&ptr| unsafe {\n                Borrowed::from_ptr_or_err(py, ptr).unwrap()\n            });\n        })\n    }\n\n    #[test]\n    fn explicit_drop_ref() {\n        Python::attach(|py| {\n            let object: Py<PyDict> = PyDict::new(py).unbind();\n            let object2 = object.clone_ref(py);\n\n            assert_eq!(object.as_ptr(), object2.as_ptr());\n            assert_eq!(object._get_refcnt(py), 2);\n\n            object.drop_ref(py);\n\n            assert_eq!(object2._get_refcnt(py), 1);\n\n            object2.drop_ref(py);\n        });\n    }\n\n    #[test]\n    fn test_py_is_truthy() {\n        Python::attach(|py| {\n            let yes = true.into_py_any(py).unwrap();\n            let no = false.into_py_any(py).unwrap();\n\n            assert!(yes.is_truthy(py).unwrap());\n            assert!(!no.is_truthy(py).unwrap());\n        });\n    }\n\n    #[cfg(all(feature = \"macros\", Py_3_8, panic = \"unwind\"))]\n    #[test]\n    fn test_constructors_panic_on_null() {\n        Python::attach(|py| {\n            const NULL: *mut ffi::PyObject = std::ptr::null_mut();\n\n            #[expect(deprecated, reason = \"Py<T> constructors\")]\n            // SAFETY: calling all constructors with null pointer to test panic behavior\n            for constructor in unsafe {\n                [\n                    (|py| {\n                        Py::<PyAny>::from_owned_ptr(py, NULL);\n                    }) as fn(Python<'_>),\n                    (|py| {\n                        Py::<PyAny>::from_borrowed_ptr(py, NULL);\n                    }) as fn(Python<'_>),\n                    (|py| {\n                        Bound::from_owned_ptr(py, NULL);\n                    }) as fn(Python<'_>),\n                    (|py| {\n                        Bound::from_borrowed_ptr(py, NULL);\n                    }) as fn(Python<'_>),\n                    (|py| {\n                        Borrowed::from_ptr(py, NULL);\n                    }) as fn(Python<'_>),\n                ]\n            } {\n                UnraisableCapture::enter(py, |capture| {\n                    // panic without exception set, no unraisable hook called\n                    let result = std::panic::catch_unwind(|| {\n                        constructor(py);\n                    });\n                    assert_eq!(\n                        result.unwrap_err().downcast_ref::<&str>(),\n                        Some(&\"PyObject pointer is null\")\n                    );\n                    assert!(capture.take_capture().is_none());\n\n                    // set an exception, panic, unraisable hook called\n                    PyValueError::new_err(\"error\").restore(py);\n                    let result = std::panic::catch_unwind(|| {\n                        constructor(py);\n                    });\n                    assert_eq!(\n                        result.unwrap_err().downcast_ref::<&str>(),\n                        Some(&\"PyObject pointer is null\")\n                    );\n                    assert!(capture.take_capture().is_some_and(|(err, obj)| {\n                        err.is_instance_of::<PyValueError>(py) && obj.is_none()\n                    }));\n                });\n            }\n        });\n    }\n\n    #[cfg(feature = \"macros\")]\n    mod using_macros {\n        use super::*;\n\n        #[crate::pyclass(crate = \"crate\")]\n        struct SomeClass(i32);\n\n        #[test]\n        fn py_borrow_methods() {\n            // More detailed tests of the underlying semantics in pycell.rs\n            Python::attach(|py| {\n                let instance = Py::new(py, SomeClass(0)).unwrap();\n                assert_eq!(instance.borrow(py).0, 0);\n                assert_eq!(instance.try_borrow(py).unwrap().0, 0);\n                assert_eq!(instance.borrow_mut(py).0, 0);\n                assert_eq!(instance.try_borrow_mut(py).unwrap().0, 0);\n\n                instance.borrow_mut(py).0 = 123;\n\n                assert_eq!(instance.borrow(py).0, 123);\n                assert_eq!(instance.try_borrow(py).unwrap().0, 123);\n                assert_eq!(instance.borrow_mut(py).0, 123);\n                assert_eq!(instance.try_borrow_mut(py).unwrap().0, 123);\n            })\n        }\n\n        #[test]\n        fn bound_borrow_methods() {\n            // More detailed tests of the underlying semantics in pycell.rs\n            Python::attach(|py| {\n                let instance = Bound::new(py, SomeClass(0)).unwrap();\n                assert_eq!(instance.borrow().0, 0);\n                assert_eq!(instance.try_borrow().unwrap().0, 0);\n                assert_eq!(instance.borrow_mut().0, 0);\n                assert_eq!(instance.try_borrow_mut().unwrap().0, 0);\n\n                instance.borrow_mut().0 = 123;\n\n                assert_eq!(instance.borrow().0, 123);\n                assert_eq!(instance.try_borrow().unwrap().0, 123);\n                assert_eq!(instance.borrow_mut().0, 123);\n                assert_eq!(instance.try_borrow_mut().unwrap().0, 123);\n            })\n        }\n\n        #[crate::pyclass(frozen, crate = \"crate\")]\n        struct FrozenClass(i32);\n\n        #[test]\n        fn test_frozen_get() {\n            Python::attach(|py| {\n                for i in 0..10 {\n                    let instance = Py::new(py, FrozenClass(i)).unwrap();\n                    assert_eq!(instance.get().0, i);\n\n                    assert_eq!(instance.bind(py).get().0, i);\n\n                    assert_eq!(instance.bind_borrowed(py).get().0, i);\n                }\n            })\n        }\n\n        #[crate::pyclass(crate = \"crate\", subclass)]\n        struct BaseClass;\n\n        trait MyClassMethods<'py>: Sized {\n            fn pyrepr_by_ref(&self) -> PyResult<String>;\n            fn pyrepr_by_val(self) -> PyResult<String> {\n                self.pyrepr_by_ref()\n            }\n        }\n        impl<'py> MyClassMethods<'py> for Bound<'py, BaseClass> {\n            fn pyrepr_by_ref(&self) -> PyResult<String> {\n                self.call_method0(\"__repr__\")?.extract()\n            }\n        }\n\n        #[crate::pyclass(crate = \"crate\", extends = BaseClass)]\n        struct SubClass;\n\n        #[test]\n        fn test_as_super() {\n            Python::attach(|py| {\n                let obj = Bound::new(py, (SubClass, BaseClass)).unwrap();\n                let _: &Bound<'_, BaseClass> = obj.as_super();\n                let _: &Bound<'_, PyAny> = obj.as_super().as_super();\n                assert!(obj.as_super().pyrepr_by_ref().is_ok());\n            })\n        }\n\n        #[test]\n        fn test_into_super() {\n            Python::attach(|py| {\n                let obj = Bound::new(py, (SubClass, BaseClass)).unwrap();\n                let _: Bound<'_, BaseClass> = obj.clone().into_super();\n                let _: Bound<'_, PyAny> = obj.clone().into_super().into_super();\n                assert!(obj.into_super().pyrepr_by_val().is_ok());\n            })\n        }\n    }\n}\n"
  },
  {
    "path": "src/internal/get_slot.rs",
    "content": "use crate::{\n    ffi,\n    types::{PyType, PyTypeMethods},\n    Borrowed, Bound,\n};\nuse std::ffi::c_int;\n\nimpl Bound<'_, PyType> {\n    #[inline]\n    pub(crate) fn get_slot<const S: c_int>(&self, slot: Slot<S>) -> <Slot<S> as GetSlotImpl>::Type\n    where\n        Slot<S>: GetSlotImpl,\n    {\n        // SAFETY: `self` is a valid type object.\n        unsafe {\n            slot.get_slot(\n                self.as_type_ptr(),\n                #[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\n                is_runtime_3_10(self.py()),\n            )\n        }\n    }\n}\n\nimpl Borrowed<'_, '_, PyType> {\n    #[inline]\n    pub(crate) fn get_slot<const S: c_int>(self, slot: Slot<S>) -> <Slot<S> as GetSlotImpl>::Type\n    where\n        Slot<S>: GetSlotImpl,\n    {\n        // SAFETY: `self` is a valid type object.\n        unsafe {\n            slot.get_slot(\n                self.as_type_ptr(),\n                #[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\n                is_runtime_3_10(self.py()),\n            )\n        }\n    }\n}\n\n/// Gets a slot from a raw FFI pointer.\n///\n/// Safety:\n///   - `ty` must be a valid non-null pointer to a `PyTypeObject`.\n///   - The Python runtime must be initialized\npub(crate) unsafe fn get_slot<const S: c_int>(\n    ty: *mut ffi::PyTypeObject,\n    slot: Slot<S>,\n) -> <Slot<S> as GetSlotImpl>::Type\nwhere\n    Slot<S>: GetSlotImpl,\n{\n    unsafe {\n        slot.get_slot(\n            ty,\n            // SAFETY: the Python runtime is initialized\n            #[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\n            is_runtime_3_10(crate::Python::assume_attached()),\n        )\n    }\n}\n\npub(crate) trait GetSlotImpl {\n    type Type;\n\n    /// Gets the requested slot from a type object.\n    ///\n    /// Safety:\n    ///  - `ty` must be a valid non-null pointer to a `PyTypeObject`.\n    ///  - `is_runtime_3_10` must be `false` if the runtime is not Python 3.10 or later.\n    unsafe fn get_slot(\n        self,\n        ty: *mut ffi::PyTypeObject,\n        #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] is_runtime_3_10: bool,\n    ) -> Self::Type;\n}\n\n#[derive(Copy, Clone)]\npub(crate) struct Slot<const S: c_int>;\n\nmacro_rules! impl_slots {\n    ($($name:ident: ($slot:ident, $field:ident) -> $tp:ty),+ $(,)?) => {\n        $(\n            pub (crate) const $name: Slot<{ ffi::$slot }> = Slot;\n\n            impl GetSlotImpl for Slot<{ ffi::$slot }> {\n                type Type = $tp;\n\n                #[inline]\n                unsafe fn get_slot(\n                    self,\n                    ty: *mut ffi::PyTypeObject,\n                    #[cfg(all(Py_LIMITED_API, not(Py_3_10)))] is_runtime_3_10: bool\n                ) -> Self::Type {\n                    #[cfg(not(Py_LIMITED_API))]\n                    {\n                        unsafe {(*ty).$field }\n                    }\n\n                    #[cfg(Py_LIMITED_API)]\n                    {\n                        #[cfg(not(Py_3_10))]\n                        {\n                            // Calling PyType_GetSlot on static types is not valid before Python 3.10\n                            // ... so the workaround is to first do a runtime check for these versions\n                            // (3.7, 3.8, 3.9) and then look in the type object anyway. This is only ok\n                            // because we know that the interpreter is not going to change the size\n                            // of the type objects for these historical versions.\n                            if !is_runtime_3_10 && unsafe {ffi::PyType_HasFeature(ty, ffi::Py_TPFLAGS_HEAPTYPE)} == 0\n                            {\n                                return unsafe {(*ty.cast::<PyTypeObject39Snapshot>()).$field};\n                            }\n                        }\n\n                        // SAFETY: slot type is set carefully to be valid\n                        unsafe {std::mem::transmute(ffi::PyType_GetSlot(ty, ffi::$slot))}\n                    }\n                }\n            }\n        )*\n    };\n}\n\n// Slots are implemented on-demand as needed.)\nimpl_slots! {\n    TP_NEW: (Py_tp_new, tp_new) -> Option<ffi::newfunc>,\n    TP_DEALLOC: (Py_tp_dealloc, tp_dealloc) -> Option<ffi::destructor>,\n    TP_BASE: (Py_tp_base, tp_base) -> *mut ffi::PyTypeObject,\n    TP_CLEAR: (Py_tp_clear, tp_clear) -> Option<ffi::inquiry>,\n    TP_DESCR_GET: (Py_tp_descr_get, tp_descr_get) -> Option<ffi::descrgetfunc>,\n    TP_FREE: (Py_tp_free, tp_free) -> Option<ffi::freefunc>,\n    TP_TRAVERSE: (Py_tp_traverse, tp_traverse) -> Option<ffi::traverseproc>,\n}\n\n#[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\nfn is_runtime_3_10(py: crate::Python<'_>) -> bool {\n    use crate::sync::PyOnceLock;\n\n    static IS_RUNTIME_3_10: PyOnceLock<bool> = PyOnceLock::new();\n    *IS_RUNTIME_3_10.get_or_init(py, || py.version_info() >= (3, 10))\n}\n\n#[repr(C)]\n#[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\npub struct PyNumberMethods39Snapshot {\n    pub nb_add: Option<ffi::binaryfunc>,\n    pub nb_subtract: Option<ffi::binaryfunc>,\n    pub nb_multiply: Option<ffi::binaryfunc>,\n    pub nb_remainder: Option<ffi::binaryfunc>,\n    pub nb_divmod: Option<ffi::binaryfunc>,\n    pub nb_power: Option<ffi::ternaryfunc>,\n    pub nb_negative: Option<ffi::unaryfunc>,\n    pub nb_positive: Option<ffi::unaryfunc>,\n    pub nb_absolute: Option<ffi::unaryfunc>,\n    pub nb_bool: Option<ffi::inquiry>,\n    pub nb_invert: Option<ffi::unaryfunc>,\n    pub nb_lshift: Option<ffi::binaryfunc>,\n    pub nb_rshift: Option<ffi::binaryfunc>,\n    pub nb_and: Option<ffi::binaryfunc>,\n    pub nb_xor: Option<ffi::binaryfunc>,\n    pub nb_or: Option<ffi::binaryfunc>,\n    pub nb_int: Option<ffi::unaryfunc>,\n    pub nb_reserved: *mut std::ffi::c_void,\n    pub nb_float: Option<ffi::unaryfunc>,\n    pub nb_inplace_add: Option<ffi::binaryfunc>,\n    pub nb_inplace_subtract: Option<ffi::binaryfunc>,\n    pub nb_inplace_multiply: Option<ffi::binaryfunc>,\n    pub nb_inplace_remainder: Option<ffi::binaryfunc>,\n    pub nb_inplace_power: Option<ffi::ternaryfunc>,\n    pub nb_inplace_lshift: Option<ffi::binaryfunc>,\n    pub nb_inplace_rshift: Option<ffi::binaryfunc>,\n    pub nb_inplace_and: Option<ffi::binaryfunc>,\n    pub nb_inplace_xor: Option<ffi::binaryfunc>,\n    pub nb_inplace_or: Option<ffi::binaryfunc>,\n    pub nb_floor_divide: Option<ffi::binaryfunc>,\n    pub nb_true_divide: Option<ffi::binaryfunc>,\n    pub nb_inplace_floor_divide: Option<ffi::binaryfunc>,\n    pub nb_inplace_true_divide: Option<ffi::binaryfunc>,\n    pub nb_index: Option<ffi::unaryfunc>,\n    pub nb_matrix_multiply: Option<ffi::binaryfunc>,\n    pub nb_inplace_matrix_multiply: Option<ffi::binaryfunc>,\n}\n\n#[repr(C)]\n#[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\npub struct PySequenceMethods39Snapshot {\n    pub sq_length: Option<ffi::lenfunc>,\n    pub sq_concat: Option<ffi::binaryfunc>,\n    pub sq_repeat: Option<ffi::ssizeargfunc>,\n    pub sq_item: Option<ffi::ssizeargfunc>,\n    pub was_sq_slice: *mut std::ffi::c_void,\n    pub sq_ass_item: Option<ffi::ssizeobjargproc>,\n    pub was_sq_ass_slice: *mut std::ffi::c_void,\n    pub sq_contains: Option<ffi::objobjproc>,\n    pub sq_inplace_concat: Option<ffi::binaryfunc>,\n    pub sq_inplace_repeat: Option<ffi::ssizeargfunc>,\n}\n\n#[repr(C)]\n#[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\npub struct PyMappingMethods39Snapshot {\n    pub mp_length: Option<ffi::lenfunc>,\n    pub mp_subscript: Option<ffi::binaryfunc>,\n    pub mp_ass_subscript: Option<ffi::objobjargproc>,\n}\n\n#[repr(C)]\n#[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\npub struct PyAsyncMethods39Snapshot {\n    pub am_await: Option<ffi::unaryfunc>,\n    pub am_aiter: Option<ffi::unaryfunc>,\n    pub am_anext: Option<ffi::unaryfunc>,\n}\n\n#[repr(C)]\n#[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\npub struct PyBufferProcs39Snapshot {\n    // not available in limited api, but structure needs to have the right size\n    pub bf_getbuffer: *mut std::ffi::c_void,\n    pub bf_releasebuffer: *mut std::ffi::c_void,\n}\n\n/// Snapshot of the structure of PyTypeObject for Python 3.7 through 3.9.\n///\n/// This is used as a fallback for static types in abi3 when the Python version is less than 3.10;\n/// this is a bit of a hack but there's no better option and the structure of the type object is\n/// not going to change for those historical versions.\n#[repr(C)]\n#[cfg(all(Py_LIMITED_API, not(Py_3_10)))]\nstruct PyTypeObject39Snapshot {\n    pub ob_base: ffi::PyVarObject,\n    pub tp_name: *const std::ffi::c_char,\n    pub tp_basicsize: ffi::Py_ssize_t,\n    pub tp_itemsize: ffi::Py_ssize_t,\n    pub tp_dealloc: Option<ffi::destructor>,\n    #[cfg(not(Py_3_8))]\n    pub tp_print: *mut std::ffi::c_void, // stubbed out, not available in limited API\n    #[cfg(Py_3_8)]\n    pub tp_vectorcall_offset: ffi::Py_ssize_t,\n    pub tp_getattr: Option<ffi::getattrfunc>,\n    pub tp_setattr: Option<ffi::setattrfunc>,\n    pub tp_as_async: *mut PyAsyncMethods39Snapshot,\n    pub tp_repr: Option<ffi::reprfunc>,\n    pub tp_as_number: *mut PyNumberMethods39Snapshot,\n    pub tp_as_sequence: *mut PySequenceMethods39Snapshot,\n    pub tp_as_mapping: *mut PyMappingMethods39Snapshot,\n    pub tp_hash: Option<ffi::hashfunc>,\n    pub tp_call: Option<ffi::ternaryfunc>,\n    pub tp_str: Option<ffi::reprfunc>,\n    pub tp_getattro: Option<ffi::getattrofunc>,\n    pub tp_setattro: Option<ffi::setattrofunc>,\n    pub tp_as_buffer: *mut PyBufferProcs39Snapshot,\n    pub tp_flags: std::ffi::c_ulong,\n    pub tp_doc: *const std::ffi::c_char,\n    pub tp_traverse: Option<ffi::traverseproc>,\n    pub tp_clear: Option<ffi::inquiry>,\n    pub tp_richcompare: Option<ffi::richcmpfunc>,\n    pub tp_weaklistoffset: ffi::Py_ssize_t,\n    pub tp_iter: Option<ffi::getiterfunc>,\n    pub tp_iternext: Option<ffi::iternextfunc>,\n    pub tp_methods: *mut ffi::PyMethodDef,\n    pub tp_members: *mut ffi::PyMemberDef,\n    pub tp_getset: *mut ffi::PyGetSetDef,\n    pub tp_base: *mut ffi::PyTypeObject,\n    pub tp_dict: *mut ffi::PyObject,\n    pub tp_descr_get: Option<ffi::descrgetfunc>,\n    pub tp_descr_set: Option<ffi::descrsetfunc>,\n    pub tp_dictoffset: ffi::Py_ssize_t,\n    pub tp_init: Option<ffi::initproc>,\n    pub tp_alloc: Option<ffi::allocfunc>,\n    pub tp_new: Option<ffi::newfunc>,\n    pub tp_free: Option<ffi::freefunc>,\n    pub tp_is_gc: Option<ffi::inquiry>,\n    pub tp_bases: *mut ffi::PyObject,\n    pub tp_mro: *mut ffi::PyObject,\n    pub tp_cache: *mut ffi::PyObject,\n    pub tp_subclasses: *mut ffi::PyObject,\n    pub tp_weaklist: *mut ffi::PyObject,\n    pub tp_del: Option<ffi::destructor>,\n    pub tp_version_tag: std::ffi::c_uint,\n    pub tp_finalize: Option<ffi::destructor>,\n    #[cfg(Py_3_8)]\n    pub tp_vectorcall: Option<ffi::vectorcallfunc>,\n}\n"
  },
  {
    "path": "src/internal/state.rs",
    "content": "//! Interaction with attachment of the current thread to the Python interpreter.\n\n#[cfg(pyo3_disable_reference_pool)]\nuse crate::impl_::panic::PanicTrap;\nuse crate::{ffi, Python};\n\nuse std::cell::Cell;\n#[cfg(not(pyo3_disable_reference_pool))]\nuse std::sync::OnceLock;\n#[cfg_attr(pyo3_disable_reference_pool, allow(unused_imports))]\nuse std::{mem, ptr::NonNull, sync};\n\nstd::thread_local! {\n    /// This is an internal counter in pyo3 monitoring whether this thread is attached to the interpreter.\n    ///\n    /// It will be incremented whenever an AttachGuard is created, and decremented whenever\n    /// they are dropped.\n    ///\n    /// As a result, if this thread is attached to the interpreter, ATTACH_COUNT is greater than zero.\n    ///\n    /// Additionally, we sometimes need to prevent safe access to the Python interpreter,\n    /// e.g. when implementing `__traverse__`, which is represented by a negative value.\n    static ATTACH_COUNT: Cell<isize> = const { Cell::new(0) };\n}\n\nconst ATTACH_FORBIDDEN_DURING_TRAVERSE: isize = -1;\n\n/// Checks whether the thread is attached to the Python interpreter.\n///\n/// Note: This uses pyo3's internal count rather than PyGILState_Check for two reasons:\n///  1) for performance\n///  2) PyGILState_Check always returns 1 if the sub-interpreter APIs have ever been called,\n///     which could lead to incorrect conclusions that the thread is attached.\n#[inline(always)]\npub(crate) fn thread_is_attached() -> bool {\n    ATTACH_COUNT.try_with(|c| c.get() > 0).unwrap_or(false)\n}\n\n/// RAII type that represents thread attachment to the interpreter.\npub(crate) enum AttachGuard {\n    /// Indicates the thread was already attached when this AttachGuard was acquired.\n    Assumed,\n    /// Indicates that we attached when this AttachGuard was acquired\n    Ensured { gstate: ffi::PyGILState_STATE },\n}\n\n/// Possible error when calling `try_attach()`\npub(crate) enum AttachError {\n    /// Forbidden during GC traversal.\n    ForbiddenDuringTraverse,\n    /// The interpreter is not initialized.\n    NotInitialized,\n    #[cfg(Py_3_13)]\n    /// The interpreter is finalizing.\n    Finalizing,\n}\n\nimpl AttachGuard {\n    /// PyO3 internal API for attaching to the Python interpreter. The public API is Python::attach.\n    ///\n    /// If the thread was already attached via PyO3, this returns\n    /// `AttachGuard::Assumed`. Otherwise, the thread will attach now and\n    /// `AttachGuard::Ensured` will be returned.\n    pub(crate) fn attach() -> Self {\n        match Self::try_attach() {\n            Ok(guard) => guard,\n            Err(AttachError::ForbiddenDuringTraverse) => {\n                panic!(\"{}\", ForbidAttaching::FORBIDDEN_DURING_TRAVERSE)\n            }\n            Err(AttachError::NotInitialized) => {\n                // try to initialize the interpreter and try again\n                crate::interpreter_lifecycle::ensure_initialized();\n                unsafe { Self::do_attach_unchecked() }\n            }\n            #[cfg(Py_3_13)]\n            Err(AttachError::Finalizing) => {\n                panic!(\"Cannot attach to the Python interpreter while it is finalizing.\");\n            }\n        }\n    }\n\n    /// Variant of the above which will will return gracefully if the interpreter cannot be attached to.\n    pub(crate) fn try_attach() -> Result<Self, AttachError> {\n        match ATTACH_COUNT.try_with(|c| c.get()) {\n            Ok(i) if i > 0 => {\n                // SAFETY: We just checked that the thread is already attached.\n                return Ok(unsafe { Self::assume() });\n            }\n            // Cannot attach during GC traversal.\n            Ok(ATTACH_FORBIDDEN_DURING_TRAVERSE) => {\n                return Err(AttachError::ForbiddenDuringTraverse)\n            }\n            // other cases handled below\n            _ => {}\n        }\n\n        // SAFETY: always safe to call this\n        if unsafe { ffi::Py_IsInitialized() } == 0 {\n            return Err(AttachError::NotInitialized);\n        }\n\n        // Calling `PyGILState_Ensure` while finalizing may crash CPython in unpredictable\n        // ways, we'll make a best effort attempt here to avoid that. (There's a time of\n        // check to time-of-use issue, but it's better than nothing.)\n        //\n        // SAFETY: always safe to call this\n        #[cfg(Py_3_13)]\n        if unsafe { ffi::Py_IsFinalizing() } != 0 {\n            // If the interpreter is not initialized, we cannot attach.\n            return Err(AttachError::Finalizing);\n        }\n\n        // SAFETY: We have done everything reasonable to ensure we're in a safe state to\n        // attach to the Python interpreter.\n        Ok(unsafe { Self::do_attach_unchecked() })\n    }\n\n    /// Acquires the `AttachGuard` without performing any state checking.\n    ///\n    /// This can be called in \"unsafe\" contexts where the normal interpreter state\n    /// checking performed by `AttachGuard::try_attach` may fail. This includes calling\n    /// as part of multi-phase interpreter initialization.\n    ///\n    /// # Safety\n    ///\n    /// The caller must ensure that the Python interpreter is sufficiently initialized\n    /// for a thread to be able to attach to it.\n    pub(crate) unsafe fn attach_unchecked() -> Self {\n        if thread_is_attached() {\n            return unsafe { Self::assume() };\n        }\n\n        unsafe { Self::do_attach_unchecked() }\n    }\n\n    /// Attach to the interpreter, without a fast-path to check if the thread is already attached.\n    #[cold]\n    unsafe fn do_attach_unchecked() -> Self {\n        // SAFETY: interpreter is sufficiently initialized to attach a thread.\n        let gstate = unsafe { ffi::PyGILState_Ensure() };\n        increment_attach_count();\n        // SAFETY: just attached to the interpreter\n        drop_deferred_references(unsafe { Python::assume_attached() });\n        AttachGuard::Ensured { gstate }\n    }\n\n    /// Acquires the `AttachGuard` while assuming that the thread is already attached\n    /// to the interpreter.\n    pub(crate) unsafe fn assume() -> Self {\n        increment_attach_count();\n        // SAFETY: invariant of calling this function\n        drop_deferred_references(unsafe { Python::assume_attached() });\n        AttachGuard::Assumed\n    }\n\n    /// Gets the Python token associated with this [`AttachGuard`].\n    #[inline]\n    pub(crate) fn python(&self) -> Python<'_> {\n        // SAFETY: this guard guarantees the thread is attached\n        unsafe { Python::assume_attached() }\n    }\n}\n\n/// The Drop implementation for `AttachGuard` will decrement the attach count (and potentially detach).\nimpl Drop for AttachGuard {\n    fn drop(&mut self) {\n        match self {\n            AttachGuard::Assumed => {}\n            AttachGuard::Ensured { gstate } => unsafe {\n                // Drop the objects in the pool before attempting to release the thread state\n                ffi::PyGILState_Release(*gstate);\n            },\n        }\n        decrement_attach_count();\n    }\n}\n\n#[cfg(not(pyo3_disable_reference_pool))]\ntype PyObjVec = Vec<NonNull<ffi::PyObject>>;\n\n#[cfg(not(pyo3_disable_reference_pool))]\n/// Thread-safe storage for objects which were dec_ref while not attached.\nstruct ReferencePool {\n    pending_decrefs: sync::Mutex<PyObjVec>,\n}\n\n#[cfg(not(pyo3_disable_reference_pool))]\nimpl ReferencePool {\n    const fn new() -> Self {\n        Self {\n            pending_decrefs: sync::Mutex::new(Vec::new()),\n        }\n    }\n\n    fn register_decref(&self, obj: NonNull<ffi::PyObject>) {\n        self.pending_decrefs.lock().unwrap().push(obj);\n    }\n\n    fn drop_deferred_references(&self, _py: Python<'_>) {\n        let mut pending_decrefs = self.pending_decrefs.lock().unwrap();\n        if pending_decrefs.is_empty() {\n            return;\n        }\n\n        let decrefs = mem::take(&mut *pending_decrefs);\n        drop(pending_decrefs);\n\n        for ptr in decrefs {\n            unsafe { ffi::Py_DECREF(ptr.as_ptr()) };\n        }\n    }\n}\n\n#[cfg(not(pyo3_disable_reference_pool))]\nunsafe impl Send for ReferencePool {}\n\n#[cfg(not(pyo3_disable_reference_pool))]\nunsafe impl Sync for ReferencePool {}\n\n#[cfg(not(pyo3_disable_reference_pool))]\nstatic POOL: OnceLock<ReferencePool> = OnceLock::new();\n\n#[cfg(not(pyo3_disable_reference_pool))]\nfn get_pool() -> &'static ReferencePool {\n    POOL.get_or_init(ReferencePool::new)\n}\n\n#[cfg_attr(pyo3_disable_reference_pool, inline(always))]\n#[cfg_attr(pyo3_disable_reference_pool, allow(unused_variables))]\nfn drop_deferred_references(py: Python<'_>) {\n    #[cfg(not(pyo3_disable_reference_pool))]\n    if let Some(pool) = POOL.get() {\n        pool.drop_deferred_references(py);\n    }\n}\n\n/// A guard which can be used to temporarily detach from the interpreter and restore on `Drop`.\npub(crate) struct SuspendAttach {\n    count: isize,\n    tstate: *mut ffi::PyThreadState,\n}\n\nimpl SuspendAttach {\n    pub(crate) unsafe fn new() -> Self {\n        let count = ATTACH_COUNT.with(|c| c.replace(0));\n        let tstate = unsafe { ffi::PyEval_SaveThread() };\n\n        Self { count, tstate }\n    }\n}\n\nimpl Drop for SuspendAttach {\n    fn drop(&mut self) {\n        ATTACH_COUNT.with(|c| c.set(self.count));\n        unsafe {\n            ffi::PyEval_RestoreThread(self.tstate);\n\n            // Update counts of `Py<T>` that were dropped while not attached.\n            #[cfg(not(pyo3_disable_reference_pool))]\n            if let Some(pool) = POOL.get() {\n                pool.drop_deferred_references(Python::assume_attached());\n            }\n        }\n    }\n}\n\n/// Used to lock safe access to the interpreter\npub(crate) struct ForbidAttaching {\n    count: isize,\n}\n\nimpl ForbidAttaching {\n    const FORBIDDEN_DURING_TRAVERSE: &'static str = \"Attaching a thread to the interpreter is prohibited while a __traverse__ implementation is running.\";\n\n    /// Lock access to the interpreter while an implementation of `__traverse__` is running\n    pub fn during_traverse() -> Self {\n        Self::new(ATTACH_FORBIDDEN_DURING_TRAVERSE)\n    }\n\n    fn new(reason: isize) -> Self {\n        let count = ATTACH_COUNT.with(|c| c.replace(reason));\n\n        Self { count }\n    }\n\n    #[cold]\n    fn bail(current: isize) {\n        match current {\n            ATTACH_FORBIDDEN_DURING_TRAVERSE => panic!(\"{}\", Self::FORBIDDEN_DURING_TRAVERSE),\n            _ => panic!(\"Attaching a thread to the interpreter is currently prohibited.\"),\n        }\n    }\n}\n\nimpl Drop for ForbidAttaching {\n    fn drop(&mut self) {\n        ATTACH_COUNT.with(|c| c.set(self.count));\n    }\n}\n\n/// Registers a Python object pointer inside the release pool, to have its reference count decreased\n/// the next time the thread is attached in pyo3.\n///\n/// If the thread is attached, the reference count will be decreased immediately instead of being queued\n/// for later.\n///\n/// # Safety\n/// - The object must be an owned Python reference.\n/// - The reference must not be used after calling this function.\n#[inline]\npub unsafe fn register_decref(obj: NonNull<ffi::PyObject>) {\n    #[cfg(not(pyo3_disable_reference_pool))]\n    {\n        get_pool().register_decref(obj);\n    }\n    #[cfg(all(\n        pyo3_disable_reference_pool,\n        not(pyo3_leak_on_drop_without_reference_pool)\n    ))]\n    {\n        let _trap = PanicTrap::new(\"Aborting the process to avoid panic-from-drop.\");\n        panic!(\"Cannot drop pointer into Python heap without the thread being attached.\");\n    }\n}\n\n/// Private helper function to check if we are currently in a GC traversal (as detected by PyO3).\n#[cfg(any(not(Py_LIMITED_API), Py_3_11))]\npub(crate) fn is_in_gc_traversal() -> bool {\n    ATTACH_COUNT\n        .try_with(|c| c.get() == ATTACH_FORBIDDEN_DURING_TRAVERSE)\n        .unwrap_or(false)\n}\n\n/// Increments pyo3's internal attach count - to be called whenever an AttachGuard is created.\n#[inline(always)]\nfn increment_attach_count() {\n    // Ignores the error in case this function called from `atexit`.\n    let _ = ATTACH_COUNT.try_with(|c| {\n        let current = c.get();\n        if current < 0 {\n            ForbidAttaching::bail(current);\n        }\n        c.set(current + 1);\n    });\n}\n\n/// Decrements pyo3's internal attach count - to be called whenever AttachGuard is dropped.\n#[inline(always)]\nfn decrement_attach_count() {\n    // Ignores the error in case this function called from `atexit`.\n    let _ = ATTACH_COUNT.try_with(|c| {\n        let current = c.get();\n        debug_assert!(\n            current > 0,\n            \"Negative attach count detected. Please report this error to the PyO3 repo as a bug.\"\n        );\n        c.set(current - 1);\n    });\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    use crate::{Py, PyAny, Python};\n\n    fn get_object(py: Python<'_>) -> Py<PyAny> {\n        py.eval(c\"object()\", None, None).unwrap().unbind()\n    }\n\n    #[cfg(not(pyo3_disable_reference_pool))]\n    fn pool_dec_refs_does_not_contain(obj: &Py<PyAny>) -> bool {\n        !get_pool()\n            .pending_decrefs\n            .lock()\n            .unwrap()\n            .contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) })\n    }\n\n    // With free-threading, threads can empty the POOL at any time, so this\n    // function does not test anything meaningful\n    #[cfg(not(any(pyo3_disable_reference_pool, Py_GIL_DISABLED)))]\n    fn pool_dec_refs_contains(obj: &Py<PyAny>) -> bool {\n        get_pool()\n            .pending_decrefs\n            .lock()\n            .unwrap()\n            .contains(&unsafe { NonNull::new_unchecked(obj.as_ptr()) })\n    }\n\n    #[test]\n    fn test_pyobject_drop_attached_decreases_refcnt() {\n        Python::attach(|py| {\n            let obj = get_object(py);\n\n            // Create a reference to drop while attached.\n            let reference = obj.clone_ref(py);\n\n            assert_eq!(obj._get_refcnt(py), 2);\n            #[cfg(not(pyo3_disable_reference_pool))]\n            assert!(pool_dec_refs_does_not_contain(&obj));\n\n            // While attached, reference count will be decreased immediately.\n            drop(reference);\n\n            assert_eq!(obj._get_refcnt(py), 1);\n            #[cfg(not(any(pyo3_disable_reference_pool)))]\n            assert!(pool_dec_refs_does_not_contain(&obj));\n        });\n    }\n\n    #[test]\n    #[cfg(all(not(pyo3_disable_reference_pool), not(target_arch = \"wasm32\")))] // We are building wasm Python with pthreads disabled\n    fn test_pyobject_drop_detached_doesnt_decrease_refcnt() {\n        let obj = Python::attach(|py| {\n            let obj = get_object(py);\n            // Create a reference to drop while detached.\n            let reference = obj.clone_ref(py);\n\n            assert_eq!(obj._get_refcnt(py), 2);\n            assert!(pool_dec_refs_does_not_contain(&obj));\n\n            // Drop reference in a separate (detached) thread.\n            std::thread::spawn(move || drop(reference)).join().unwrap();\n\n            // The reference count should not have changed, it is remembered\n            // to release later.\n            assert_eq!(obj._get_refcnt(py), 2);\n            #[cfg(not(Py_GIL_DISABLED))]\n            assert!(pool_dec_refs_contains(&obj));\n            obj\n        });\n\n        // On next attach, the reference is released\n        #[allow(unused)]\n        Python::attach(|py| {\n            // With free-threading, another thread could still be processing\n            // DECREFs after releasing the lock on the POOL, so the\n            // refcnt could still be 2 when this assert happens\n            #[cfg(not(Py_GIL_DISABLED))]\n            assert_eq!(obj._get_refcnt(py), 1);\n            assert!(pool_dec_refs_does_not_contain(&obj));\n        });\n    }\n\n    #[test]\n    fn test_attach_counts() {\n        // Check `attach` and AttachGuard both increase counts correctly\n        let get_attach_count = || ATTACH_COUNT.with(|c| c.get());\n\n        assert_eq!(get_attach_count(), 0);\n        Python::attach(|_| {\n            assert_eq!(get_attach_count(), 1);\n\n            let pool = unsafe { AttachGuard::assume() };\n            assert_eq!(get_attach_count(), 2);\n\n            let pool2 = unsafe { AttachGuard::assume() };\n            assert_eq!(get_attach_count(), 3);\n\n            drop(pool);\n            assert_eq!(get_attach_count(), 2);\n\n            Python::attach(|_| {\n                // nested `attach` updates attach count\n                assert_eq!(get_attach_count(), 3);\n            });\n            assert_eq!(get_attach_count(), 2);\n\n            drop(pool2);\n            assert_eq!(get_attach_count(), 1);\n        });\n        assert_eq!(get_attach_count(), 0);\n    }\n\n    #[test]\n    fn test_detach() {\n        assert!(!thread_is_attached());\n\n        Python::attach(|py| {\n            assert!(thread_is_attached());\n\n            py.detach(move || {\n                assert!(!thread_is_attached());\n\n                Python::attach(|_| assert!(thread_is_attached()));\n\n                assert!(!thread_is_attached());\n            });\n\n            assert!(thread_is_attached());\n        });\n\n        assert!(!thread_is_attached());\n    }\n\n    #[cfg(feature = \"py-clone\")]\n    #[test]\n    #[should_panic]\n    fn test_detach_updates_refcounts() {\n        Python::attach(|py| {\n            // Make a simple object with 1 reference\n            let obj = get_object(py);\n            assert_eq!(obj._get_refcnt(py), 1);\n            // Cloning the object when detached should panic\n            py.detach(|| obj.clone());\n        });\n    }\n\n    #[test]\n    fn recursive_attach_ok() {\n        Python::attach(|py| {\n            let obj = Python::attach(|_| py.eval(c\"object()\", None, None).unwrap());\n            assert_eq!(obj._get_refcnt(), 1);\n        })\n    }\n\n    #[cfg(feature = \"py-clone\")]\n    #[test]\n    fn test_clone_attached() {\n        Python::attach(|py| {\n            let obj = get_object(py);\n            let count = obj._get_refcnt(py);\n\n            // Cloning when attached should increase reference count immediately\n            #[expect(clippy::redundant_clone)]\n            let c = obj.clone();\n            assert_eq!(count + 1, c._get_refcnt(py));\n        })\n    }\n\n    #[test]\n    #[cfg(not(pyo3_disable_reference_pool))]\n    fn test_drop_deferred_references_does_not_deadlock() {\n        // drop_deferred_references can run arbitrary Python code during Py_DECREF.\n        // if the locking is implemented incorrectly, it will deadlock.\n\n        use crate::ffi;\n\n        Python::attach(|py| {\n            let obj = get_object(py);\n\n            unsafe extern \"C\" fn capsule_drop(capsule: *mut ffi::PyObject) {\n                // This line will implicitly call drop_deferred_references\n                // -> and so cause deadlock if drop_deferred_references is not handling recursion correctly.\n                let pool = unsafe { AttachGuard::assume() };\n\n                // Rebuild obj so that it can be dropped\n                unsafe {\n                    use crate::Bound;\n\n                    Bound::from_owned_ptr(\n                        pool.python(),\n                        ffi::PyCapsule_GetPointer(capsule, std::ptr::null()) as _,\n                    )\n                };\n            }\n\n            let ptr = obj.into_ptr();\n\n            let capsule =\n                unsafe { ffi::PyCapsule_New(ptr as _, std::ptr::null(), Some(capsule_drop)) };\n\n            get_pool().register_decref(NonNull::new(capsule).unwrap());\n\n            // Updating the counts will call decref on the capsule, which calls capsule_drop\n            get_pool().drop_deferred_references(py);\n        })\n    }\n\n    #[test]\n    #[cfg(not(pyo3_disable_reference_pool))]\n    fn test_attach_guard_drop_deferred_references() {\n        Python::attach(|py| {\n            let obj = get_object(py);\n\n            // For AttachGuard::attach\n\n            get_pool().register_decref(NonNull::new(obj.clone_ref(py).into_ptr()).unwrap());\n            #[cfg(not(Py_GIL_DISABLED))]\n            assert!(pool_dec_refs_contains(&obj));\n            let _guard = AttachGuard::attach();\n            assert!(pool_dec_refs_does_not_contain(&obj));\n\n            // For AttachGuard::assume\n\n            get_pool().register_decref(NonNull::new(obj.clone_ref(py).into_ptr()).unwrap());\n            #[cfg(not(Py_GIL_DISABLED))]\n            assert!(pool_dec_refs_contains(&obj));\n            let _guard2 = unsafe { AttachGuard::assume() };\n            assert!(pool_dec_refs_does_not_contain(&obj));\n        })\n    }\n}\n"
  },
  {
    "path": "src/internal.rs",
    "content": "//! Holding place for code which is not intended to be reachable from outside of PyO3.\n\npub(crate) mod get_slot;\npub(crate) mod state;\n"
  },
  {
    "path": "src/internal_tricks.rs",
    "content": "use crate::ffi::{self, Py_ssize_t, PY_SSIZE_T_MAX};\n\nmacro_rules! pyo3_exception {\n    ($doc: expr, $name: ident, $base: ty) => {\n        #[doc = $doc]\n        #[repr(transparent)]\n        pub struct $name($crate::PyAny);\n\n        $crate::impl_exception_boilerplate!($name);\n\n        $crate::create_exception_type_object!(pyo3_runtime, $name, $base, Some($doc));\n    };\n}\n\n/// Convert an usize index into a Py_ssize_t index, clamping overflow to\n/// PY_SSIZE_T_MAX.\npub(crate) fn get_ssize_index(index: usize) -> Py_ssize_t {\n    index.min(PY_SSIZE_T_MAX as usize) as Py_ssize_t\n}\n\n// TODO: use ptr::fn_addr_eq on MSRV 1.85\npub(crate) fn clear_eq(f: Option<ffi::inquiry>, g: ffi::inquiry) -> bool {\n    #[cfg(fn_ptr_eq)]\n    #[expect(clippy::incompatible_msrv, reason = \"guarded by cfg(fn_ptr_eq)\")]\n    {\n        let Some(f) = f else { return false };\n        std::ptr::fn_addr_eq(f, g)\n    }\n\n    #[cfg(not(fn_ptr_eq))]\n    {\n        f == Some(g)\n    }\n}\n\n// TODO: use ptr::fn_addr_eq on MSRV 1.85\npub(crate) fn traverse_eq(f: Option<ffi::traverseproc>, g: ffi::traverseproc) -> bool {\n    #[cfg(fn_ptr_eq)]\n    #[expect(clippy::incompatible_msrv, reason = \"guarded by cfg(fn_ptr_eq)\")]\n    {\n        let Some(f) = f else { return false };\n        std::ptr::fn_addr_eq(f, g)\n    }\n\n    #[cfg(not(fn_ptr_eq))]\n    {\n        f == Some(g)\n    }\n}\n"
  },
  {
    "path": "src/interpreter_lifecycle.rs",
    "content": "#[cfg(not(any(PyPy, GraalPy)))]\nuse crate::{ffi, internal::state::AttachGuard, Python};\n\nstatic START: std::sync::Once = std::sync::Once::new();\n\n#[cfg(not(any(PyPy, GraalPy)))]\npub(crate) fn initialize() {\n    // Protect against race conditions when Python is not yet initialized and multiple threads\n    // concurrently call 'initialize()'. Note that we do not protect against\n    // concurrent initialization of the Python runtime by other users of the Python C API.\n    START.call_once_force(|_| unsafe {\n        // Use call_once_force because if initialization panics, it's okay to try again.\n        if ffi::Py_IsInitialized() == 0 {\n            ffi::Py_InitializeEx(0);\n\n            // Release the GIL.\n            ffi::PyEval_SaveThread();\n        }\n    });\n}\n\n/// Executes the provided closure with an embedded Python interpreter.\n///\n/// This function initializes the Python interpreter, executes the provided closure, and then\n/// finalizes the Python interpreter.\n///\n/// After execution all Python resources are cleaned up, and no further Python APIs can be called.\n/// Because many Python modules implemented in C do not support multiple Python interpreters in a\n/// single process, it is not safe to call this function more than once. (Many such modules will not\n/// initialize correctly on the second run.)\n///\n/// # Panics\n/// - If the Python interpreter is already initialized before calling this function.\n///\n/// # Safety\n/// - This function should only ever be called once per process (usually as part of the `main`\n///   function). It is also not thread-safe.\n/// - No Python APIs can be used after this function has finished executing.\n/// - The return value of the closure must not contain any Python value, _including_ `PyResult`.\n///\n/// # Examples\n///\n/// ```rust\n/// unsafe {\n///     pyo3::with_embedded_python_interpreter(|py| {\n///         if let Err(e) = py.run(c\"print('Hello World')\", None, None) {\n///             // We must make sure to not return a `PyErr`!\n///             e.print(py);\n///         }\n///     });\n/// }\n/// ```\n#[cfg(not(any(PyPy, GraalPy)))]\npub unsafe fn with_embedded_python_interpreter<F, R>(f: F) -> R\nwhere\n    F: for<'p> FnOnce(Python<'p>) -> R,\n{\n    assert_eq!(\n        unsafe { ffi::Py_IsInitialized() },\n        0,\n        \"called `with_embedded_python_interpreter` but a Python interpreter is already running.\"\n    );\n\n    unsafe { ffi::Py_InitializeEx(0) };\n\n    let result = {\n        let guard = unsafe { AttachGuard::assume() };\n        let py = guard.python();\n        // Import the threading module - this ensures that it will associate this thread as the \"main\"\n        // thread, which is important to avoid an `AssertionError` at finalization.\n        py.import(\"threading\").unwrap();\n\n        // Execute the closure.\n        f(py)\n    };\n\n    // Finalize the Python interpreter.\n    unsafe { ffi::Py_Finalize() };\n\n    result\n}\n\npub(crate) fn ensure_initialized() {\n    // Maybe auto-initialize the interpreter:\n    //  - If auto-initialize feature set and supported, try to initialize the interpreter.\n    //  - If the auto-initialize feature is set but unsupported, emit hard errors only when the\n    //    extension-module feature is not activated - extension modules don't care about\n    //    auto-initialize so this avoids breaking existing builds.\n    //  - Otherwise, just check the interpreter is initialized.\n    #[cfg(all(feature = \"auto-initialize\", not(any(PyPy, GraalPy))))]\n    {\n        initialize();\n    }\n    #[cfg(not(all(feature = \"auto-initialize\", not(any(PyPy, GraalPy)))))]\n    {\n        // This is a \"hack\" to make running `cargo test` for PyO3 convenient (i.e. no need\n        // to specify `--features auto-initialize` manually). Tests within the crate itself\n        // all depend on the auto-initialize feature for conciseness but Cargo does not\n        // provide a mechanism to specify required features for tests.\n        #[cfg(not(any(PyPy, GraalPy)))]\n        if option_env!(\"CARGO_PRIMARY_PACKAGE\").is_some() {\n            initialize();\n        }\n\n        START.call_once_force(|_| unsafe {\n            // Use call_once_force because if there is a panic because the interpreter is\n            // not initialized, it's fine for the user to initialize the interpreter and\n            // retry.\n            assert_ne!(\n                crate::ffi::Py_IsInitialized(),\n                0,\n                \"The Python interpreter is not initialized and the `auto-initialize` \\\n                        feature is not enabled.\\n\\n\\\n                        Consider calling `Python::initialize()` before attempting \\\n                        to use Python APIs.\"\n            );\n        });\n    }\n}\n"
  },
  {
    "path": "src/lib.rs",
    "content": "#![warn(missing_docs)]\n#![cfg_attr(\n    feature = \"nightly\",\n    feature(auto_traits, negative_impls, iter_advance_by)\n)]\n#![cfg_attr(all(feature = \"nightly\", Py_GIL_DISABLED), feature(try_trait_v2))]\n#![cfg_attr(docsrs, feature(doc_cfg))]\n#![warn(unsafe_op_in_unsafe_fn)]\n// Deny some lints in doctests.\n// Use `#[allow(...)]` locally to override.\n#![doc(test(attr(\n    deny(\n        rust_2018_idioms,\n        unused_lifetimes,\n        rust_2021_prelude_collisions,\n        warnings\n    ),\n    allow(\n        unused_imports,  // to make imports already in the prelude explicit\n        unused_variables,\n        unused_assignments,\n        unused_extern_crates,\n        // FIXME https://github.com/rust-lang/rust/issues/121621#issuecomment-1965156376\n        unknown_lints,\n        non_local_definitions,\n    )\n)))]\n\n//! Rust bindings to the Python interpreter.\n//!\n//! PyO3 can be used to write native Python modules or run Python code and modules from Rust.\n//!\n//! See [the guide] for a detailed introduction.\n//!\n//! # PyO3's object types\n//!\n//! PyO3 has several core types that you should familiarize yourself with:\n//!\n//! ## The `Python<'py>` object, and the `'py` lifetime\n//!\n//! Holding the [global interpreter lock] (GIL) is modeled with the [`Python<'py>`](Python) token. Many\n//! Python APIs require that the GIL is held, and PyO3 uses this token as proof that these APIs\n//! can be called safely. It can be explicitly acquired and is also implicitly acquired by PyO3\n//! as it wraps Rust functions and structs into Python functions and objects.\n//!\n//! The [`Python<'py>`](Python) token's lifetime `'py` is common to many PyO3 APIs:\n//! - Types that also have the `'py` lifetime, such as the [`Bound<'py, T>`](Bound) smart pointer, are\n//!   bound to the Python GIL and rely on this to offer their functionality. These types often\n//!   have a [`.py()`](Bound::py) method to get the associated [`Python<'py>`](Python) token.\n//! - Functions which depend on the `'py` lifetime, such as [`PyList::new`](types::PyList::new),\n//!   require a [`Python<'py>`](Python) token as an input. Sometimes the token is passed implicitly by\n//!   taking a [`Bound<'py, T>`](Bound) or other type which is bound to the `'py` lifetime.\n//! - Traits which depend on the `'py` lifetime, such as [`FromPyObject<'py>`](FromPyObject), usually have\n//!   inputs or outputs which depend on the lifetime. Adding the lifetime to the trait allows\n//!   these inputs and outputs to express their binding to the GIL in the Rust type system.\n//!\n//! ## Python object smart pointers\n//!\n//! PyO3 has two core smart pointers to refer to Python objects, [`Py<T>`](Py) and its GIL-bound\n//! form [`Bound<'py, T>`](Bound) which carries the `'py` lifetime. (There is also\n//! [`Borrowed<'a, 'py, T>`](instance::Borrowed), but it is used much more rarely).\n//!\n//! The type parameter `T` in these smart pointers can be filled by:\n//!   - [`PyAny`], e.g. `Py<PyAny>` or `Bound<'py, PyAny>`, where the Python object type is not\n//!     known.\n//!   - Concrete Python types like [`PyList`](types::PyList) or [`PyTuple`](types::PyTuple).\n//!   - Rust types which are exposed to Python using the [`#[pyclass]`](macro@pyclass) macro.\n//!\n//! See the [guide][types] for an explanation of the different Python object types.\n//!\n//! ## PyErr\n//!\n//! The vast majority of operations in this library will return [`PyResult<...>`](PyResult).\n//! This is an alias for the type `Result<..., PyErr>`.\n//!\n//! A `PyErr` represents a Python exception. A `PyErr` returned to Python code will be raised as a\n//! Python exception. Errors from `PyO3` itself are also exposed as Python exceptions.\n//!\n//! # Feature flags\n//!\n//! PyO3 uses [feature flags] to enable you to opt-in to additional functionality. For a detailed\n//! description, see the [Features chapter of the guide].\n//!\n//! ## Default feature flags\n//!\n//! The following features are turned on by default:\n//! - `macros`: Enables various macros, including all the attribute macros.\n//!\n//! ## Optional feature flags\n//!\n//! The following features customize PyO3's behavior:\n//!\n//! - `abi3`: Restricts PyO3's API to a subset of the full Python API which is guaranteed by\n//! [PEP 384] to be forward-compatible with future Python versions.\n//! - `auto-initialize`: Changes [`Python::attach`] to automatically initialize the Python\n//! interpreter if needed.\n//! - `multiple-pymethods`: Enables the use of multiple [`#[pymethods]`](macro@crate::pymethods)\n//! blocks per [`#[pyclass]`](macro@crate::pyclass). This adds a dependency on the [inventory]\n//! crate, which is not supported on all platforms.\n//!\n//! The following features enable interactions with other crates in the Rust ecosystem:\n//! - [`anyhow`]: Enables a conversion from [anyhow]’s [`Error`][anyhow_error] type to [`PyErr`].\n//! - [`chrono`]: Enables a conversion from [chrono]'s structures to the equivalent Python ones.\n//! - [`chrono-tz`]: Enables a conversion from [chrono-tz]'s `Tz` enum. Requires Python 3.9+.\n//! - [`either`]: Enables conversions between Python objects and [either]'s [`Either`] type.\n//! - [`eyre`]: Enables a conversion from [eyre]’s [`Report`] type to [`PyErr`].\n//! - [`hashbrown`]: Enables conversions between Python objects and [hashbrown]'s [`HashMap`] and\n//! [`HashSet`] types.\n//! - [`indexmap`][indexmap_feature]: Enables conversions between Python dictionary and [indexmap]'s [`IndexMap`].\n//! - [`num-bigint`]: Enables conversions between Python objects and [num-bigint]'s [`BigInt`] and\n//! [`BigUint`] types.\n//! - [`num-complex`]: Enables conversions between Python objects and [num-complex]'s [`Complex`]\n//!  type.\n//! - [`num-rational`]: Enables conversions between Python's fractions.Fraction and [num-rational]'s types\n//! - [`ordered-float`]: Enables conversions between Python's float and [ordered-float]'s types\n//! - [`rust_decimal`]: Enables conversions between Python's decimal.Decimal and [rust_decimal]'s\n//! [`Decimal`] type.\n//! - [`serde`]: Allows implementing [serde]'s [`Serialize`] and [`Deserialize`] traits for\n//! [`Py`]`<T>` for all `T` that implement [`Serialize`] and [`Deserialize`].\n//! - [`smallvec`][smallvec]: Enables conversions between Python list and [smallvec]'s [`SmallVec`].\n//!\n//! ## Unstable features\n//!\n//! - `nightly`: Uses  `#![feature(auto_traits, negative_impls)]` to define [`Ungil`] as an auto trait.\n//\n//! ## `rustc` environment flags\n//! - `Py_3_7`, `Py_3_8`, `Py_3_9`, `Py_3_10`, `Py_3_11`, `Py_3_12`, `Py_3_13`: Marks code that is\n//!    only enabled when compiling for a given minimum Python version.\n//! - `Py_LIMITED_API`: Marks code enabled when the `abi3` feature flag is enabled.\n//! - `Py_GIL_DISABLED`: Marks code that runs only in the free-threaded build of CPython.\n//! - `PyPy` - Marks code enabled when compiling for PyPy.\n//! - `GraalPy` - Marks code enabled when compiling for GraalPy.\n//!\n//! Additionally, you can query for the values `Py_DEBUG`, `Py_REF_DEBUG`,\n//! `Py_TRACE_REFS`, and `COUNT_ALLOCS` from `py_sys_config` to query for the\n//! corresponding C build-time defines. For example, to conditionally define\n//! debug code using `Py_DEBUG`, you could do:\n//!\n//! ```rust,ignore\n//! #[cfg(py_sys_config = \"Py_DEBUG\")]\n//! println!(\"only runs if python was compiled with Py_DEBUG\")\n//! ```\n//! To use these attributes, add [`pyo3-build-config`] as a build dependency in\n//! your `Cargo.toml` and call `pyo3_build_config::use_pyo3_cfgs()` in a\n//! `build.rs` file.\n//!\n//! # Minimum supported Rust and Python versions\n//!\n//! Requires Rust 1.63 or greater.\n//!\n//! PyO3 supports the following Python distributions:\n//!   - CPython 3.7 or greater\n//!   - PyPy 7.3 (Python 3.11+)\n//!   - GraalPy 24.0 or greater (Python 3.10+)\n//!\n//! # Example: Building a native Python module\n//!\n//! PyO3 can be used to generate a native Python module. The easiest way to try this out for the\n//! first time is to use [`maturin`]. `maturin` is a tool for building and publishing Rust-based\n//! Python packages with minimal configuration. The following steps set up some files for an example\n//! Python module, install `maturin`, and then show how to build and import the Python module.\n//!\n//! First, create a new folder (let's call it `string_sum`) containing the following two files:\n//!\n//! **`Cargo.toml`**\n//!\n//! ```toml\n//! [package]\n//! name = \"string-sum\"\n//! version = \"0.1.0\"\n//! edition = \"2021\"\n//!\n//! [lib]\n//! name = \"string_sum\"\n//! # \"cdylib\" is necessary to produce a shared library for Python to import from.\n//! #\n//! # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able\n//! # to `use string_sum;` unless the \"rlib\" or \"lib\" crate type is also included, e.g.:\n//! # crate-type = [\"cdylib\", \"rlib\"]\n//! crate-type = [\"cdylib\"]\n//!\n//! [dependencies]\n#![doc = concat!(\"pyo3 = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\"\")]\n//! ```\n//!\n//! **`src/lib.rs`**\n//! ```rust,no_run\n//! use pyo3::prelude::*;\n//!\n//! /// Formats the sum of two numbers as string.\n//! #[pyfunction]\n//! fn sum_as_string(a: usize, b: usize) -> PyResult<String> {\n//!     Ok((a + b).to_string())\n//! }\n//!\n//! /// A Python module implemented in Rust.\n//! #[pymodule]\n//! fn string_sum(m: &Bound<'_, PyModule>) -> PyResult<()> {\n//!     m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;\n//!\n//!     Ok(())\n//! }\n//! ```\n//!\n//! With those two files in place, now `maturin` needs to be installed. This can be done using\n//! Python's package manager `pip`. First, load up a new Python `virtualenv`, and install `maturin`\n//! into it:\n//! ```bash\n//! $ cd string_sum\n//! $ python -m venv .env\n//! $ source .env/bin/activate\n//! $ pip install maturin\n//! ```\n//!\n//! Now build and execute the module:\n//! ```bash\n//! $ maturin develop\n//! # lots of progress output as maturin runs the compilation...\n//! $ python\n//! >>> import string_sum\n//! >>> string_sum.sum_as_string(5, 20)\n//! '25'\n//! ```\n//!\n//! As well as with `maturin`, it is possible to build using [setuptools-rust] or\n//! [manually][manual_builds]. Both offer more flexibility than `maturin` but require further\n//! configuration.\n//!\n//! # Example: Using Python from Rust\n//!\n//! To embed Python into a Rust binary, you need to ensure that your Python installation contains a\n//! shared library. The following steps demonstrate how to ensure this (for Ubuntu), and then give\n//! some example code which runs an embedded Python interpreter.\n//!\n//! To install the Python shared library on Ubuntu:\n//! ```bash\n//! sudo apt install python3-dev\n//! ```\n//!\n//! Start a new project with `cargo new` and add  `pyo3` to the `Cargo.toml` like this:\n//! ```toml\n//! [dependencies.pyo3]\n#![doc = concat!(\"version = \\\"\", env!(\"CARGO_PKG_VERSION\"),  \"\\\"\")]\n//! # this is necessary to automatically initialize the Python interpreter\n//! features = [\"auto-initialize\"]\n//! ```\n//!\n//! Example program displaying the value of `sys.version` and the current user name:\n//! ```rust\n//! use pyo3::prelude::*;\n//! use pyo3::types::IntoPyDict;\n//! use pyo3::ffi::c_str;\n//!\n//! fn main() -> PyResult<()> {\n//!     Python::attach(|py| {\n//!         let sys = py.import(\"sys\")?;\n//!         let version: String = sys.getattr(\"version\")?.extract()?;\n//!\n//!         let locals = [(\"os\", py.import(\"os\")?)].into_py_dict(py)?;\n//!         let code = c\"os.getenv('USER') or os.getenv('USERNAME') or 'Unknown'\";\n//!         let user: String = py.eval(code, None, Some(&locals))?.extract()?;\n//!\n//!         println!(\"Hello {}, I'm Python {}\", user, version);\n//!         Ok(())\n//!     })\n//! }\n//! ```\n//!\n//! The guide has [a section][calling_rust] with lots of examples about this topic.\n//!\n//! # Other Examples\n//!\n//! The PyO3 [README](https://github.com/PyO3/pyo3#readme) contains quick-start examples for both\n//! using [Rust from Python] and [Python from Rust].\n//!\n//! The PyO3 repository's [examples subdirectory]\n//! contains some basic packages to demonstrate usage of PyO3.\n//!\n//! There are many projects using PyO3 - see a list of some at\n//! <https://github.com/PyO3/pyo3#examples>.\n//!\n//! [anyhow]: https://docs.rs/anyhow/ \"A trait object based error system for easy idiomatic error handling in Rust applications.\"\n//! [anyhow_error]: https://docs.rs/anyhow/latest/anyhow/struct.Error.html \"Anyhows `Error` type, a wrapper around a dynamic error type\"\n//! [`anyhow`]: ./anyhow/index.html \"Documentation about the `anyhow` feature.\"\n//! [inventory]: https://docs.rs/inventory\n//! [`HashMap`]: https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html\n//! [`HashSet`]: https://docs.rs/hashbrown/latest/hashbrown/struct.HashSet.html\n//! [`SmallVec`]: https://docs.rs/smallvec/latest/smallvec/struct.SmallVec.html\n//! [`Uuid`]: https://docs.rs/uuid/latest/uuid/struct.Uuid.html\n//! [`IndexMap`]: https://docs.rs/indexmap/latest/indexmap/map/struct.IndexMap.html\n//! [`BigInt`]: https://docs.rs/num-bigint/latest/num_bigint/struct.BigInt.html\n//! [`BigUint`]: https://docs.rs/num-bigint/latest/num_bigint/struct.BigUint.html\n//! [`Complex`]: https://docs.rs/num-complex/latest/num_complex/struct.Complex.html\n//! [`Deserialize`]: https://docs.rs/serde/latest/serde/trait.Deserialize.html\n//! [`Serialize`]: https://docs.rs/serde/latest/serde/trait.Serialize.html\n//! [chrono]: https://docs.rs/chrono/ \"Date and Time for Rust.\"\n//! [chrono-tz]: https://docs.rs/chrono-tz/ \"TimeZone implementations for chrono from the IANA database.\"\n//! [`chrono`]: ./chrono/index.html \"Documentation about the `chrono` feature.\"\n//! [`chrono-tz`]: ./chrono-tz/index.html \"Documentation about the `chrono-tz` feature.\"\n//! [either]: https://docs.rs/either/ \"A type that represents one of two alternatives.\"\n//! [`either`]: ./either/index.html \"Documentation about the `either` feature.\"\n//! [`Either`]: https://docs.rs/either/latest/either/enum.Either.html\n//! [eyre]: https://docs.rs/eyre/ \"A library for easy idiomatic error handling and reporting in Rust applications.\"\n//! [`Report`]: https://docs.rs/eyre/latest/eyre/struct.Report.html\n//! [`eyre`]: ./eyre/index.html \"Documentation about the `eyre` feature.\"\n//! [`hashbrown`]: ./hashbrown/index.html \"Documentation about the `hashbrown` feature.\"\n//! [indexmap_feature]: ./indexmap/index.html \"Documentation about the `indexmap` feature.\"\n//! [`maturin`]: https://github.com/PyO3/maturin \"Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages\"\n//! [`num-bigint`]: ./num_bigint/index.html \"Documentation about the `num-bigint` feature.\"\n//! [`num-complex`]: ./num_complex/index.html \"Documentation about the `num-complex` feature.\"\n//! [`num-rational`]: ./num_rational/index.html \"Documentation about the `num-rational` feature.\"\n//! [`ordered-float`]: ./ordered_float/index.html \"Documentation about the `ordered-float` feature.\"\n//! [`pyo3-build-config`]: https://docs.rs/pyo3-build-config\n//! [rust_decimal]: https://docs.rs/rust_decimal\n//! [`rust_decimal`]: ./rust_decimal/index.html \"Documentation about the `rust_decimal` feature.\"\n//! [`Decimal`]: https://docs.rs/rust_decimal/latest/rust_decimal/struct.Decimal.html\n//! [`serde`]: <./serde/index.html> \"Documentation about the `serde` feature.\"\n#![doc = concat!(\"[calling_rust]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/python-from-rust.html \\\"Calling Python from Rust - PyO3 user guide\\\"\")]\n//! [examples subdirectory]: https://github.com/PyO3/pyo3/tree/main/examples\n//! [feature flags]: https://doc.rust-lang.org/cargo/reference/features.html \"Features - The Cargo Book\"\n//! [global interpreter lock]: https://docs.python.org/3/glossary.html#term-global-interpreter-lock\n//! [hashbrown]: https://docs.rs/hashbrown\n//! [smallvec]: https://docs.rs/smallvec\n//! [uuid]: https://docs.rs/uuid\n//! [indexmap]: https://docs.rs/indexmap\n#![doc = concat!(\"[manual_builds]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/building-and-distribution.html#manual-builds \\\"Manual builds - Building and Distribution - PyO3 user guide\\\"\")]\n//! [num-bigint]: https://docs.rs/num-bigint\n//! [num-complex]: https://docs.rs/num-complex\n//! [num-rational]: https://docs.rs/num-rational\n//! [ordered-float]: https://docs.rs/ordered-float\n//! [serde]: https://docs.rs/serde\n//! [setuptools-rust]: https://github.com/PyO3/setuptools-rust \"Setuptools plugin for Rust extensions\"\n//! [the guide]: https://pyo3.rs \"PyO3 user guide\"\n#![doc = concat!(\"[types]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/types.html \\\"GIL lifetimes, mutability and Python object types\\\"\")]\n//! [PEP 384]: https://www.python.org/dev/peps/pep-0384 \"PEP 384 -- Defining a Stable ABI\"\n//! [Python from Rust]: https://github.com/PyO3/pyo3#using-python-from-rust\n//! [Rust from Python]: https://github.com/PyO3/pyo3#using-rust-from-python\n#![doc = concat!(\"[Features chapter of the guide]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/features.html#features-reference \\\"Features Reference - PyO3 user guide\\\"\")]\n//! [`Ungil`]: crate::marker::Ungil\npub use crate::class::*;\npub use crate::conversion::{FromPyObject, IntoPyObject, IntoPyObjectExt};\npub use crate::err::{CastError, CastIntoError, PyErr, PyErrArguments, PyResult, ToPyErr};\n#[allow(deprecated)]\npub use crate::err::{DowncastError, DowncastIntoError};\npub use crate::instance::{Borrowed, Bound, BoundObject, Py};\n#[cfg(not(any(PyPy, GraalPy)))]\npub use crate::interpreter_lifecycle::with_embedded_python_interpreter;\npub use crate::marker::Python;\npub use crate::pycell::{PyRef, PyRefMut};\npub use crate::pyclass::{PyClass, PyClassGuard, PyClassGuardMut};\npub use crate::pyclass_init::PyClassInitializer;\npub use crate::type_object::{PyTypeCheck, PyTypeInfo};\npub use crate::types::PyAny;\npub use crate::version::PythonVersionInfo;\n\npub(crate) mod ffi_ptr_ext;\npub(crate) mod py_result_ext;\npub(crate) mod sealed;\n\n/// Old module which contained some implementation details of the `#[pyproto]` module.\n///\n/// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::CompareOp` instead\n/// of `use pyo3::class::basic::CompareOp`.\n///\n/// For compatibility reasons this has not yet been removed, however will be done so\n/// once <https://github.com/rust-lang/rust/issues/30827> is resolved.\npub mod class {\n    pub use self::gc::{PyTraverseError, PyVisit};\n\n    /// Old module which contained some implementation details of the `#[pyproto]` module.\n    ///\n    /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::CompareOp` instead\n    /// of `use pyo3::class::basic::CompareOp`.\n    ///\n    /// For compatibility reasons this has not yet been removed, however will be done so\n    /// once <https://github.com/rust-lang/rust/issues/30827> is resolved.\n    pub mod basic {\n        pub use crate::pyclass::CompareOp;\n    }\n\n    /// Old module which contained some implementation details of the `#[pyproto]` module.\n    ///\n    /// Prefer using the same content from `pyo3::pyclass`, e.g. `use pyo3::pyclass::PyTraverseError` instead\n    /// of `use pyo3::class::gc::PyTraverseError`.\n    ///\n    /// For compatibility reasons this has not yet been removed, however will be done so\n    /// once <https://github.com/rust-lang/rust/issues/30827> is resolved.\n    pub mod gc {\n        pub use crate::pyclass::{PyTraverseError, PyVisit};\n    }\n}\n\n#[cfg(all(feature = \"macros\", feature = \"multiple-pymethods\"))]\n#[doc(hidden)]\npub use inventory; // Re-exported for `#[pyclass]` and `#[pymethods]` with `multiple-pymethods`.\n\n/// Tests and helpers which reside inside PyO3's main library. Declared first so that macros\n/// are available in unit tests.\n#[cfg(test)]\nmod test_utils;\n#[cfg(test)]\nmod tests;\n\n// Macro dependencies, also contains macros exported for use across the codebase and\n// in expanded macros.\n#[doc(hidden)]\npub mod impl_;\n\n#[macro_use]\nmod internal_tricks;\nmod internal;\n\npub mod buffer;\npub mod call;\npub mod conversion;\nmod conversions;\n#[cfg(feature = \"experimental-async\")]\npub mod coroutine;\nmod err;\npub mod exceptions;\npub mod ffi;\npub(crate) mod fmt;\nmod instance;\nmod interpreter_lifecycle;\npub mod marker;\npub mod marshal;\n#[macro_use]\npub mod sync;\npub(crate) mod byteswriter;\npub mod panic;\npub mod pybacked;\npub mod pycell;\npub mod pyclass;\npub mod pyclass_init;\n\npub mod type_object;\npub mod types;\nmod version;\n\n#[allow(\n    unused_imports,\n    reason = \"with no features enabled this module has no public exports\"\n)]\npub use crate::conversions::*;\n\n#[cfg(feature = \"macros\")]\npub use pyo3_macros::{\n    pyfunction, pymethods, pymodule, FromPyObject, IntoPyObject, IntoPyObjectRef,\n};\n\n/// A proc macro used to expose Rust structs and fieldless enums as Python objects.\n///\n#[doc = include_str!(\"../guide/pyclass-parameters.md\")]\n///\n/// For more on creating Python classes,\n/// see the [class section of the guide][1].\n///\n#[doc = concat!(\"[1]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html\")]\n#[cfg(feature = \"macros\")]\npub use pyo3_macros::pyclass;\n\n#[cfg(feature = \"macros\")]\n#[macro_use]\nmod macros;\n\n#[cfg(feature = \"experimental-inspect\")]\npub mod inspect;\n\n// Putting the declaration of prelude at the end seems to help encourage rustc and rustdoc to prefer using\n// other paths to the same items. (e.g. `pyo3::types::PyAnyMethods` instead of `pyo3::prelude::PyAnyMethods`).\npub mod prelude;\n\n/// Test readme and user guide\n#[cfg(doctest)]\npub mod doc_test {\n    macro_rules! doctests {\n        ($($path:expr => $mod:ident),* $(,)?) => {\n            $(\n                #[doc = include_str!(concat!(\"../\", $path))]\n                mod $mod{}\n            )*\n        };\n    }\n\n    doctests! {\n        \"README.md\" => readme_md,\n        \"guide/src/advanced.md\" => guide_advanced_md,\n        \"guide/src/async-await.md\" => guide_async_await_md,\n        \"guide/src/building-and-distribution.md\" => guide_building_and_distribution_md,\n        \"guide/src/building-and-distribution/multiple-python-versions.md\" => guide_bnd_multiple_python_versions_md,\n        \"guide/src/class.md\" => guide_class_md,\n        \"guide/src/class/call.md\" => guide_class_call,\n        \"guide/src/class/object.md\" => guide_class_object,\n        \"guide/src/class/numeric.md\" => guide_class_numeric,\n        \"guide/src/class/protocols.md\" => guide_class_protocols_md,\n        \"guide/src/class/thread-safety.md\" => guide_class_thread_safety_md,\n        \"guide/src/conversions.md\" => guide_conversions_md,\n        \"guide/src/conversions/tables.md\" => guide_conversions_tables_md,\n        \"guide/src/conversions/traits.md\" => guide_conversions_traits_md,\n        \"guide/src/debugging.md\" => guide_debugging_md,\n\n        // deliberate choice not to test guide/ecosystem because those pages depend on external\n        // crates such as pyo3_asyncio.\n\n        \"guide/src/exception.md\" => guide_exception_md,\n        \"guide/src/faq.md\" => guide_faq_md,\n        \"guide/src/features.md\" => guide_features_md,\n        \"guide/src/free-threading.md\" => guide_free_threading_md,\n        \"guide/src/function.md\" => guide_function_md,\n        \"guide/src/function/error-handling.md\" => guide_function_error_handling_md,\n        \"guide/src/function/signature.md\" => guide_function_signature_md,\n        \"guide/src/migration.md\" => guide_migration_md,\n        \"guide/src/module.md\" => guide_module_md,\n        \"guide/src/parallelism.md\" => guide_parallelism_md,\n        \"guide/src/performance.md\" => guide_performance_md,\n        \"guide/src/python-from-rust.md\" => guide_python_from_rust_md,\n        \"guide/src/python-from-rust/calling-existing-code.md\" => guide_pfr_calling_existing_code_md,\n        \"guide/src/python-from-rust/function-calls.md\" => guide_pfr_function_calls_md,\n        \"guide/src/python-typing-hints.md\" => guide_python_typing_hints_md,\n        \"guide/src/rust-from-python.md\" => guide_rust_from_python_md,\n        \"guide/src/trait-bounds.md\" => guide_trait_bounds_md,\n        \"guide/src/types.md\" => guide_types_md,\n    }\n}\n"
  },
  {
    "path": "src/macros.rs",
    "content": "/// A convenient macro to execute a Python code snippet, with some local variables set.\n///\n/// # Panics\n///\n/// This macro internally calls [`Python::run`](crate::Python::run) and panics\n/// if it returns `Err`, after printing the error to stdout.\n///\n/// If you need to handle failures, please use [`Python::run`](crate::marker::Python::run) instead.\n///\n/// # Examples\n/// ```\n/// use pyo3::{prelude::*, py_run, types::PyList};\n///\n/// # fn main() -> PyResult<()> {\n/// Python::attach(|py| {\n///     let list = PyList::new(py, &[1, 2, 3])?;\n///     py_run!(py, list, \"assert list == [1, 2, 3]\");\n/// # Ok(())\n/// })\n/// # }\n/// ```\n///\n/// You can use this macro to test pyfunctions or pyclasses quickly.\n///\n/// ```\n/// use pyo3::{prelude::*, py_run};\n///\n/// #[pyclass]\n/// #[derive(Debug)]\n/// struct Time {\n///     hour: u32,\n///     minute: u32,\n///     second: u32,\n/// }\n///\n/// #[pymethods]\n/// impl Time {\n///     fn repl_japanese(&self) -> String {\n///         format!(\"{}時{}分{}秒\", self.hour, self.minute, self.second)\n///     }\n///     #[getter]\n///     fn hour(&self) -> u32 {\n///         self.hour\n///     }\n///     fn as_tuple(&self) -> (u32, u32, u32) {\n///         (self.hour, self.minute, self.second)\n///     }\n/// }\n///\n/// Python::attach(|py| {\n///     let time = Py::new(py, Time {hour: 8, minute: 43, second: 16}).unwrap();\n///     let time_as_tuple = (8, 43, 16);\n///     py_run!(py, time time_as_tuple, r#\"\n///         assert time.hour == 8\n///         assert time.repl_japanese() == \"8時43分16秒\"\n///         assert time.as_tuple() == time_as_tuple\n///     \"#);\n/// });\n/// ```\n///\n/// If you need to prepare the `locals` dict by yourself, you can pass it as `*locals`.\n///\n/// ```\n/// use pyo3::prelude::*;\n/// use pyo3::types::IntoPyDict;\n///\n/// #[pyclass]\n/// struct MyClass;\n///\n/// #[pymethods]\n/// impl MyClass {\n///     #[new]\n///     fn new() -> Self {\n///         MyClass {}\n///     }\n/// }\n///\n/// # fn main() -> PyResult<()> {\n/// Python::attach(|py| {\n///     let locals = [(\"C\", py.get_type::<MyClass>())].into_py_dict(py)?;\n///     pyo3::py_run!(py, *locals, \"c = C()\");\n/// #   Ok(())\n/// })\n/// # }\n/// ```\n#[macro_export]\nmacro_rules! py_run {\n    // unindent the code at compile time\n    ($py:expr, $($val:ident)+, $code:literal) => {{\n        $crate::py_run_impl!($py, $($val)+, $crate::impl_::unindent::unindent!($code))\n    }};\n    ($py:expr, *$dict:expr, $code:literal) => {{\n        $crate::py_run_impl!($py, *$dict, $crate::impl_::unindent::unindent!($code))\n    }};\n    // unindent the code at runtime\n    ($py:expr, $($val:ident)+, $code:expr) => {{\n        $crate::py_run_impl!($py, $($val)+, $crate::impl_::unindent::unindent($code))\n    }};\n    ($py:expr, *$dict:expr, $code:expr) => {{\n        $crate::py_run_impl!($py, *$dict, $crate::impl_::unindent::unindent($code))\n    }};\n}\n\n/// Internal implementation of the `py_run!` macro.\n///\n/// FIXME: this currently unconditionally allocates a `CString`. We should consider making this not so:\n/// - Maybe require users to pass `&CStr` / `CString`?\n/// - Maybe adjust the `unindent` code to produce `&Cstr` / `Cstring`?\n#[macro_export]\n#[doc(hidden)]\nmacro_rules! py_run_impl {\n    ($py:expr, $($val:ident)+, $code:expr) => {{\n        use $crate::types::IntoPyDict;\n        use $crate::conversion::IntoPyObject;\n        use $crate::BoundObject;\n        let d = [$((stringify!($val), (&$val).into_pyobject($py).unwrap().into_any().into_bound()),)+].into_py_dict($py).unwrap();\n        $crate::py_run_impl!($py, *d, $code)\n    }};\n    ($py:expr, *$dict:expr, $code:expr) => {{\n        use ::std::option::Option::*;\n        if let ::std::result::Result::Err(e) = $py.run(&::std::ffi::CString::new($code).unwrap(), None, Some(&$dict)) {\n            e.print($py);\n            // So when this c api function the last line called printed the error to stderr,\n            // the output is only written into a buffer which is never flushed because we\n            // panic before flushing. This is where this hack comes into place\n            $py.run(c\"import sys; sys.stderr.flush()\", None, None)\n                .unwrap();\n            ::std::panic!(\"{}\", $code)\n        }\n    }};\n}\n\n/// Wraps a Rust function annotated with [`#[pyfunction]`](macro@crate::pyfunction).\n///\n/// This can be used with [`PyModule::add_function`](crate::types::PyModuleMethods::add_function) to\n/// add free functions to a [`PyModule`](crate::types::PyModule) - see its documentation for more\n/// information.\n#[macro_export]\nmacro_rules! wrap_pyfunction {\n    ($function:path) => {\n        &|py_or_module| {\n            use $function as wrapped_pyfunction;\n            $crate::impl_::pyfunction::WrapPyFunctionArg::wrap_pyfunction(\n                py_or_module,\n                &wrapped_pyfunction::_PYO3_DEF,\n            )\n        }\n    };\n    ($function:path, $py_or_module:expr) => {{\n        use $function as wrapped_pyfunction;\n        $crate::impl_::pyfunction::WrapPyFunctionArg::wrap_pyfunction(\n            $py_or_module,\n            &wrapped_pyfunction::_PYO3_DEF,\n        )\n    }};\n}\n\n/// Returns a function that takes a [`Python`](crate::Python) instance and returns a\n/// Python module.\n///\n/// Use this together with [`#[pymodule]`](crate::pymodule) and\n/// [`PyModule::add_wrapped`](crate::types::PyModuleMethods::add_wrapped).\n#[macro_export]\nmacro_rules! wrap_pymodule {\n    ($module:path) => {\n        &|py| {\n            use $module as wrapped_pymodule;\n            wrapped_pymodule::_PYO3_DEF\n                .make_module(py)\n                .expect(\"failed to wrap pymodule\")\n        }\n    };\n}\n\n/// Add the module to the initialization table in order to make embedded Python code to use it.\n/// Module name is the argument.\n///\n/// Use it before [`Python::initialize`](crate::marker::Python::initialize) and\n/// leave feature `auto-initialize` off\n#[cfg(not(any(PyPy, GraalPy)))]\n#[macro_export]\nmacro_rules! append_to_inittab {\n    ($module:ident) => {\n        unsafe {\n            if $crate::ffi::Py_IsInitialized() != 0 {\n                ::std::panic!(\n                    \"called `append_to_inittab` but a Python interpreter is already running.\"\n                );\n            }\n            $crate::ffi::PyImport_AppendInittab(\n                $module::__PYO3_NAME.as_ptr(),\n                ::std::option::Option::Some($module::__pyo3_init),\n            );\n        }\n    };\n}\n"
  },
  {
    "path": "src/marker.rs",
    "content": "//! Fundamental properties of objects tied to the Python interpreter.\n//!\n//! The Python interpreter is not thread-safe. To protect the Python interpreter in multithreaded\n//! scenarios there is a global lock, the *global interpreter lock* (hereafter referred to as *GIL*)\n//! that must be held to safely interact with Python objects. This is why in PyO3 when you acquire\n//! the GIL you get a [`Python`] marker token that carries the *lifetime* of holding the GIL and all\n//! borrowed references to Python objects carry this lifetime as well. This will statically ensure\n//! that you can never use Python objects after dropping the lock - if you mess this up it will be\n//! caught at compile time and your program will fail to compile.\n//!\n//! It also supports this pattern that many extension modules employ:\n//! - Drop the GIL, so that other Python threads can acquire it and make progress themselves\n//! - Do something independently of the Python interpreter, like IO, a long running calculation or\n//!   awaiting a future\n//! - Once that is done, reacquire the GIL\n//!\n//! That API is provided by [`Python::detach`] and enforced via the [`Ungil`] bound on the\n//! closure and the return type. This is done by relying on the [`Send`] auto trait. `Ungil` is\n//! defined as the following:\n//!\n//! ```rust,no_run\n//! # #![allow(dead_code)]\n//! pub unsafe trait Ungil {}\n//!\n//! unsafe impl<T: Send> Ungil for T {}\n//! ```\n//!\n//! We piggy-back off the `Send` auto trait because it is not possible to implement custom auto\n//! traits on stable Rust. This is the solution which enables it for as many types as possible while\n//! making the API usable.\n//!\n//! In practice this API works quite well, but it comes with some drawbacks:\n//!\n//! ## Drawbacks\n//!\n//! There is no reason to prevent `!Send` types like [`Rc`] from crossing the closure. After all,\n//! [`Python::detach`] just lets other Python threads run - it does not itself launch a new\n//! thread.\n//!\n//! ```rust, compile_fail\n//! # #[cfg(feature = \"nightly\")]\n//! # compile_error!(\"this actually works on nightly\")\n//! use pyo3::prelude::*;\n//! use std::rc::Rc;\n//!\n//! fn main() {\n//!     Python::attach(|py| {\n//!         let rc = Rc::new(5);\n//!\n//!         py.detach(|| {\n//!             // This would actually be fine...\n//!             println!(\"{:?}\", *rc);\n//!         });\n//!     });\n//! }\n//! ```\n//!\n//! Because we are using `Send` for something it's not quite meant for, other code that\n//! (correctly) upholds the invariants of [`Send`] can cause problems.\n//!\n//! [`SendWrapper`] is one of those. Per its documentation:\n//!\n//! > A wrapper which allows you to move around non-Send-types between threads, as long as you\n//! > access the contained value only from within the original thread and make sure that it is\n//! > dropped from within the original thread.\n//!\n//! This will \"work\" to smuggle Python references across the closure, because we're not actually\n//! doing anything with threads:\n//!\n//! ```rust, no_run\n//! use pyo3::prelude::*;\n//! use pyo3::types::PyString;\n//! use send_wrapper::SendWrapper;\n//!\n//! Python::attach(|py| {\n//!     let string = PyString::new(py, \"foo\");\n//!\n//!     let wrapped = SendWrapper::new(string);\n//!\n//!     py.detach(|| {\n//! # #[cfg(not(feature = \"nightly\"))]\n//! # {\n//!         // 💥 Unsound! 💥\n//!         let smuggled: &Bound<'_, PyString> = &*wrapped;\n//!         println!(\"{:?}\", smuggled);\n//! # }\n//!     });\n//! });\n//! ```\n//!\n//! For now the answer to that is \"don't do that\".\n//!\n//! # A proper implementation using an auto trait\n//!\n//! However on nightly Rust and when PyO3's `nightly` feature is\n//! enabled, `Ungil` is defined as the following:\n//!\n//! ```rust,no_run\n//! # #[cfg(any())]\n//! # {\n//! #![feature(auto_traits, negative_impls)]\n//!\n//! pub unsafe auto trait Ungil {}\n//!\n//! // It is unimplemented for the `Python` struct and Python objects.\n//! impl !Ungil for Python<'_> {}\n//! impl !Ungil for ffi::PyObject {}\n//!\n//! // `Py` wraps it in  a safe api, so this is OK\n//! unsafe impl<T> Ungil for Py<T> {}\n//! # }\n//! ```\n//!\n//! With this feature enabled, the above two examples will start working and not working, respectively.\n//!\n//! [`SendWrapper`]: https://docs.rs/send_wrapper/latest/send_wrapper/struct.SendWrapper.html\n//! [`Rc`]: std::rc::Rc\n//! [`Py`]: crate::Py\nuse crate::conversion::IntoPyObject;\nuse crate::err::{self, PyResult};\nuse crate::internal::state::{AttachGuard, SuspendAttach};\nuse crate::types::any::PyAnyMethods;\nuse crate::types::{\n    PyAny, PyCode, PyCodeMethods, PyDict, PyEllipsis, PyModule, PyNone, PyNotImplemented, PyString,\n    PyType,\n};\nuse crate::version::PythonVersionInfo;\nuse crate::{ffi, Bound, Py, PyTypeInfo};\nuse std::ffi::CStr;\nuse std::marker::PhantomData;\n\n/// Types that are safe to access while the GIL is not held.\n///\n/// # Safety\n///\n/// The type must not carry borrowed Python references or, if it does, not allow access to them if\n/// the GIL is not held.\n///\n/// See the [module-level documentation](self) for more information.\n///\n/// # Examples\n///\n/// This tracking is currently imprecise as it relies on the [`Send`] auto trait on stable Rust.\n/// For example, an `Rc` smart pointer should be usable without the GIL, but we currently prevent that:\n///\n/// ```compile_fail\n/// # use pyo3::prelude::*;\n/// use std::rc::Rc;\n///\n/// Python::attach(|py| {\n///     let rc = Rc::new(42);\n///\n///     py.detach(|| {\n///         println!(\"{:?}\", rc);\n///     });\n/// });\n/// ```\n///\n/// This also implies that the interplay between `attach` and `detach` is unsound, for example\n/// one can circumvent this protection using the [`send_wrapper`](https://docs.rs/send_wrapper/) crate:\n///\n/// ```no_run\n/// # use pyo3::prelude::*;\n/// # use pyo3::types::PyString;\n/// use send_wrapper::SendWrapper;\n///\n/// Python::attach(|py| {\n///     let string = PyString::new(py, \"foo\");\n///\n///     let wrapped = SendWrapper::new(string);\n///\n///     py.detach(|| {\n///         let sneaky: &Bound<'_, PyString> = &*wrapped;\n///\n///         println!(\"{:?}\", sneaky);\n///     });\n/// });\n/// ```\n///\n/// Fixing this loophole on stable Rust has significant ergonomic issues, but it is fixed when using\n/// nightly Rust and the `nightly` feature, c.f. [#2141](https://github.com/PyO3/pyo3/issues/2141).\n#[cfg_attr(docsrs, doc(cfg(all())))] // Hide the cfg flag\n#[cfg(not(feature = \"nightly\"))]\npub unsafe trait Ungil {}\n\n#[cfg_attr(docsrs, doc(cfg(all())))] // Hide the cfg flag\n#[cfg(not(feature = \"nightly\"))]\nunsafe impl<T: Send> Ungil for T {}\n\n#[cfg(feature = \"nightly\")]\nmod nightly {\n    macro_rules! define {\n        ($($tt:tt)*) => { $($tt)* }\n    }\n\n    define! {\n        /// Types that are safe to access while the GIL is not held.\n        ///\n        /// # Safety\n        ///\n        /// The type must not carry borrowed Python references or, if it does, not allow access to them if\n        /// the GIL is not held.\n        ///\n        /// See the [module-level documentation](self) for more information.\n        ///\n        /// # Examples\n        ///\n        /// Types which are `Ungil` cannot be used in contexts where the GIL was released, e.g.\n        ///\n        /// ```compile_fail\n        /// # use pyo3::prelude::*;\n        /// # use pyo3::types::PyString;\n        /// Python::attach(|py| {\n        ///     let string = PyString::new(py, \"foo\");\n        ///\n        ///     py.detach(|| {\n        ///         println!(\"{:?}\", string);\n        ///     });\n        /// });\n        /// ```\n        ///\n        /// This applies to the [`Python`] token itself as well, e.g.\n        ///\n        /// ```compile_fail\n        /// # use pyo3::prelude::*;\n        /// Python::attach(|py| {\n        ///     py.detach(|| {\n        ///         drop(py);\n        ///     });\n        /// });\n        /// ```\n        ///\n        /// On nightly Rust, this is not based on the [`Send`] auto trait and hence we are able\n        /// to prevent incorrectly circumventing it using e.g. the [`send_wrapper`](https://docs.rs/send_wrapper/) crate:\n        ///\n        /// ```compile_fail\n        /// # use pyo3::prelude::*;\n        /// # use pyo3::types::PyString;\n        /// use send_wrapper::SendWrapper;\n        ///\n        /// Python::attach(|py| {\n        ///     let string = PyString::new(py, \"foo\");\n        ///\n        ///     let wrapped = SendWrapper::new(string);\n        ///\n        ///     py.detach(|| {\n        ///         let sneaky: &PyString = *wrapped;\n        ///\n        ///         println!(\"{:?}\", sneaky);\n        ///     });\n        /// });\n        /// ```\n        ///\n        /// This also enables using non-[`Send`] types in `detach`,\n        /// at least if they are not also bound to the GIL:\n        ///\n        /// ```rust\n        /// # use pyo3::prelude::*;\n        /// use std::rc::Rc;\n        ///\n        /// Python::attach(|py| {\n        ///     let rc = Rc::new(42);\n        ///\n        ///     py.detach(|| {\n        ///         println!(\"{:?}\", rc);\n        ///     });\n        /// });\n        /// ```\n        pub unsafe auto trait Ungil {}\n    }\n\n    impl !Ungil for crate::Python<'_> {}\n\n    // This means that PyString, PyList, etc all inherit !Ungil from  this.\n    impl !Ungil for crate::PyAny {}\n\n    impl<T> !Ungil for crate::PyRef<'_, T> {}\n    impl<T> !Ungil for crate::PyRefMut<'_, T> {}\n\n    // FFI pointees\n    impl !Ungil for crate::ffi::PyObject {}\n    impl !Ungil for crate::ffi::PyLongObject {}\n\n    impl !Ungil for crate::ffi::PyThreadState {}\n    impl !Ungil for crate::ffi::PyInterpreterState {}\n    impl !Ungil for crate::ffi::PyWeakReference {}\n    impl !Ungil for crate::ffi::PyFrameObject {}\n    impl !Ungil for crate::ffi::PyCodeObject {}\n    #[cfg(not(Py_LIMITED_API))]\n    impl !Ungil for crate::ffi::PyDictKeysObject {}\n    #[cfg(not(any(Py_LIMITED_API, Py_3_10)))]\n    impl !Ungil for crate::ffi::PyArena {}\n}\n\n#[cfg(feature = \"nightly\")]\npub use nightly::Ungil;\n\n/// A marker token that represents holding the GIL.\n///\n/// It serves three main purposes:\n/// - It provides a global API for the Python interpreter, such as [`Python::eval`].\n/// - It can be passed to functions that require a proof of holding the GIL, such as\n///   [`Py::clone_ref`](crate::Py::clone_ref).\n/// - Its lifetime represents the scope of holding the GIL which can be used to create Rust\n///   references that are bound to it, such as [`Bound<'py, PyAny>`].\n///\n/// Note that there are some caveats to using it that you might need to be aware of. See the\n/// [Deadlocks](#deadlocks) and [Releasing and freeing memory](#releasing-and-freeing-memory)\n/// paragraphs for more information about that.\n///\n/// # Obtaining a Python token\n///\n/// The following are the recommended ways to obtain a [`Python<'py>`] token, in order of preference:\n/// - If you already have something with a lifetime bound to the GIL, such as [`Bound<'py, PyAny>`], you can\n///   use its `.py()` method to get a token.\n/// - In a function or method annotated with [`#[pyfunction]`](crate::pyfunction) or [`#[pymethods]`](crate::pymethods) you can declare it\n///   as a parameter, and PyO3 will pass in the token when Python code calls it.\n/// - When you need to acquire the GIL yourself, such as when calling Python code from Rust, you\n///   should call [`Python::attach`] to do that and pass your code as a closure to it.\n///\n/// The first two options are zero-cost; [`Python::attach`] requires runtime checking and may need to block\n/// to acquire the GIL.\n///\n/// # Deadlocks\n///\n/// Note that the GIL can be temporarily released by the Python interpreter during a function call\n/// (e.g. importing a module). In general, you don't need to worry about this because the GIL is\n/// reacquired before returning to the Rust code:\n///\n/// ```text\n/// `Python` exists   |=====================================|\n/// GIL actually held |==========|         |================|\n/// Rust code running |=======|                |==|  |======|\n/// ```\n///\n/// This behaviour can cause deadlocks when trying to lock a Rust mutex while holding the GIL:\n///\n///  * Thread 1 acquires the GIL\n///  * Thread 1 locks a mutex\n///  * Thread 1 makes a call into the Python interpreter which releases the GIL\n///  * Thread 2 acquires the GIL\n///  * Thread 2 tries to locks the mutex, blocks\n///  * Thread 1's Python interpreter call blocks trying to reacquire the GIL held by thread 2\n///\n/// To avoid deadlocking, you should release the GIL before trying to lock a mutex or `await`ing in\n/// asynchronous code, e.g. with [`Python::detach`].\n///\n/// # Releasing and freeing memory\n///\n/// The [`Python<'py>`] type can be used to create references to variables owned by the Python\n/// interpreter, using functions such as [`Python::eval`] and [`PyModule::import`].\n#[derive(Copy, Clone)]\npub struct Python<'py>(PhantomData<&'py AttachGuard>, PhantomData<NotSend>);\n\n/// A marker type that makes the type !Send.\n/// Workaround for lack of !Send on stable (<https://github.com/rust-lang/rust/issues/68318>).\nstruct NotSend(PhantomData<*mut Python<'static>>);\n\nimpl Python<'_> {\n    /// Acquires the global interpreter lock, allowing access to the Python interpreter. The\n    /// provided closure `F` will be executed with the acquired `Python` marker token.\n    ///\n    /// If implementing [`#[pymethods]`](crate::pymethods) or [`#[pyfunction]`](crate::pyfunction),\n    /// declare `py: Python` as an argument. PyO3 will pass in the token to grant access to the GIL\n    /// context in which the function is running, avoiding the need to call `attach`.\n    ///\n    /// If the [`auto-initialize`] feature is enabled and the Python runtime is not already\n    /// initialized, this function will initialize it. See\n    #[cfg_attr(\n        not(any(PyPy, GraalPy)),\n        doc = \"[`Python::initialize`](crate::marker::Python::initialize)\"\n    )]\n    #[cfg_attr(PyPy, doc = \"`Python::initialize\")]\n    /// for details.\n    ///\n    /// If the current thread does not yet have a Python \"thread state\" associated with it,\n    /// a new one will be automatically created before `F` is executed and destroyed after `F`\n    /// completes.\n    ///\n    /// # Panics\n    ///\n    /// - If the [`auto-initialize`] feature is not enabled and the Python interpreter is not\n    ///   initialized.\n    /// - If the Python interpreter is in the process of [shutting down].\n    /// - If the current thread is currently in the middle of a GC traversal (i.e. called from\n    ///   within a `__traverse__` method).\n    ///\n    /// To avoid possible initialization or panics if calling in a context where the Python\n    /// interpreter might be unavailable, consider using [`Python::try_attach`].\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use pyo3::prelude::*;\n    /// use pyo3::ffi::c_str;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let x: i32 = py.eval(c\"5\", None, None)?.extract()?;\n    ///     assert_eq!(x, 5);\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    ///\n    /// [`auto-initialize`]: https://pyo3.rs/main/features.html#auto-initialize\n    /// [shutting down]: https://docs.python.org/3/glossary.html#term-interpreter-shutdown\n    #[inline]\n    #[track_caller]\n    pub fn attach<F, R>(f: F) -> R\n    where\n        F: for<'py> FnOnce(Python<'py>) -> R,\n    {\n        let guard = AttachGuard::attach();\n        f(guard.python())\n    }\n\n    /// Variant of [`Python::attach`] which will return without attaching to the Python\n    /// interpreter if the interpreter is in a state where it cannot be attached to:\n    ///\n    /// - If the Python interpreter is not initialized.\n    /// - If the Python interpreter is in the process of [shutting down].\n    /// - If the current thread is currently in the middle of a GC traversal (i.e. called from\n    ///   within a `__traverse__` method).\n    ///\n    /// Unlike `Python::attach`, this function will not initialize the Python interpreter,\n    /// even if the [`auto-initialize`] feature is enabled.\n    ///\n    /// Note that due to the nature of the underlying Python APIs used to implement this,\n    /// the behavior is currently provided on a best-effort basis; it is expected that a\n    /// future CPython version will introduce APIs which guarantee this behaviour. This\n    /// function is still recommended for use in the meanwhile as it provides the best\n    /// possible behaviour and should transparently change to an optimal implementation\n    /// once such APIs are available.\n    ///\n    /// [`auto-initialize`]: https://pyo3.rs/main/features.html#auto-initialize\n    /// [shutting down]: https://docs.python.org/3/glossary.html#term-interpreter-shutdown\n    #[inline]\n    #[track_caller]\n    pub fn try_attach<F, R>(f: F) -> Option<R>\n    where\n        F: for<'py> FnOnce(Python<'py>) -> R,\n    {\n        let guard = AttachGuard::try_attach().ok()?;\n        Some(f(guard.python()))\n    }\n\n    /// Prepares the use of Python.\n    ///\n    /// If the Python interpreter is not already initialized, this function will initialize it with\n    /// signal handling disabled (Python will not raise the `KeyboardInterrupt` exception). Python\n    /// signal handling depends on the notion of a 'main thread', which must be the thread that\n    /// initializes the Python interpreter.\n    ///\n    /// If the Python interpreter is already initialized, this function has no effect.\n    ///\n    /// This function is unavailable under PyPy because PyPy cannot be embedded in Rust (or any other\n    /// software). Support for this is tracked on the\n    /// [PyPy issue tracker](https://github.com/pypy/pypy/issues/3836).\n    ///\n    /// # Examples\n    /// ```rust\n    /// use pyo3::prelude::*;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::initialize();\n    /// Python::attach(|py| py.run(c\"print('Hello World')\", None, None))\n    /// # }\n    /// ```\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn initialize() {\n        crate::interpreter_lifecycle::initialize();\n    }\n\n    /// Like [`Python::attach`] except Python interpreter state checking is skipped.\n    ///\n    /// Normally when attaching to the Python interpreter, PyO3 checks that it is in\n    /// an appropriate state (e.g. it is fully initialized). This function skips\n    /// those checks.\n    ///\n    /// # Safety\n    ///\n    /// If [`Python::attach`] would succeed, it is safe to call this function.\n    #[inline]\n    #[track_caller]\n    pub unsafe fn attach_unchecked<F, R>(f: F) -> R\n    where\n        F: for<'py> FnOnce(Python<'py>) -> R,\n    {\n        let guard = unsafe { AttachGuard::attach_unchecked() };\n\n        f(guard.python())\n    }\n}\n\nimpl<'py> Python<'py> {\n    /// Temporarily releases the GIL, thus allowing other Python threads to run. The GIL will be\n    /// reacquired when `F`'s scope ends.\n    ///\n    /// If you don't need to touch the Python\n    /// interpreter for some time and have other Python threads around, this will let you run\n    /// Rust-only code while letting those other Python threads make progress.\n    ///\n    /// Only types that implement [`Ungil`] can cross the closure. See the\n    /// [module level documentation](self) for more information.\n    ///\n    /// If you need to pass Python objects into the closure you can use [`Py`]`<T>`to create a\n    /// reference independent of the GIL lifetime. However, you cannot do much with those without a\n    /// [`Python`] token, for which you'd need to reacquire the GIL.\n    ///\n    /// # Example: Releasing the GIL while running a computation in Rust-only code\n    ///\n    /// ```\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyfunction]\n    /// fn sum_numbers(py: Python<'_>, numbers: Vec<u32>) -> PyResult<u32> {\n    ///     // We release the GIL here so any other Python threads get a chance to run.\n    ///     py.detach(move || {\n    ///         // An example of an \"expensive\" Rust calculation\n    ///         let sum = numbers.iter().sum();\n    ///\n    ///         Ok(sum)\n    ///     })\n    /// }\n    /// #\n    /// # fn main() -> PyResult<()> {\n    /// #     Python::attach(|py| -> PyResult<()> {\n    /// #         let fun = pyo3::wrap_pyfunction!(sum_numbers, py)?;\n    /// #         let res = fun.call1((vec![1_u32, 2, 3],))?;\n    /// #         assert_eq!(res.extract::<u32>()?, 6_u32);\n    /// #         Ok(())\n    /// #     })\n    /// # }\n    /// ```\n    ///\n    /// Please see the [Parallelism] chapter of the guide for a thorough discussion of using\n    /// [`Python::detach`] in this manner.\n    ///\n    /// # Example: Passing borrowed Python references into the closure is not allowed\n    ///\n    /// ```compile_fail\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyString;\n    ///\n    /// fn parallel_print(py: Python<'_>) {\n    ///     let s = PyString::new(py, \"This object cannot be accessed without holding the GIL >_<\");\n    ///     py.detach(move || {\n    ///         println!(\"{:?}\", s); // This causes a compile error.\n    ///     });\n    /// }\n    /// ```\n    ///\n    /// [`Py`]: crate::Py\n    /// [`PyString`]: crate::types::PyString\n    /// [auto-traits]: https://doc.rust-lang.org/nightly/unstable-book/language-features/auto-traits.html\n    /// [Parallelism]: https://pyo3.rs/main/parallelism.html\n    pub fn detach<T, F>(self, f: F) -> T\n    where\n        F: Ungil + FnOnce() -> T,\n        T: Ungil,\n    {\n        // Use a guard pattern to handle reacquiring the GIL,\n        // so that the GIL will be reacquired even if `f` panics.\n        // The `Send` bound on the closure prevents the user from\n        // transferring the `Python` token into the closure.\n        let _guard = unsafe { SuspendAttach::new() };\n        f()\n    }\n\n    /// Evaluates a Python expression in the given context and returns the result.\n    ///\n    /// If `globals` is `None`, it defaults to Python module `__main__`.\n    /// If `locals` is `None`, it defaults to the value of `globals`.\n    ///\n    /// If `globals` doesn't contain `__builtins__`, default `__builtins__`\n    /// will be added automatically.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use pyo3::prelude::*;\n    /// # use pyo3::ffi::c_str;\n    /// # Python::attach(|py| {\n    /// let result = py.eval(c\"[i * 10 for i in range(5)]\", None, None).unwrap();\n    /// let res: Vec<i64> = result.extract().unwrap();\n    /// assert_eq!(res, vec![0, 10, 20, 30, 40])\n    /// # });\n    /// ```\n    pub fn eval(\n        self,\n        code: &CStr,\n        globals: Option<&Bound<'py, PyDict>>,\n        locals: Option<&Bound<'py, PyDict>>,\n    ) -> PyResult<Bound<'py, PyAny>> {\n        let code = PyCode::compile(self, code, c\"<string>\", crate::types::PyCodeInput::Eval)?;\n        code.run(globals, locals)\n    }\n\n    /// Executes one or more Python statements in the given context.\n    ///\n    /// If `globals` is `None`, it defaults to Python module `__main__`.\n    /// If `locals` is `None`, it defaults to the value of `globals`.\n    ///\n    /// If `globals` doesn't contain `__builtins__`, default `__builtins__`\n    /// will be added automatically.\n    ///\n    /// # Examples\n    /// ```\n    /// use pyo3::{\n    ///     prelude::*,\n    ///     types::{PyBytes, PyDict},\n    ///     ffi::c_str,\n    /// };\n    /// Python::attach(|py| {\n    ///     let locals = PyDict::new(py);\n    ///     py.run(cr#\"\n    /// import base64\n    /// s = 'Hello Rust!'\n    /// ret = base64.b64encode(s.encode('utf-8'))\n    /// \"#,\n    ///         None,\n    ///         Some(&locals),\n    ///     )\n    ///     .unwrap();\n    ///     let ret = locals.get_item(\"ret\").unwrap().unwrap();\n    ///     let b64 = ret.cast::<PyBytes>().unwrap();\n    ///     assert_eq!(b64.as_bytes(), b\"SGVsbG8gUnVzdCE=\");\n    /// });\n    /// ```\n    ///\n    /// You can use [`py_run!`](macro.py_run.html) for a handy alternative of `run`\n    /// if you don't need `globals` and unwrapping is OK.\n    pub fn run(\n        self,\n        code: &CStr,\n        globals: Option<&Bound<'py, PyDict>>,\n        locals: Option<&Bound<'py, PyDict>>,\n    ) -> PyResult<()> {\n        let code = PyCode::compile(self, code, c\"<string>\", crate::types::PyCodeInput::File)?;\n        code.run(globals, locals).map(|obj| {\n            debug_assert!(obj.is_none());\n        })\n    }\n\n    /// Gets the Python type object for type `T`.\n    #[inline]\n    pub fn get_type<T>(self) -> Bound<'py, PyType>\n    where\n        T: PyTypeInfo,\n    {\n        T::type_object(self)\n    }\n\n    /// Imports the Python module with the specified name.\n    pub fn import<N>(self, name: N) -> PyResult<Bound<'py, PyModule>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n    {\n        PyModule::import(self, name)\n    }\n\n    /// Gets the Python builtin value `None`.\n    #[allow(non_snake_case)] // the Python keyword starts with uppercase\n    #[inline]\n    pub fn None(self) -> Py<PyAny> {\n        PyNone::get(self).to_owned().into_any().unbind()\n    }\n\n    /// Gets the Python builtin value `Ellipsis`, or `...`.\n    #[allow(non_snake_case)] // the Python keyword starts with uppercase\n    #[inline]\n    pub fn Ellipsis(self) -> Py<PyAny> {\n        PyEllipsis::get(self).to_owned().into_any().unbind()\n    }\n\n    /// Gets the Python builtin value `NotImplemented`.\n    #[allow(non_snake_case)] // the Python keyword starts with uppercase\n    #[inline]\n    pub fn NotImplemented(self) -> Py<PyAny> {\n        PyNotImplemented::get(self).to_owned().into_any().unbind()\n    }\n\n    /// Gets the running Python interpreter version as a string.\n    ///\n    /// # Examples\n    /// ```rust\n    /// # use pyo3::Python;\n    /// Python::attach(|py| {\n    ///     // The full string could be, for example:\n    ///     // \"3.10.0 (tags/v3.10.0:b494f59, Oct  4 2021, 19:00:18) [MSC v.1929 64 bit (AMD64)]\"\n    ///     assert!(py.version().starts_with(\"3.\"));\n    /// });\n    /// ```\n    pub fn version(self) -> &'py str {\n        unsafe {\n            CStr::from_ptr(ffi::Py_GetVersion())\n                .to_str()\n                .expect(\"Python version string not UTF-8\")\n        }\n    }\n\n    /// Gets the running Python interpreter version as a struct similar to\n    /// `sys.version_info`.\n    ///\n    /// # Examples\n    /// ```rust\n    /// # use pyo3::Python;\n    /// Python::attach(|py| {\n    ///     // PyO3 supports Python 3.7 and up.\n    ///     assert!(py.version_info() >= (3, 7));\n    ///     assert!(py.version_info() >= (3, 7, 0));\n    /// });\n    /// ```\n    pub fn version_info(self) -> PythonVersionInfo<'py> {\n        let version_str = self.version();\n\n        // Portion of the version string returned by Py_GetVersion up to the first space is the\n        // version number.\n        let version_number_str = version_str.split(' ').next().unwrap_or(version_str);\n\n        PythonVersionInfo::from_str(version_number_str).unwrap()\n    }\n\n    /// Lets the Python interpreter check and handle any pending signals. This will invoke the\n    /// corresponding signal handlers registered in Python (if any).\n    ///\n    /// Returns `Err(`[`PyErr`](crate::PyErr)`)` if any signal handler raises an exception.\n    ///\n    /// These signals include `SIGINT` (normally raised by CTRL + C), which by default raises\n    /// `KeyboardInterrupt`. For this reason it is good practice to call this function regularly\n    /// as part of long-running Rust functions so that users can cancel it.\n    ///\n    /// # Example\n    ///\n    /// ```rust,no_run\n    /// # #![allow(dead_code)] // this example is quite impractical to test\n    /// use pyo3::prelude::*;\n    ///\n    /// # fn main() {\n    /// #[pyfunction]\n    /// fn loop_forever(py: Python<'_>) -> PyResult<()> {\n    ///     loop {\n    ///         // As this loop is infinite it should check for signals every once in a while.\n    ///         // Using `?` causes any `PyErr` (potentially containing `KeyboardInterrupt`)\n    ///         // to break out of the loop.\n    ///         py.check_signals()?;\n    ///\n    ///         // do work here\n    ///         # break Ok(()) // don't actually loop forever\n    ///     }\n    /// }\n    /// # }\n    /// ```\n    ///\n    /// # Note\n    ///\n    /// This function calls [`PyErr_CheckSignals()`][1] which in turn may call signal handlers.\n    /// As Python's [`signal`][2] API allows users to define custom signal handlers, calling this\n    /// function allows arbitrary Python code inside signal handlers to run.\n    ///\n    /// If the function is called from a non-main thread, or under a non-main Python interpreter,\n    /// it does nothing yet still returns `Ok(())`.\n    ///\n    /// [1]: https://docs.python.org/3/c-api/exceptions.html?highlight=pyerr_checksignals#c.PyErr_CheckSignals\n    /// [2]: https://docs.python.org/3/library/signal.html\n    pub fn check_signals(self) -> PyResult<()> {\n        err::error_on_minusone(self, unsafe { ffi::PyErr_CheckSignals() })\n    }\n}\n\nimpl<'unbound> Python<'unbound> {\n    /// Unsafely creates a Python token with an unbounded lifetime.\n    ///\n    /// Many of PyO3 APIs use [`Python<'_>`] as proof that the calling thread is attached to the\n    /// interpreter, but this function can be used to call them unsafely.\n    ///\n    /// # Safety\n    ///\n    /// - This token and any borrowed Python references derived from it can only be safely used\n    ///   whilst the currently executing thread is actually attached to the interpreter.\n    /// - This function creates a token with an *unbounded* lifetime. Safe code can assume that\n    ///   holding a [`Python<'py>`] token means the thread is attached and stays attached for the\n    ///   lifetime `'py`. If you let it or borrowed Python references escape to safe code you are\n    ///   responsible for bounding the lifetime `'unbound` appropriately. For more on unbounded\n    ///   lifetimes, see the [nomicon].\n    ///\n    /// [nomicon]: https://doc.rust-lang.org/nomicon/unbounded-lifetimes.html\n    #[inline]\n    pub unsafe fn assume_attached() -> Python<'unbound> {\n        Python(PhantomData, PhantomData)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::{\n        internal::state::ForbidAttaching,\n        types::{IntoPyDict, PyList},\n    };\n\n    #[test]\n    fn test_eval() {\n        Python::attach(|py| {\n            // Make sure builtin names are accessible\n            let v: i32 = py\n                .eval(c\"min(1, 2)\", None, None)\n                .map_err(|e| e.display(py))\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(v, 1);\n\n            let d = [(\"foo\", 13)].into_py_dict(py).unwrap();\n\n            // Inject our own global namespace\n            let v: i32 = py\n                .eval(c\"foo + 29\", Some(&d), None)\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(v, 42);\n\n            // Inject our own local namespace\n            let v: i32 = py\n                .eval(c\"foo + 29\", None, Some(&d))\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(v, 42);\n\n            // Make sure builtin names are still accessible when using a local namespace\n            let v: i32 = py\n                .eval(c\"min(foo, 2)\", None, Some(&d))\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(v, 2);\n        });\n    }\n\n    #[test]\n    #[cfg(not(target_arch = \"wasm32\"))] // We are building wasm Python with pthreads disabled\n    fn test_detach_releases_and_acquires_gil() {\n        Python::attach(|py| {\n            let b = std::sync::Arc::new(std::sync::Barrier::new(2));\n\n            let b2 = b.clone();\n            std::thread::spawn(move || Python::attach(|_| b2.wait()));\n\n            py.detach(|| {\n                // If `detach` does not release the GIL, this will deadlock because\n                // the thread spawned above will never be able to acquire the GIL.\n                b.wait();\n            });\n\n            unsafe {\n                // If the GIL is not reacquired at the end of `detach`, this call\n                // will crash the Python interpreter.\n                let tstate = ffi::PyEval_SaveThread();\n                ffi::PyEval_RestoreThread(tstate);\n            }\n        });\n    }\n\n    #[test]\n    #[cfg(panic = \"unwind\")]\n    fn test_detach_panics_safely() {\n        Python::attach(|py| {\n            let result = std::panic::catch_unwind(|| unsafe {\n                let py = Python::assume_attached();\n                py.detach(|| {\n                    panic!(\"There was a panic!\");\n                });\n            });\n\n            // Check panic was caught\n            assert!(result.is_err());\n\n            // If `detach` is implemented correctly, this thread still owns the GIL here\n            // so the following Python calls should not cause crashes.\n            let list = PyList::new(py, [1, 2, 3, 4]).unwrap();\n            assert_eq!(list.extract::<Vec<i32>>().unwrap(), vec![1, 2, 3, 4]);\n        });\n    }\n\n    #[cfg(not(pyo3_disable_reference_pool))]\n    #[test]\n    fn test_detach_pass_stuff_in() {\n        let list = Python::attach(|py| PyList::new(py, vec![\"foo\", \"bar\"]).unwrap().unbind());\n        let mut v = vec![1, 2, 3];\n        let a = std::sync::Arc::new(String::from(\"foo\"));\n\n        Python::attach(|py| {\n            py.detach(|| {\n                drop((list, &mut v, a));\n            });\n        });\n    }\n\n    #[test]\n    #[cfg(not(Py_LIMITED_API))]\n    fn test_acquire_gil() {\n        use std::ffi::c_int;\n\n        const GIL_NOT_HELD: c_int = 0;\n        const GIL_HELD: c_int = 1;\n\n        // Before starting the interpreter the state of calling `PyGILState_Check`\n        // seems to be undefined, so let's ensure that Python is up.\n        #[cfg(not(any(PyPy, GraalPy)))]\n        Python::initialize();\n\n        let state = unsafe { crate::ffi::PyGILState_Check() };\n        assert_eq!(state, GIL_NOT_HELD);\n\n        Python::attach(|_| {\n            let state = unsafe { crate::ffi::PyGILState_Check() };\n            assert_eq!(state, GIL_HELD);\n        });\n\n        let state = unsafe { crate::ffi::PyGILState_Check() };\n        assert_eq!(state, GIL_NOT_HELD);\n    }\n\n    #[test]\n    fn test_ellipsis() {\n        Python::attach(|py| {\n            assert_eq!(py.Ellipsis().to_string(), \"Ellipsis\");\n\n            let v = py\n                .eval(c\"...\", None, None)\n                .map_err(|e| e.display(py))\n                .unwrap();\n\n            assert!(v.eq(py.Ellipsis()).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_py_run_inserts_globals() {\n        use crate::types::dict::PyDictMethods;\n\n        Python::attach(|py| {\n            let namespace = PyDict::new(py);\n            py.run(\n                c\"class Foo: pass\\na = int(3)\",\n                Some(&namespace),\n                Some(&namespace),\n            )\n            .unwrap();\n            assert!(matches!(namespace.get_item(\"Foo\"), Ok(Some(..))));\n            assert!(matches!(namespace.get_item(\"a\"), Ok(Some(..))));\n            // 3.9 and older did not automatically insert __builtins__ if it wasn't inserted \"by hand\"\n            #[cfg(not(Py_3_10))]\n            assert!(matches!(namespace.get_item(\"__builtins__\"), Ok(Some(..))));\n        })\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[test]\n    fn test_py_run_inserts_globals_2() {\n        use std::ffi::CString;\n\n        #[crate::pyclass(crate = \"crate\", skip_from_py_object)]\n        #[derive(Clone)]\n        struct CodeRunner {\n            code: CString,\n        }\n\n        impl CodeRunner {\n            fn reproducer(&mut self, py: Python<'_>) -> PyResult<()> {\n                let variables = PyDict::new(py);\n                variables.set_item(\"cls\", crate::Py::new(py, self.clone())?)?;\n\n                py.run(self.code.as_c_str(), Some(&variables), None)?;\n                Ok(())\n            }\n        }\n\n        #[crate::pymethods(crate = \"crate\")]\n        impl CodeRunner {\n            fn func(&mut self, py: Python<'_>) -> PyResult<()> {\n                py.import(\"math\")?;\n                Ok(())\n            }\n        }\n\n        let mut runner = CodeRunner {\n            code: CString::new(\n                r#\"\ncls.func()\n\"#\n                .to_string(),\n            )\n            .unwrap(),\n        };\n\n        Python::attach(|py| {\n            runner.reproducer(py).unwrap();\n        });\n    }\n\n    #[test]\n    fn python_is_zst() {\n        assert_eq!(std::mem::size_of::<Python<'_>>(), 0);\n    }\n\n    #[test]\n    fn test_try_attach_fail_during_gc() {\n        Python::attach(|_| {\n            assert!(Python::try_attach(|_| {}).is_some());\n\n            let guard = ForbidAttaching::during_traverse();\n            assert!(Python::try_attach(|_| {}).is_none());\n            drop(guard);\n\n            assert!(Python::try_attach(|_| {}).is_some());\n        })\n    }\n\n    #[test]\n    fn test_try_attach_ok_when_detached() {\n        Python::attach(|py| {\n            py.detach(|| {\n                assert!(Python::try_attach(|_| {}).is_some());\n            });\n        });\n    }\n}\n"
  },
  {
    "path": "src/marshal.rs",
    "content": "#![cfg(not(Py_LIMITED_API))]\n\n//! Support for the Python `marshal` format.\n\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::py_result_ext::PyResultExt;\nuse crate::types::{PyAny, PyBytes};\nuse crate::{ffi, Bound};\nuse crate::{PyResult, Python};\nuse std::ffi::c_int;\n\n/// The current version of the marshal binary format.\npub const VERSION: i32 = 4;\n\n/// Serialize an object to bytes using the Python built-in marshal module.\n///\n/// The built-in marshalling only supports a limited range of objects.\n/// The exact types supported depend on the version argument.\n/// The [`VERSION`] constant holds the highest version currently supported.\n///\n/// See the [Python documentation](https://docs.python.org/3/library/marshal.html) for more details.\n///\n/// # Examples\n/// ```\n/// # use pyo3::{marshal, types::PyDict, prelude::PyDictMethods};\n/// # pyo3::Python::attach(|py| {\n/// let dict = PyDict::new(py);\n/// dict.set_item(\"aap\", \"noot\").unwrap();\n/// dict.set_item(\"mies\", \"wim\").unwrap();\n/// dict.set_item(\"zus\", \"jet\").unwrap();\n///\n/// let bytes = marshal::dumps(&dict, marshal::VERSION);\n/// # });\n/// ```\npub fn dumps<'py>(object: &Bound<'py, PyAny>, version: i32) -> PyResult<Bound<'py, PyBytes>> {\n    unsafe {\n        ffi::PyMarshal_WriteObjectToString(object.as_ptr(), version as c_int)\n            .assume_owned_or_err(object.py())\n            .cast_into_unchecked()\n    }\n}\n\n/// Deserialize an object from bytes using the Python built-in marshal module.\npub fn loads<'py, B>(py: Python<'py>, data: &B) -> PyResult<Bound<'py, PyAny>>\nwhere\n    B: AsRef<[u8]> + ?Sized,\n{\n    let data = data.as_ref();\n    unsafe {\n        ffi::PyMarshal_ReadObjectFromString(data.as_ptr().cast(), data.len() as isize)\n            .assume_owned_or_err(py)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::{bytes::PyBytesMethods, dict::PyDictMethods, PyAnyMethods, PyDict};\n\n    #[test]\n    fn marshal_roundtrip() {\n        Python::attach(|py| {\n            let dict = PyDict::new(py);\n            dict.set_item(\"aap\", \"noot\").unwrap();\n            dict.set_item(\"mies\", \"wim\").unwrap();\n            dict.set_item(\"zus\", \"jet\").unwrap();\n\n            let pybytes = dumps(&dict, VERSION).expect(\"marshalling failed\");\n            let deserialized = loads(py, pybytes.as_bytes()).expect(\"unmarshalling failed\");\n\n            assert!(dict.eq(&deserialized).unwrap());\n        });\n    }\n}\n"
  },
  {
    "path": "src/panic.rs",
    "content": "//! Helper to convert Rust panics to Python exceptions.\nuse crate::exceptions::PyBaseException;\nuse crate::PyErr;\nuse std::any::Any;\n\npyo3_exception!(\n    \"\nThe exception raised when Rust code called from Python panics.\n\nLike SystemExit, this exception is derived from BaseException so that\nit will typically propagate all the way through the stack and cause the\nPython interpreter to exit.\n\",\n    PanicException,\n    PyBaseException\n);\n\nimpl PanicException {\n    /// Creates a new PanicException from a panic payload.\n    ///\n    /// Attempts to format the error in the same way panic does.\n    #[cold]\n    pub(crate) fn from_panic_payload(payload: Box<dyn Any + Send + 'static>) -> PyErr {\n        if let Some(string) = payload.downcast_ref::<String>() {\n            Self::new_err((string.clone(),))\n        } else if let Some(s) = payload.downcast_ref::<&str>() {\n            Self::new_err((s.to_string(),))\n        } else {\n            Self::new_err((\"panic from Rust code\",))\n        }\n    }\n}\n"
  },
  {
    "path": "src/prelude.rs",
    "content": "//! PyO3's prelude.\n//!\n//! The purpose of this module is to alleviate imports of many commonly used items of the PyO3 crate\n//! by adding a glob import to the top of pyo3 heavy modules:\n//!\n//! ```\n//! # #![allow(unused_imports)]\n//! use pyo3::prelude::*;\n//! ```\n\npub use crate::conversion::{FromPyObject, FromPyObjectOwned, IntoPyObject};\npub use crate::err::{PyErr, PyResult};\npub use crate::instance::{Borrowed, Bound, Py};\npub use crate::marker::Python;\npub use crate::pycell::{PyRef, PyRefMut};\npub use crate::pyclass_init::PyClassInitializer;\npub use crate::types::{PyAny, PyModule};\n\n#[cfg(feature = \"macros\")]\npub use pyo3_macros::{\n    pyclass, pyfunction, pymethods, pymodule, FromPyObject, IntoPyObject, IntoPyObjectRef,\n};\n\n#[cfg(feature = \"macros\")]\npub use crate::wrap_pyfunction;\n\npub use crate::types::any::PyAnyMethods;\npub use crate::types::boolobject::PyBoolMethods;\npub use crate::types::bytearray::PyByteArrayMethods;\npub use crate::types::bytes::PyBytesMethods;\npub use crate::types::capsule::PyCapsuleMethods;\npub use crate::types::complex::PyComplexMethods;\npub use crate::types::dict::PyDictMethods;\npub use crate::types::float::PyFloatMethods;\npub use crate::types::frozenset::PyFrozenSetMethods;\npub use crate::types::list::PyListMethods;\npub use crate::types::mapping::PyMappingMethods;\npub use crate::types::mappingproxy::PyMappingProxyMethods;\npub use crate::types::module::PyModuleMethods;\npub use crate::types::sequence::PySequenceMethods;\npub use crate::types::set::PySetMethods;\npub use crate::types::slice::PySliceMethods;\npub use crate::types::string::PyStringMethods;\npub use crate::types::traceback::PyTracebackMethods;\npub use crate::types::tuple::PyTupleMethods;\npub use crate::types::typeobject::PyTypeMethods;\npub use crate::types::weakref::PyWeakrefMethods;\n"
  },
  {
    "path": "src/py_result_ext.rs",
    "content": "use crate::{Bound, PyAny, PyResult, PyTypeCheck};\n\npub(crate) trait PyResultExt<'py>: crate::sealed::Sealed {\n    fn cast_into<T: PyTypeCheck>(self) -> PyResult<Bound<'py, T>>;\n    unsafe fn cast_into_unchecked<T>(self) -> PyResult<Bound<'py, T>>;\n}\n\nimpl<'py> PyResultExt<'py> for PyResult<Bound<'py, PyAny>> {\n    #[inline]\n    fn cast_into<T: PyTypeCheck>(self) -> PyResult<Bound<'py, T>> where {\n        self.and_then(|instance| instance.cast_into().map_err(Into::into))\n    }\n\n    #[inline]\n    unsafe fn cast_into_unchecked<T>(self) -> PyResult<Bound<'py, T>> {\n        self.map(|instance| unsafe { instance.cast_into_unchecked() })\n    }\n}\n"
  },
  {
    "path": "src/pybacked.rs",
    "content": "//! Contains types for working with Python objects that own the underlying data.\n\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_hint_union;\nuse crate::{\n    types::{\n        bytearray::PyByteArrayMethods, bytes::PyBytesMethods, string::PyStringMethods, PyByteArray,\n        PyBytes, PyString, PyTuple,\n    },\n    Borrowed, Bound, CastError, FromPyObject, IntoPyObject, Py, PyAny, PyErr, PyTypeInfo, Python,\n};\nuse std::{borrow::Borrow, convert::Infallible, ops::Deref, ptr::NonNull, sync::Arc};\n\n/// An equivalent to `String` where the storage is owned by a Python `bytes` or `str` object.\n///\n/// On Python 3.10+ or when not using the stable API, this type is guaranteed to contain a Python `str`\n/// for the underlying data.\n///\n/// This type gives access to the underlying data via a `Deref` implementation.\n#[cfg_attr(feature = \"py-clone\", derive(Clone))]\npub struct PyBackedStr {\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    storage: Py<PyString>,\n    #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))]\n    storage: Py<PyBytes>,\n    data: NonNull<str>,\n}\n\nimpl PyBackedStr {\n    /// Clones this by incrementing the reference count of the underlying Python object.\n    ///\n    /// Similar to [`Py::clone_ref`], this method is always available, even when the `py-clone` feature is disabled.\n    #[inline]\n    pub fn clone_ref(&self, py: Python<'_>) -> Self {\n        Self {\n            storage: self.storage.clone_ref(py),\n            data: self.data,\n        }\n    }\n\n    /// Returns the underlying data as a `&str` slice.\n    #[inline]\n    pub fn as_str(&self) -> &str {\n        // Safety: `data` is known to be immutable and owned by self\n        unsafe { self.data.as_ref() }\n    }\n\n    /// Returns the underlying data as a Python `str`.\n    ///\n    /// Older versions of the Python stable API do not support this zero-cost conversion.\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    #[inline]\n    pub fn as_py_str(&self) -> &Py<PyString> {\n        &self.storage\n    }\n}\n\nimpl Deref for PyBackedStr {\n    type Target = str;\n    #[inline]\n    fn deref(&self) -> &str {\n        self.as_str()\n    }\n}\n\nimpl AsRef<str> for PyBackedStr {\n    #[inline]\n    fn as_ref(&self) -> &str {\n        self\n    }\n}\n\nimpl AsRef<[u8]> for PyBackedStr {\n    #[inline]\n    fn as_ref(&self) -> &[u8] {\n        self.as_bytes()\n    }\n}\n\nimpl Borrow<str> for PyBackedStr {\n    #[inline]\n    fn borrow(&self) -> &str {\n        self\n    }\n}\n\n// Safety: the underlying Python str (or bytes) is immutable and\n// safe to share between threads\nunsafe impl Send for PyBackedStr {}\nunsafe impl Sync for PyBackedStr {}\n\nimpl std::fmt::Display for PyBackedStr {\n    #[inline]\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        self.deref().fmt(f)\n    }\n}\n\nimpl_traits!(PyBackedStr, str);\n\nimpl TryFrom<Bound<'_, PyString>> for PyBackedStr {\n    type Error = PyErr;\n    fn try_from(py_string: Bound<'_, PyString>) -> Result<Self, Self::Error> {\n        #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n        {\n            let s = py_string.to_str()?;\n            let data = NonNull::from(s);\n            Ok(Self {\n                storage: py_string.unbind(),\n                data,\n            })\n        }\n        #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))]\n        {\n            let bytes = py_string.encode_utf8()?;\n            let s = unsafe { std::str::from_utf8_unchecked(bytes.as_bytes()) };\n            let data = NonNull::from(s);\n            Ok(Self {\n                storage: bytes.unbind(),\n                data,\n            })\n        }\n    }\n}\n\nimpl FromPyObject<'_, '_> for PyBackedStr {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    #[inline]\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let py_string = obj.cast::<PyString>()?.to_owned();\n        Self::try_from(py_string)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for PyBackedStr {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.storage.into_bound(py))\n    }\n\n    #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PyString::new(py, &self))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &PyBackedStr {\n    type Target = PyString;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyString::TYPE_HINT;\n\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.storage.bind(py).to_owned())\n    }\n\n    #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PyString::new(py, self))\n    }\n}\n\n/// A wrapper around `[u8]` where the storage is either owned by a Python `bytes` object, or a Rust `Box<[u8]>`.\n///\n/// This type gives access to the underlying data via a `Deref` implementation.\n#[cfg_attr(feature = \"py-clone\", derive(Clone))]\npub struct PyBackedBytes {\n    storage: PyBackedBytesStorage,\n    data: NonNull<[u8]>,\n}\n\n#[cfg_attr(feature = \"py-clone\", derive(Clone))]\nenum PyBackedBytesStorage {\n    Python(Py<PyBytes>),\n    Rust(Arc<[u8]>),\n}\n\nimpl PyBackedBytes {\n    /// Clones this by incrementing the reference count of the underlying data.\n    ///\n    /// Similar to [`Py::clone_ref`], this method is always available, even when the `py-clone` feature is disabled.\n    pub fn clone_ref(&self, py: Python<'_>) -> Self {\n        Self {\n            storage: match &self.storage {\n                PyBackedBytesStorage::Python(bytes) => {\n                    PyBackedBytesStorage::Python(bytes.clone_ref(py))\n                }\n                PyBackedBytesStorage::Rust(bytes) => PyBackedBytesStorage::Rust(bytes.clone()),\n            },\n            data: self.data,\n        }\n    }\n}\n\nimpl Deref for PyBackedBytes {\n    type Target = [u8];\n    fn deref(&self) -> &[u8] {\n        // Safety: `data` is known to be immutable and owned by self\n        unsafe { self.data.as_ref() }\n    }\n}\n\nimpl AsRef<[u8]> for PyBackedBytes {\n    fn as_ref(&self) -> &[u8] {\n        self\n    }\n}\n\n// Safety: the underlying Python bytes or Rust bytes is immutable and\n// safe to share between threads\nunsafe impl Send for PyBackedBytes {}\nunsafe impl Sync for PyBackedBytes {}\n\nimpl<const N: usize> PartialEq<[u8; N]> for PyBackedBytes {\n    fn eq(&self, other: &[u8; N]) -> bool {\n        self.deref() == other\n    }\n}\n\nimpl<const N: usize> PartialEq<PyBackedBytes> for [u8; N] {\n    fn eq(&self, other: &PyBackedBytes) -> bool {\n        self == other.deref()\n    }\n}\n\nimpl<const N: usize> PartialEq<&[u8; N]> for PyBackedBytes {\n    fn eq(&self, other: &&[u8; N]) -> bool {\n        self.deref() == *other\n    }\n}\n\nimpl<const N: usize> PartialEq<PyBackedBytes> for &[u8; N] {\n    fn eq(&self, other: &PyBackedBytes) -> bool {\n        self == &other.deref()\n    }\n}\n\nimpl_traits!(PyBackedBytes, [u8]);\n\nimpl From<Bound<'_, PyBytes>> for PyBackedBytes {\n    fn from(py_bytes: Bound<'_, PyBytes>) -> Self {\n        let b = py_bytes.as_bytes();\n        let data = NonNull::from(b);\n        Self {\n            storage: PyBackedBytesStorage::Python(py_bytes.to_owned().unbind()),\n            data,\n        }\n    }\n}\n\nimpl From<Bound<'_, PyByteArray>> for PyBackedBytes {\n    fn from(py_bytearray: Bound<'_, PyByteArray>) -> Self {\n        let s = Arc::<[u8]>::from(py_bytearray.to_vec());\n        let data = NonNull::from(s.as_ref());\n        Self {\n            storage: PyBackedBytesStorage::Rust(s),\n            data,\n        }\n    }\n}\n\nimpl<'a, 'py> FromPyObject<'a, 'py> for PyBackedBytes {\n    type Error = CastError<'a, 'py>;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = type_hint_union!(PyBytes::TYPE_HINT, PyByteArray::TYPE_HINT);\n\n    fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {\n        if let Ok(bytes) = obj.cast::<PyBytes>() {\n            Ok(Self::from(bytes.to_owned()))\n        } else if let Ok(bytearray) = obj.cast::<PyByteArray>() {\n            Ok(Self::from(bytearray.to_owned()))\n        } else {\n            Err(CastError::new(\n                obj,\n                PyTuple::new(\n                    obj.py(),\n                    [\n                        PyBytes::type_object(obj.py()),\n                        PyByteArray::type_object(obj.py()),\n                    ],\n                )\n                .unwrap()\n                .into_any(),\n            ))\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for PyBackedBytes {\n    type Target = PyBytes;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyBytes::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        match self.storage {\n            PyBackedBytesStorage::Python(bytes) => Ok(bytes.into_bound(py)),\n            PyBackedBytesStorage::Rust(bytes) => Ok(PyBytes::new(py, &bytes)),\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &PyBackedBytes {\n    type Target = PyBytes;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyBytes::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        match &self.storage {\n            PyBackedBytesStorage::Python(bytes) => Ok(bytes.bind(py).clone()),\n            PyBackedBytesStorage::Rust(bytes) => Ok(PyBytes::new(py, bytes)),\n        }\n    }\n}\n\nmacro_rules! impl_traits {\n    ($slf:ty, $equiv:ty) => {\n        impl std::fmt::Debug for $slf {\n            #[inline]\n            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n                self.deref().fmt(f)\n            }\n        }\n\n        impl PartialEq for $slf {\n            #[inline]\n            fn eq(&self, other: &Self) -> bool {\n                self.deref() == other.deref()\n            }\n        }\n\n        impl PartialEq<$equiv> for $slf {\n            #[inline]\n            fn eq(&self, other: &$equiv) -> bool {\n                self.deref() == other\n            }\n        }\n\n        impl PartialEq<&$equiv> for $slf {\n            #[inline]\n            fn eq(&self, other: &&$equiv) -> bool {\n                self.deref() == *other\n            }\n        }\n\n        impl PartialEq<$slf> for $equiv {\n            #[inline]\n            fn eq(&self, other: &$slf) -> bool {\n                self == other.deref()\n            }\n        }\n\n        impl PartialEq<$slf> for &$equiv {\n            #[inline]\n            fn eq(&self, other: &$slf) -> bool {\n                self == &other.deref()\n            }\n        }\n\n        impl Eq for $slf {}\n\n        impl PartialOrd for $slf {\n            #[inline]\n            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {\n                Some(self.cmp(other))\n            }\n        }\n\n        impl PartialOrd<$equiv> for $slf {\n            #[inline]\n            fn partial_cmp(&self, other: &$equiv) -> Option<std::cmp::Ordering> {\n                self.deref().partial_cmp(other)\n            }\n        }\n\n        impl PartialOrd<$slf> for $equiv {\n            #[inline]\n            fn partial_cmp(&self, other: &$slf) -> Option<std::cmp::Ordering> {\n                self.partial_cmp(other.deref())\n            }\n        }\n\n        impl Ord for $slf {\n            #[inline]\n            fn cmp(&self, other: &Self) -> std::cmp::Ordering {\n                self.deref().cmp(other.deref())\n            }\n        }\n\n        impl std::hash::Hash for $slf {\n            #[inline]\n            fn hash<H: std::hash::Hasher>(&self, state: &mut H) {\n                self.deref().hash(state)\n            }\n        }\n    };\n}\nuse impl_traits;\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use crate::impl_::pyclass::{value_of, IsSend, IsSync};\n    use crate::types::PyAnyMethods as _;\n    use crate::{IntoPyObject, Python};\n    use std::collections::hash_map::DefaultHasher;\n    use std::hash::{Hash, Hasher};\n\n    #[test]\n    fn py_backed_str_empty() {\n        Python::attach(|py| {\n            let s = PyString::new(py, \"\");\n            let py_backed_str = s.extract::<PyBackedStr>().unwrap();\n            assert_eq!(&*py_backed_str, \"\");\n        });\n    }\n\n    #[test]\n    fn py_backed_str() {\n        Python::attach(|py| {\n            let s = PyString::new(py, \"hello\");\n            let py_backed_str = s.extract::<PyBackedStr>().unwrap();\n            assert_eq!(&*py_backed_str, \"hello\");\n        });\n    }\n\n    #[test]\n    fn py_backed_str_try_from() {\n        Python::attach(|py| {\n            let s = PyString::new(py, \"hello\");\n            let py_backed_str = PyBackedStr::try_from(s).unwrap();\n            assert_eq!(&*py_backed_str, \"hello\");\n        });\n    }\n\n    #[test]\n    fn py_backed_str_into_pyobject() {\n        Python::attach(|py| {\n            let orig_str = PyString::new(py, \"hello\");\n            let py_backed_str = orig_str.extract::<PyBackedStr>().unwrap();\n            let new_str = py_backed_str.into_pyobject(py).unwrap();\n            assert_eq!(new_str.extract::<PyBackedStr>().unwrap(), \"hello\");\n            #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n            assert!(new_str.is(&orig_str));\n        });\n    }\n\n    #[test]\n    fn py_backed_bytes_empty() {\n        Python::attach(|py| {\n            let b = PyBytes::new(py, b\"\");\n            let py_backed_bytes = b.extract::<PyBackedBytes>().unwrap();\n            assert_eq!(&*py_backed_bytes, b\"\");\n        });\n    }\n\n    #[test]\n    fn py_backed_bytes() {\n        Python::attach(|py| {\n            let b = PyBytes::new(py, b\"abcde\");\n            let py_backed_bytes = b.extract::<PyBackedBytes>().unwrap();\n            assert_eq!(&*py_backed_bytes, b\"abcde\");\n        });\n    }\n\n    #[test]\n    fn py_backed_bytes_from_bytes() {\n        Python::attach(|py| {\n            let b = PyBytes::new(py, b\"abcde\");\n            let py_backed_bytes = PyBackedBytes::from(b);\n            assert_eq!(&*py_backed_bytes, b\"abcde\");\n        });\n    }\n\n    #[test]\n    fn py_backed_bytes_from_bytearray() {\n        Python::attach(|py| {\n            let b = PyByteArray::new(py, b\"abcde\");\n            let py_backed_bytes = PyBackedBytes::from(b);\n            assert_eq!(&*py_backed_bytes, b\"abcde\");\n        });\n    }\n\n    #[test]\n    fn py_backed_bytes_into_pyobject() {\n        Python::attach(|py| {\n            let orig_bytes = PyBytes::new(py, b\"abcde\");\n            let py_backed_bytes = PyBackedBytes::from(orig_bytes.clone());\n            assert!((&py_backed_bytes)\n                .into_pyobject(py)\n                .unwrap()\n                .is(&orig_bytes));\n        });\n    }\n\n    #[test]\n    fn rust_backed_bytes_into_pyobject() {\n        Python::attach(|py| {\n            let orig_bytes = PyByteArray::new(py, b\"abcde\");\n            let rust_backed_bytes = PyBackedBytes::from(orig_bytes);\n            assert!(matches!(\n                rust_backed_bytes.storage,\n                PyBackedBytesStorage::Rust(_)\n            ));\n            let to_object = (&rust_backed_bytes).into_pyobject(py).unwrap();\n            assert!(&to_object.is_exact_instance_of::<PyBytes>());\n            assert_eq!(&to_object.extract::<PyBackedBytes>().unwrap(), b\"abcde\");\n        });\n    }\n\n    #[test]\n    fn test_backed_types_send_sync() {\n        assert!(value_of!(IsSend, PyBackedStr));\n        assert!(value_of!(IsSync, PyBackedStr));\n\n        assert!(value_of!(IsSend, PyBackedBytes));\n        assert!(value_of!(IsSync, PyBackedBytes));\n    }\n\n    #[cfg(feature = \"py-clone\")]\n    #[test]\n    fn test_backed_str_clone() {\n        Python::attach(|py| {\n            let s1: PyBackedStr = PyString::new(py, \"hello\").try_into().unwrap();\n            let s2 = s1.clone();\n            assert_eq!(s1, s2);\n\n            drop(s1);\n            assert_eq!(s2, \"hello\");\n        });\n    }\n\n    #[test]\n    fn test_backed_str_clone_ref() {\n        Python::attach(|py| {\n            let s1: PyBackedStr = PyString::new(py, \"hello\").try_into().unwrap();\n            let s2 = s1.clone_ref(py);\n            assert_eq!(s1, s2);\n            assert!(s1.storage.is(&s2.storage));\n\n            drop(s1);\n            assert_eq!(s2, \"hello\");\n        });\n    }\n\n    #[test]\n    fn test_backed_str_eq() {\n        Python::attach(|py| {\n            let s1: PyBackedStr = PyString::new(py, \"hello\").try_into().unwrap();\n            let s2: PyBackedStr = PyString::new(py, \"hello\").try_into().unwrap();\n            assert_eq!(s1, \"hello\");\n            assert_eq!(s1, s2);\n\n            let s3: PyBackedStr = PyString::new(py, \"abcde\").try_into().unwrap();\n            assert_eq!(\"abcde\", s3);\n            assert_ne!(s1, s3);\n        });\n    }\n\n    #[test]\n    fn test_backed_str_hash() {\n        Python::attach(|py| {\n            let h = {\n                let mut hasher = DefaultHasher::new();\n                \"abcde\".hash(&mut hasher);\n                hasher.finish()\n            };\n\n            let s1: PyBackedStr = PyString::new(py, \"abcde\").try_into().unwrap();\n            let h1 = {\n                let mut hasher = DefaultHasher::new();\n                s1.hash(&mut hasher);\n                hasher.finish()\n            };\n\n            assert_eq!(h, h1);\n        });\n    }\n\n    #[test]\n    fn test_backed_str_ord() {\n        Python::attach(|py| {\n            let mut a = vec![\"a\", \"c\", \"d\", \"b\", \"f\", \"g\", \"e\"];\n            let mut b = a\n                .iter()\n                .map(|s| PyString::new(py, s).try_into().unwrap())\n                .collect::<Vec<PyBackedStr>>();\n\n            a.sort();\n            b.sort();\n\n            assert_eq!(a, b);\n        })\n    }\n\n    #[test]\n    fn test_backed_str_map_key() {\n        Python::attach(|py| {\n            use std::collections::HashMap;\n\n            let mut map: HashMap<PyBackedStr, usize> = HashMap::new();\n            let s: PyBackedStr = PyString::new(py, \"key1\").try_into().unwrap();\n\n            map.insert(s, 1);\n\n            assert_eq!(map.get(\"key1\"), Some(&1));\n        });\n    }\n\n    #[test]\n    fn test_backed_str_as_str() {\n        Python::attach(|py| {\n            let s: PyBackedStr = PyString::new(py, \"hello\").try_into().unwrap();\n            assert_eq!(s.as_str(), \"hello\");\n        });\n    }\n\n    #[test]\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    fn test_backed_str_as_py_str() {\n        Python::attach(|py| {\n            let s: PyBackedStr = PyString::new(py, \"hello\").try_into().unwrap();\n            let py_str = s.as_py_str().bind(py);\n            assert!(py_str.is(&s.storage));\n            assert_eq!(py_str.to_str().unwrap(), \"hello\");\n        });\n    }\n\n    #[cfg(feature = \"py-clone\")]\n    #[test]\n    fn test_backed_bytes_from_bytes_clone() {\n        Python::attach(|py| {\n            let b1: PyBackedBytes = PyBytes::new(py, b\"abcde\").into();\n            let b2 = b1.clone();\n            assert_eq!(b1, b2);\n\n            drop(b1);\n            assert_eq!(b2, b\"abcde\");\n        });\n    }\n\n    #[test]\n    fn test_backed_bytes_from_bytes_clone_ref() {\n        Python::attach(|py| {\n            let b1: PyBackedBytes = PyBytes::new(py, b\"abcde\").into();\n            let b2 = b1.clone_ref(py);\n            assert_eq!(b1, b2);\n            let (PyBackedBytesStorage::Python(s1), PyBackedBytesStorage::Python(s2)) =\n                (&b1.storage, &b2.storage)\n            else {\n                panic!(\"Expected Python-backed bytes\");\n            };\n            assert!(s1.is(s2));\n\n            drop(b1);\n            assert_eq!(b2, b\"abcde\");\n        });\n    }\n\n    #[cfg(feature = \"py-clone\")]\n    #[test]\n    fn test_backed_bytes_from_bytearray_clone() {\n        Python::attach(|py| {\n            let b1: PyBackedBytes = PyByteArray::new(py, b\"abcde\").into();\n            let b2 = b1.clone();\n            assert_eq!(b1, b2);\n\n            drop(b1);\n            assert_eq!(b2, b\"abcde\");\n        });\n    }\n\n    #[test]\n    fn test_backed_bytes_from_bytearray_clone_ref() {\n        Python::attach(|py| {\n            let b1: PyBackedBytes = PyByteArray::new(py, b\"abcde\").into();\n            let b2 = b1.clone_ref(py);\n            assert_eq!(b1, b2);\n            let (PyBackedBytesStorage::Rust(s1), PyBackedBytesStorage::Rust(s2)) =\n                (&b1.storage, &b2.storage)\n            else {\n                panic!(\"Expected Rust-backed bytes\");\n            };\n            assert!(Arc::ptr_eq(s1, s2));\n\n            drop(b1);\n            assert_eq!(b2, b\"abcde\");\n        });\n    }\n\n    #[test]\n    fn test_backed_bytes_eq() {\n        Python::attach(|py| {\n            let b1: PyBackedBytes = PyBytes::new(py, b\"abcde\").into();\n            let b2: PyBackedBytes = PyByteArray::new(py, b\"abcde\").into();\n\n            assert_eq!(b1, b\"abcde\");\n            assert_eq!(b1, b2);\n\n            let b3: PyBackedBytes = PyBytes::new(py, b\"hello\").into();\n            assert_eq!(b\"hello\", b3);\n            assert_ne!(b1, b3);\n        });\n    }\n\n    #[test]\n    fn test_backed_bytes_hash() {\n        Python::attach(|py| {\n            let h = {\n                let mut hasher = DefaultHasher::new();\n                b\"abcde\".hash(&mut hasher);\n                hasher.finish()\n            };\n\n            let b1: PyBackedBytes = PyBytes::new(py, b\"abcde\").into();\n            let h1 = {\n                let mut hasher = DefaultHasher::new();\n                b1.hash(&mut hasher);\n                hasher.finish()\n            };\n\n            let b2: PyBackedBytes = PyByteArray::new(py, b\"abcde\").into();\n            let h2 = {\n                let mut hasher = DefaultHasher::new();\n                b2.hash(&mut hasher);\n                hasher.finish()\n            };\n\n            assert_eq!(h, h1);\n            assert_eq!(h, h2);\n        });\n    }\n\n    #[test]\n    fn test_backed_bytes_ord() {\n        Python::attach(|py| {\n            let mut a = vec![b\"a\", b\"c\", b\"d\", b\"b\", b\"f\", b\"g\", b\"e\"];\n            let mut b = a\n                .iter()\n                .map(|&b| PyBytes::new(py, b).into())\n                .collect::<Vec<PyBackedBytes>>();\n\n            a.sort();\n            b.sort();\n\n            assert_eq!(a, b);\n        })\n    }\n}\n"
  },
  {
    "path": "src/pycell/impl_.rs",
    "content": "#![allow(missing_docs)]\n//! Crate-private implementation of PyClassObject\n\nuse std::cell::UnsafeCell;\nuse std::marker::PhantomData;\nuse std::mem::{offset_of, ManuallyDrop, MaybeUninit};\nuse std::sync::atomic::{AtomicUsize, Ordering};\n\nuse crate::impl_::pyclass::{\n    PyClassBaseType, PyClassDict, PyClassImpl, PyClassThreadChecker, PyClassWeakRef, PyObjectOffset,\n};\nuse crate::internal::get_slot::{TP_DEALLOC, TP_FREE};\nuse crate::type_object::{PyLayout, PySizedLayout, PyTypeInfo};\nuse crate::types::PyType;\nuse crate::{ffi, PyClass, Python};\n\nuse crate::types::PyTypeMethods;\n\nuse super::{PyBorrowError, PyBorrowMutError};\n\npub trait PyClassMutability {\n    // The storage for this inheritance layer. Only the first mutable class in\n    // an inheritance hierarchy needs to store the borrow flag.\n    type Storage: PyClassBorrowChecker;\n    // The borrow flag needed to implement this class' mutability. Empty until\n    // the first mutable class, at which point it is BorrowChecker and will be\n    // for all subclasses.\n    type Checker: PyClassBorrowChecker;\n    type ImmutableChild: PyClassMutability;\n    type MutableChild: PyClassMutability;\n}\n\npub struct ImmutableClass(());\npub struct MutableClass(());\npub struct ExtendsMutableAncestor<M: PyClassMutability>(PhantomData<M>);\n\nimpl PyClassMutability for ImmutableClass {\n    type Storage = EmptySlot;\n    type Checker = EmptySlot;\n    type ImmutableChild = ImmutableClass;\n    type MutableChild = MutableClass;\n}\n\nimpl PyClassMutability for MutableClass {\n    type Storage = BorrowChecker;\n    type Checker = BorrowChecker;\n    type ImmutableChild = ExtendsMutableAncestor<ImmutableClass>;\n    type MutableChild = ExtendsMutableAncestor<MutableClass>;\n}\n\nimpl<M: PyClassMutability> PyClassMutability for ExtendsMutableAncestor<M> {\n    type Storage = EmptySlot;\n    type Checker = BorrowChecker;\n    type ImmutableChild = ExtendsMutableAncestor<ImmutableClass>;\n    type MutableChild = ExtendsMutableAncestor<MutableClass>;\n}\n\n#[derive(Debug)]\nstruct BorrowFlag(AtomicUsize);\n\nimpl BorrowFlag {\n    pub(crate) const UNUSED: usize = 0;\n    const HAS_MUTABLE_BORROW: usize = usize::MAX;\n    fn increment(&self) -> Result<(), PyBorrowError> {\n        // relaxed is OK because we will read the value again in the compare_exchange\n        let mut value = self.0.load(Ordering::Relaxed);\n        loop {\n            if value == BorrowFlag::HAS_MUTABLE_BORROW {\n                return Err(PyBorrowError { _private: () });\n            }\n            match self.0.compare_exchange(\n                // only increment if the value hasn't changed since the\n                // last atomic load\n                value,\n                value + 1,\n                // reading the value is happens-after a previous write\n                // writing the new value is happens-after the previous read\n                Ordering::AcqRel,\n                // relaxed is OK here because we're going to try to read again\n                Ordering::Relaxed,\n            ) {\n                Ok(..) => {\n                    break Ok(());\n                }\n                Err(changed_value) => {\n                    // value changed under us, need to try again\n                    value = changed_value;\n                }\n            }\n        }\n    }\n    fn decrement(&self) {\n        // relaxed load is OK but decrements must happen-before the next read\n        self.0.fetch_sub(1, Ordering::Release);\n    }\n}\n\npub struct EmptySlot(());\npub struct BorrowChecker(BorrowFlag);\n\npub trait PyClassBorrowChecker {\n    /// Initial value for self\n    fn new() -> Self\n    where\n        Self: Sized;\n\n    /// Increments immutable borrow count, if possible\n    fn try_borrow(&self) -> Result<(), PyBorrowError>;\n\n    /// Decrements immutable borrow count\n    fn release_borrow(&self);\n    /// Increments mutable borrow count, if possible\n    fn try_borrow_mut(&self) -> Result<(), PyBorrowMutError>;\n    /// Decremements mutable borrow count\n    fn release_borrow_mut(&self);\n}\n\nimpl PyClassBorrowChecker for EmptySlot {\n    #[inline]\n    fn new() -> Self {\n        EmptySlot(())\n    }\n\n    #[inline]\n    fn try_borrow(&self) -> Result<(), PyBorrowError> {\n        Ok(())\n    }\n\n    #[inline]\n    fn release_borrow(&self) {}\n\n    #[inline]\n    fn try_borrow_mut(&self) -> Result<(), PyBorrowMutError> {\n        unreachable!()\n    }\n\n    #[inline]\n    fn release_borrow_mut(&self) {\n        unreachable!()\n    }\n}\n\nimpl PyClassBorrowChecker for BorrowChecker {\n    #[inline]\n    fn new() -> Self {\n        Self(BorrowFlag(AtomicUsize::new(BorrowFlag::UNUSED)))\n    }\n\n    fn try_borrow(&self) -> Result<(), PyBorrowError> {\n        self.0.increment()\n    }\n\n    fn release_borrow(&self) {\n        self.0.decrement();\n    }\n\n    fn try_borrow_mut(&self) -> Result<(), PyBorrowMutError> {\n        let flag = &self.0;\n        match flag.0.compare_exchange(\n            // only allowed to transition to mutable borrow if the reference is\n            // currently unused\n            BorrowFlag::UNUSED,\n            BorrowFlag::HAS_MUTABLE_BORROW,\n            // On success, reading the flag and updating its state are an atomic\n            // operation\n            Ordering::AcqRel,\n            // It doesn't matter precisely when the failure gets turned\n            // into an error\n            Ordering::Relaxed,\n        ) {\n            Ok(..) => Ok(()),\n            Err(..) => Err(PyBorrowMutError { _private: () }),\n        }\n    }\n\n    fn release_borrow_mut(&self) {\n        self.0 .0.store(BorrowFlag::UNUSED, Ordering::Release)\n    }\n}\n\npub trait GetBorrowChecker<T: PyClassImpl> {\n    fn borrow_checker(\n        class_object: &T::Layout,\n    ) -> &<T::PyClassMutability as PyClassMutability>::Checker;\n}\n\nimpl<T: PyClassImpl<PyClassMutability = Self>> GetBorrowChecker<T> for MutableClass {\n    fn borrow_checker(class_object: &T::Layout) -> &BorrowChecker {\n        &class_object.contents().borrow_checker\n    }\n}\n\nimpl<T: PyClassImpl<PyClassMutability = Self>> GetBorrowChecker<T> for ImmutableClass {\n    fn borrow_checker(class_object: &T::Layout) -> &EmptySlot {\n        &class_object.contents().borrow_checker\n    }\n}\n\nimpl<T: PyClassImpl<PyClassMutability = Self>, M: PyClassMutability> GetBorrowChecker<T>\n    for ExtendsMutableAncestor<M>\nwhere\n    T::BaseType: PyClassImpl + PyClassBaseType<LayoutAsBase = <T::BaseType as PyClassImpl>::Layout>,\n    <T::BaseType as PyClassImpl>::PyClassMutability: PyClassMutability<Checker = BorrowChecker>,\n{\n    fn borrow_checker(class_object: &T::Layout) -> &BorrowChecker {\n        <<T::BaseType as PyClassImpl>::PyClassMutability as GetBorrowChecker<T::BaseType>>::borrow_checker(class_object.ob_base())\n    }\n}\n\n/// Base layout of PyClassObject with a known sized base type.\n/// Corresponds to [PyObject](https://docs.python.org/3/c-api/structures.html#c.PyObject) from the C API.\n#[doc(hidden)]\n#[repr(C)]\npub struct PyClassObjectBase<T> {\n    ob_base: T,\n}\n\nunsafe impl<T, U> PyLayout<T> for PyClassObjectBase<U> where U: PySizedLayout<T> {}\n\nimpl<T, U> PyClassObjectBaseLayout<T> for PyClassObjectBase<U>\nwhere\n    U: PySizedLayout<T>,\n    T: PyTypeInfo,\n{\n    fn ensure_threadsafe(&self) {}\n    fn check_threadsafe(&self) -> Result<(), PyBorrowError> {\n        Ok(())\n    }\n    unsafe fn tp_dealloc(py: Python<'_>, slf: *mut ffi::PyObject) {\n        unsafe { tp_dealloc(slf, &T::type_object(py)) };\n    }\n}\n\n/// Base layout of PyClassObject with an unknown sized base type.\n/// Corresponds to [PyVarObject](https://docs.python.org/3/c-api/structures.html#c.PyVarObject) from the C API.\n#[doc(hidden)]\n#[repr(C)]\npub struct PyVariableClassObjectBase {\n    ob_base: ffi::PyVarObject,\n}\n\nunsafe impl<T> PyLayout<T> for PyVariableClassObjectBase {}\n\nimpl<T: PyTypeInfo> PyClassObjectBaseLayout<T> for PyVariableClassObjectBase {\n    fn ensure_threadsafe(&self) {}\n    fn check_threadsafe(&self) -> Result<(), PyBorrowError> {\n        Ok(())\n    }\n    unsafe fn tp_dealloc(py: Python<'_>, slf: *mut ffi::PyObject) {\n        unsafe { tp_dealloc(slf, &T::type_object(py)) };\n    }\n}\n\n/// Implementation of tp_dealloc.\n/// # Safety\n/// - `slf` must be a valid pointer to an instance of the type at `type_obj` or a subclass.\n/// - `slf` must not be used after this call (as it will be freed).\nunsafe fn tp_dealloc(slf: *mut ffi::PyObject, type_obj: &crate::Bound<'_, PyType>) {\n    let py = type_obj.py();\n    unsafe {\n        // FIXME: there is potentially subtle issues here if the base is overwritten\n        // at runtime? To be investigated.\n        let type_ptr = type_obj.as_type_ptr();\n        let actual_type = PyType::from_borrowed_type_ptr(py, ffi::Py_TYPE(slf));\n\n        // For `#[pyclass]` types which inherit from PyAny, we can just call tp_free\n        if std::ptr::eq(type_ptr, &raw const ffi::PyBaseObject_Type) {\n            let tp_free = actual_type\n                .get_slot(TP_FREE)\n                .expect(\"PyBaseObject_Type should have tp_free\");\n            return tp_free(slf.cast());\n        }\n\n        // More complex native types (e.g. `extends=PyDict`) require calling the base's dealloc.\n        // FIXME: should this be using actual_type.tp_dealloc?\n        if let Some(dealloc) = type_obj.get_slot(TP_DEALLOC) {\n            // Before CPython 3.11 BaseException_dealloc would use Py_GC_UNTRACK which\n            // assumes the exception is currently GC tracked, so we have to re-track\n            // before calling the dealloc so that it can safely call Py_GC_UNTRACK.\n            #[cfg(not(any(Py_3_11, PyPy)))]\n            if ffi::PyType_FastSubclass(type_ptr, ffi::Py_TPFLAGS_BASE_EXC_SUBCLASS) == 1 {\n                ffi::PyObject_GC_Track(slf.cast());\n            }\n            dealloc(slf);\n        } else {\n            type_obj.get_slot(TP_FREE).expect(\"type missing tp_free\")(slf.cast());\n        }\n    }\n}\n\n/// functionality common to all PyObjects regardless of the layout\n#[doc(hidden)]\npub trait PyClassObjectBaseLayout<T>: PyLayout<T> {\n    fn ensure_threadsafe(&self);\n    fn check_threadsafe(&self) -> Result<(), PyBorrowError>;\n    /// Implementation of tp_dealloc.\n    /// # Safety\n    /// - slf must be a valid pointer to an instance of a T or a subclass.\n    /// - slf must not be used after this call (as it will be freed).\n    unsafe fn tp_dealloc(py: Python<'_>, slf: *mut ffi::PyObject);\n}\n\n/// Functionality required for creating and managing the memory associated with a pyclass annotated struct.\n#[doc(hidden)]\n#[diagnostic::on_unimplemented(\n    message = \"the class layout is not valid\",\n    label = \"required for `#[pyclass(extends=...)]`\",\n    note = \"the python version being built against influences which layouts are valid\"\n)]\npub trait PyClassObjectLayout<T: PyClassImpl>: PyClassObjectBaseLayout<T> {\n    /// Gets the offset of the contents from the start of the struct in bytes.\n    const CONTENTS_OFFSET: PyObjectOffset;\n\n    /// Used to set `PyType_Spec::basicsize`\n    /// ([docs](https://docs.python.org/3/c-api/type.html#c.PyType_Spec.basicsize))\n    const BASIC_SIZE: ffi::Py_ssize_t;\n\n    /// Gets the offset of the dictionary from the start of the struct in bytes.\n    const DICT_OFFSET: PyObjectOffset;\n\n    /// Gets the offset of the weakref list from the start of the struct in bytes.\n    const WEAKLIST_OFFSET: PyObjectOffset;\n\n    /// Obtain a pointer to the contents of an uninitialized PyObject of this type.\n    ///\n    /// SAFETY: `obj` must have the layout that the implementation is expecting\n    unsafe fn contents_uninit(\n        obj: *mut ffi::PyObject,\n    ) -> *mut MaybeUninit<PyClassObjectContents<T>>;\n\n    /// Obtain a reference to the structure that contains the pyclass struct and associated metadata.\n    fn contents(&self) -> &PyClassObjectContents<T>;\n\n    /// Obtain a mutable reference to the structure that contains the pyclass struct and associated metadata.\n    fn contents_mut(&mut self) -> &mut PyClassObjectContents<T>;\n\n    /// Obtain a pointer to the pyclass struct.\n    fn get_ptr(&self) -> *mut T;\n\n    /// obtain a reference to the data at the start of the PyObject.\n    fn ob_base(&self) -> &<T::BaseType as PyClassBaseType>::LayoutAsBase;\n\n    fn borrow_checker(&self) -> &<T::PyClassMutability as PyClassMutability>::Checker;\n}\n\n#[repr(C)]\npub struct PyClassObjectContents<T: PyClassImpl> {\n    pub(crate) value: ManuallyDrop<UnsafeCell<T>>,\n    pub(crate) borrow_checker: <T::PyClassMutability as PyClassMutability>::Storage,\n    pub(crate) thread_checker: T::ThreadChecker,\n    pub(crate) dict: T::Dict,\n    pub(crate) weakref: T::WeakRef,\n}\n\nimpl<T: PyClassImpl> PyClassObjectContents<T> {\n    pub(crate) fn new(init: T) -> Self {\n        PyClassObjectContents {\n            value: ManuallyDrop::new(UnsafeCell::new(init)),\n            borrow_checker: <T::PyClassMutability as PyClassMutability>::Storage::new(),\n            thread_checker: T::ThreadChecker::new(),\n            dict: T::Dict::INIT,\n            weakref: T::WeakRef::INIT,\n        }\n    }\n\n    unsafe fn dealloc(&mut self, py: Python<'_>, py_object: *mut ffi::PyObject) {\n        if self.thread_checker.can_drop(py) {\n            unsafe { ManuallyDrop::drop(&mut self.value) };\n        }\n        self.dict.clear_dict(py);\n        unsafe { self.weakref.clear_weakrefs(py_object, py) };\n    }\n}\n\n/// The layout of a PyClassObject with a known sized base class.\n#[repr(C)]\npub struct PyStaticClassObject<T: PyClassImpl> {\n    ob_base: <T::BaseType as PyClassBaseType>::LayoutAsBase,\n    contents: PyClassObjectContents<T>,\n}\n\nimpl<T: PyClassImpl<Layout = Self>> PyClassObjectLayout<T> for PyStaticClassObject<T> {\n    /// Gets the offset of the contents from the start of the struct in bytes.\n    const CONTENTS_OFFSET: PyObjectOffset = {\n        let offset = offset_of!(Self, contents);\n        // Py_ssize_t may not be equal to isize on all platforms\n        assert!(offset <= ffi::Py_ssize_t::MAX as usize);\n        PyObjectOffset::Absolute(offset as ffi::Py_ssize_t)\n    };\n\n    const BASIC_SIZE: ffi::Py_ssize_t = {\n        let size = std::mem::size_of::<Self>();\n        assert!(size <= ffi::Py_ssize_t::MAX as usize);\n        size as _\n    };\n\n    const DICT_OFFSET: PyObjectOffset = {\n        let offset = offset_of!(PyStaticClassObject<T>, contents)\n            + offset_of!(PyClassObjectContents<T>, dict);\n        assert!(offset <= ffi::Py_ssize_t::MAX as usize);\n        PyObjectOffset::Absolute(offset as _)\n    };\n\n    const WEAKLIST_OFFSET: PyObjectOffset = {\n        let offset = offset_of!(PyStaticClassObject<T>, contents)\n            + offset_of!(PyClassObjectContents<T>, weakref);\n        assert!(offset <= ffi::Py_ssize_t::MAX as usize);\n        PyObjectOffset::Absolute(offset as _)\n    };\n\n    unsafe fn contents_uninit(\n        obj: *mut ffi::PyObject,\n    ) -> *mut MaybeUninit<PyClassObjectContents<T>> {\n        #[repr(C)]\n        struct PartiallyInitializedClassObject<T: PyClassImpl> {\n            _ob_base: <T::BaseType as PyClassBaseType>::LayoutAsBase,\n            contents: MaybeUninit<PyClassObjectContents<T>>,\n        }\n        let obj = obj.cast::<PartiallyInitializedClassObject<T>>();\n        unsafe { &raw mut (*obj).contents }\n    }\n\n    fn contents(&self) -> &PyClassObjectContents<T> {\n        &self.contents\n    }\n\n    fn contents_mut(&mut self) -> &mut PyClassObjectContents<T> {\n        &mut self.contents\n    }\n\n    fn get_ptr(&self) -> *mut T {\n        self.contents.value.get()\n    }\n\n    fn ob_base(&self) -> &<T::BaseType as PyClassBaseType>::LayoutAsBase {\n        &self.ob_base\n    }\n\n    fn borrow_checker(&self) -> &<T::PyClassMutability as PyClassMutability>::Checker {\n        T::PyClassMutability::borrow_checker(self)\n    }\n}\n\nunsafe impl<T: PyClassImpl> PyLayout<T> for PyStaticClassObject<T> {}\nimpl<T: PyClass> PySizedLayout<T> for PyStaticClassObject<T> {}\n\nimpl<T: PyClassImpl<Layout = Self>> PyClassObjectBaseLayout<T> for PyStaticClassObject<T>\nwhere\n    <T::BaseType as PyClassBaseType>::LayoutAsBase: PyClassObjectBaseLayout<T::BaseType>,\n{\n    fn ensure_threadsafe(&self) {\n        self.contents.thread_checker.ensure();\n        self.ob_base.ensure_threadsafe();\n    }\n    fn check_threadsafe(&self) -> Result<(), PyBorrowError> {\n        if !self.contents.thread_checker.check() {\n            return Err(PyBorrowError { _private: () });\n        }\n        self.ob_base.check_threadsafe()\n    }\n    unsafe fn tp_dealloc(py: Python<'_>, slf: *mut ffi::PyObject) {\n        // Safety: Python only calls tp_dealloc when no references to the object remain.\n        let class_object = unsafe { &mut *(slf.cast::<T::Layout>()) };\n        unsafe { class_object.contents_mut().dealloc(py, slf) };\n        unsafe { <T::BaseType as PyClassBaseType>::LayoutAsBase::tp_dealloc(py, slf) }\n    }\n}\n\n/// A layout for a PyClassObject with an unknown sized base type.\n///\n/// Utilises [PEP-697](https://peps.python.org/pep-0697/)\n#[doc(hidden)]\n#[repr(C)]\npub struct PyVariableClassObject<T: PyClassImpl> {\n    ob_base: <T::BaseType as PyClassBaseType>::LayoutAsBase,\n}\n\n#[cfg(Py_3_12)]\nimpl<T: PyClass<Layout = Self>> PyVariableClassObject<T> {\n    /// # Safety\n    /// - `obj` must have the layout that the implementation is expecting\n    /// - thread must be attached to the interpreter\n    unsafe fn get_contents_of_obj(\n        obj: *mut ffi::PyObject,\n    ) -> *mut MaybeUninit<PyClassObjectContents<T>> {\n        // TODO: it would be nice to eventually avoid coupling to the PyO3 statics here, maybe using\n        // 3.14's PyType_GetBaseByToken, to support PEP 587 / multiple interpreters better\n        // SAFETY: caller guarantees attached to the interpreter\n        let type_obj = T::type_object_raw(unsafe { Python::assume_attached() });\n        let pointer = unsafe { ffi::PyObject_GetTypeData(obj, type_obj) };\n        pointer.cast()\n    }\n\n    fn get_contents_ptr(&self) -> *mut PyClassObjectContents<T> {\n        unsafe {\n            Self::get_contents_of_obj(self as *const PyVariableClassObject<T> as *mut ffi::PyObject)\n        }\n        .cast()\n    }\n}\n\n#[cfg(Py_3_12)]\nimpl<T: PyClass<Layout = Self>> PyClassObjectLayout<T> for PyVariableClassObject<T> {\n    /// Gets the offset of the contents from the start of the struct in bytes.\n    const CONTENTS_OFFSET: PyObjectOffset = PyObjectOffset::Relative(0);\n    const BASIC_SIZE: ffi::Py_ssize_t = {\n        let size = std::mem::size_of::<PyClassObjectContents<T>>();\n        assert!(size <= ffi::Py_ssize_t::MAX as usize);\n        // negative to indicate 'extra' space that cpython will allocate for us\n        -(size as ffi::Py_ssize_t)\n    };\n    const DICT_OFFSET: PyObjectOffset = {\n        let offset = offset_of!(PyClassObjectContents<T>, dict);\n        assert!(offset <= ffi::Py_ssize_t::MAX as usize);\n        PyObjectOffset::Relative(offset as _)\n    };\n    const WEAKLIST_OFFSET: PyObjectOffset = {\n        let offset = offset_of!(PyClassObjectContents<T>, weakref);\n        assert!(offset <= ffi::Py_ssize_t::MAX as usize);\n        PyObjectOffset::Relative(offset as _)\n    };\n\n    unsafe fn contents_uninit(\n        obj: *mut ffi::PyObject,\n    ) -> *mut MaybeUninit<PyClassObjectContents<T>> {\n        unsafe { Self::get_contents_of_obj(obj) }\n    }\n\n    fn get_ptr(&self) -> *mut T {\n        self.contents().value.get()\n    }\n\n    fn ob_base(&self) -> &<T::BaseType as PyClassBaseType>::LayoutAsBase {\n        &self.ob_base\n    }\n\n    fn contents(&self) -> &PyClassObjectContents<T> {\n        unsafe { self.get_contents_ptr().cast_const().as_ref() }\n            .expect(\"should be able to cast PyClassObjectContents pointer\")\n    }\n\n    fn contents_mut(&mut self) -> &mut PyClassObjectContents<T> {\n        unsafe { self.get_contents_ptr().as_mut() }\n            .expect(\"should be able to cast PyClassObjectContents pointer\")\n    }\n\n    fn borrow_checker(&self) -> &<T::PyClassMutability as PyClassMutability>::Checker {\n        T::PyClassMutability::borrow_checker(self)\n    }\n}\n\nunsafe impl<T: PyClassImpl> PyLayout<T> for PyVariableClassObject<T> {}\n\n#[cfg(Py_3_12)]\nimpl<T: PyClass<Layout = Self>> PyClassObjectBaseLayout<T> for PyVariableClassObject<T>\nwhere\n    <T::BaseType as PyClassBaseType>::LayoutAsBase: PyClassObjectBaseLayout<T::BaseType>,\n{\n    fn ensure_threadsafe(&self) {\n        self.contents().thread_checker.ensure();\n        self.ob_base.ensure_threadsafe();\n    }\n    fn check_threadsafe(&self) -> Result<(), PyBorrowError> {\n        if !self.contents().thread_checker.check() {\n            return Err(PyBorrowError { _private: () });\n        }\n        self.ob_base.check_threadsafe()\n    }\n    unsafe fn tp_dealloc(py: Python<'_>, slf: *mut ffi::PyObject) {\n        // Safety: Python only calls tp_dealloc when no references to the object remain.\n        let class_object = unsafe { &mut *(slf.cast::<T::Layout>()) };\n        unsafe { class_object.contents_mut().dealloc(py, slf) };\n        unsafe { <T::BaseType as PyClassBaseType>::LayoutAsBase::tp_dealloc(py, slf) }\n    }\n}\n\n#[cfg(test)]\n#[cfg(feature = \"macros\")]\nmod tests {\n    use super::*;\n\n    use crate::prelude::*;\n    use crate::pyclass::boolean_struct::{False, True};\n\n    #[pyclass(crate = \"crate\", subclass)]\n    struct MutableBase;\n\n    #[pyclass(crate = \"crate\", extends = MutableBase, subclass)]\n    struct MutableChildOfMutableBase;\n\n    #[pyclass(crate = \"crate\", extends = MutableBase, frozen, subclass)]\n    struct ImmutableChildOfMutableBase;\n\n    #[pyclass(crate = \"crate\", extends = MutableChildOfMutableBase)]\n    struct MutableChildOfMutableChildOfMutableBase;\n\n    #[pyclass(crate = \"crate\", extends = ImmutableChildOfMutableBase)]\n    struct MutableChildOfImmutableChildOfMutableBase;\n\n    #[pyclass(crate = \"crate\", extends = MutableChildOfMutableBase, frozen)]\n    struct ImmutableChildOfMutableChildOfMutableBase;\n\n    #[pyclass(crate = \"crate\", extends = ImmutableChildOfMutableBase, frozen)]\n    struct ImmutableChildOfImmutableChildOfMutableBase;\n\n    #[pyclass(crate = \"crate\", frozen, subclass)]\n    struct ImmutableBase;\n\n    #[pyclass(crate = \"crate\", extends = ImmutableBase, subclass)]\n    struct MutableChildOfImmutableBase;\n\n    #[pyclass(crate = \"crate\", extends = ImmutableBase, frozen, subclass)]\n    struct ImmutableChildOfImmutableBase;\n\n    #[pyclass(crate = \"crate\", extends = MutableChildOfImmutableBase)]\n    struct MutableChildOfMutableChildOfImmutableBase;\n\n    #[pyclass(crate = \"crate\", extends = ImmutableChildOfImmutableBase)]\n    struct MutableChildOfImmutableChildOfImmutableBase;\n\n    #[pyclass(crate = \"crate\", extends = MutableChildOfImmutableBase, frozen)]\n    struct ImmutableChildOfMutableChildOfImmutableBase;\n\n    #[pyclass(crate = \"crate\", extends = ImmutableChildOfImmutableBase, frozen)]\n    struct ImmutableChildOfImmutableChildOfImmutableBase;\n\n    #[pyclass(crate = \"crate\", subclass)]\n    struct BaseWithData(#[allow(unused)] u64);\n\n    #[pyclass(crate = \"crate\", extends = BaseWithData)]\n    struct ChildWithData(#[allow(unused)] u64);\n\n    #[pyclass(crate = \"crate\", extends = BaseWithData)]\n    struct ChildWithoutData;\n\n    #[test]\n    fn test_inherited_size() {\n        let base_size = PyStaticClassObject::<BaseWithData>::BASIC_SIZE;\n        assert!(base_size > 0); // negative indicates variable sized\n        assert_eq!(\n            base_size,\n            PyStaticClassObject::<ChildWithoutData>::BASIC_SIZE\n        );\n        assert!(base_size < PyStaticClassObject::<ChildWithData>::BASIC_SIZE);\n    }\n\n    fn assert_mutable<T: PyClass<Frozen = False, PyClassMutability = MutableClass>>() {}\n    fn assert_immutable<T: PyClass<Frozen = True, PyClassMutability = ImmutableClass>>() {}\n    fn assert_mutable_with_mutable_ancestor<\n        T: PyClass<Frozen = False, PyClassMutability = ExtendsMutableAncestor<MutableClass>>,\n    >() {\n    }\n    fn assert_immutable_with_mutable_ancestor<\n        T: PyClass<Frozen = True, PyClassMutability = ExtendsMutableAncestor<ImmutableClass>>,\n    >() {\n    }\n\n    #[test]\n    fn test_inherited_mutability() {\n        // mutable base\n        assert_mutable::<MutableBase>();\n\n        // children of mutable base have a mutable ancestor\n        assert_mutable_with_mutable_ancestor::<MutableChildOfMutableBase>();\n        assert_immutable_with_mutable_ancestor::<ImmutableChildOfMutableBase>();\n\n        // grandchildren of mutable base have a mutable ancestor\n        assert_mutable_with_mutable_ancestor::<MutableChildOfMutableChildOfMutableBase>();\n        assert_mutable_with_mutable_ancestor::<MutableChildOfImmutableChildOfMutableBase>();\n        assert_immutable_with_mutable_ancestor::<ImmutableChildOfMutableChildOfMutableBase>();\n        assert_immutable_with_mutable_ancestor::<ImmutableChildOfImmutableChildOfMutableBase>();\n\n        // immutable base and children\n        assert_immutable::<ImmutableBase>();\n        assert_immutable::<ImmutableChildOfImmutableBase>();\n        assert_immutable::<ImmutableChildOfImmutableChildOfImmutableBase>();\n\n        // mutable children of immutable at any level are simply mutable\n        assert_mutable::<MutableChildOfImmutableBase>();\n        assert_mutable::<MutableChildOfImmutableChildOfImmutableBase>();\n\n        // children of the mutable child display this property\n        assert_mutable_with_mutable_ancestor::<MutableChildOfMutableChildOfImmutableBase>();\n        assert_immutable_with_mutable_ancestor::<ImmutableChildOfMutableChildOfImmutableBase>();\n    }\n\n    #[test]\n    fn test_mutable_borrow_prevents_further_borrows() {\n        Python::attach(|py| {\n            let mmm = Py::new(\n                py,\n                PyClassInitializer::from(MutableBase)\n                    .add_subclass(MutableChildOfMutableBase)\n                    .add_subclass(MutableChildOfMutableChildOfMutableBase),\n            )\n            .unwrap();\n\n            let mmm_bound: &Bound<'_, MutableChildOfMutableChildOfMutableBase> = mmm.bind(py);\n\n            let mmm_refmut = mmm_bound.borrow_mut();\n\n            // Cannot take any other mutable or immutable borrows whilst the object is borrowed mutably\n            assert!(mmm_bound\n                .extract::<PyRef<'_, MutableChildOfMutableChildOfMutableBase>>()\n                .is_err());\n            assert!(mmm_bound\n                .extract::<PyRef<'_, MutableChildOfMutableBase>>()\n                .is_err());\n            assert!(mmm_bound.extract::<PyRef<'_, MutableBase>>().is_err());\n            assert!(mmm_bound\n                .extract::<PyRefMut<'_, MutableChildOfMutableChildOfMutableBase>>()\n                .is_err());\n            assert!(mmm_bound\n                .extract::<PyRefMut<'_, MutableChildOfMutableBase>>()\n                .is_err());\n            assert!(mmm_bound.extract::<PyRefMut<'_, MutableBase>>().is_err());\n\n            // With the borrow dropped, all other borrow attempts will succeed\n            drop(mmm_refmut);\n\n            assert!(mmm_bound\n                .extract::<PyRef<'_, MutableChildOfMutableChildOfMutableBase>>()\n                .is_ok());\n            assert!(mmm_bound\n                .extract::<PyRef<'_, MutableChildOfMutableBase>>()\n                .is_ok());\n            assert!(mmm_bound.extract::<PyRef<'_, MutableBase>>().is_ok());\n            assert!(mmm_bound\n                .extract::<PyRefMut<'_, MutableChildOfMutableChildOfMutableBase>>()\n                .is_ok());\n            assert!(mmm_bound\n                .extract::<PyRefMut<'_, MutableChildOfMutableBase>>()\n                .is_ok());\n            assert!(mmm_bound.extract::<PyRefMut<'_, MutableBase>>().is_ok());\n        })\n    }\n\n    #[test]\n    fn test_immutable_borrows_prevent_mutable_borrows() {\n        Python::attach(|py| {\n            let mmm = Py::new(\n                py,\n                PyClassInitializer::from(MutableBase)\n                    .add_subclass(MutableChildOfMutableBase)\n                    .add_subclass(MutableChildOfMutableChildOfMutableBase),\n            )\n            .unwrap();\n\n            let mmm_bound: &Bound<'_, MutableChildOfMutableChildOfMutableBase> = mmm.bind(py);\n\n            let mmm_refmut = mmm_bound.borrow();\n\n            // Further immutable borrows are ok\n            assert!(mmm_bound\n                .extract::<PyRef<'_, MutableChildOfMutableChildOfMutableBase>>()\n                .is_ok());\n            assert!(mmm_bound\n                .extract::<PyRef<'_, MutableChildOfMutableBase>>()\n                .is_ok());\n            assert!(mmm_bound.extract::<PyRef<'_, MutableBase>>().is_ok());\n\n            // Further mutable borrows are not ok\n            assert!(mmm_bound\n                .extract::<PyRefMut<'_, MutableChildOfMutableChildOfMutableBase>>()\n                .is_err());\n            assert!(mmm_bound\n                .extract::<PyRefMut<'_, MutableChildOfMutableBase>>()\n                .is_err());\n            assert!(mmm_bound.extract::<PyRefMut<'_, MutableBase>>().is_err());\n\n            // With the borrow dropped, all mutable borrow attempts will succeed\n            drop(mmm_refmut);\n\n            assert!(mmm_bound\n                .extract::<PyRefMut<'_, MutableChildOfMutableChildOfMutableBase>>()\n                .is_ok());\n            assert!(mmm_bound\n                .extract::<PyRefMut<'_, MutableChildOfMutableBase>>()\n                .is_ok());\n            assert!(mmm_bound.extract::<PyRefMut<'_, MutableBase>>().is_ok());\n        })\n    }\n\n    #[test]\n    #[cfg(not(target_arch = \"wasm32\"))]\n    fn test_thread_safety() {\n        #[crate::pyclass(crate = \"crate\")]\n        struct MyClass {\n            x: u64,\n        }\n\n        Python::attach(|py| {\n            let inst = Py::new(py, MyClass { x: 0 }).unwrap();\n\n            let total_modifications = py.detach(|| {\n                std::thread::scope(|s| {\n                    // Spawn a bunch of threads all racing to write to\n                    // the same instance of `MyClass`.\n                    let threads = (0..10)\n                        .map(|_| {\n                            s.spawn(|| {\n                                Python::attach(|py| {\n                                    // Each thread records its own view of how many writes it made\n                                    let mut local_modifications = 0;\n                                    for _ in 0..100 {\n                                        if let Ok(mut i) = inst.try_borrow_mut(py) {\n                                            i.x += 1;\n                                            local_modifications += 1;\n                                        }\n                                    }\n                                    local_modifications\n                                })\n                            })\n                        })\n                        .collect::<Vec<_>>();\n\n                    // Sum up the total number of writes made by all threads\n                    threads.into_iter().map(|t| t.join().unwrap()).sum::<u64>()\n                })\n            });\n\n            // If the implementation is free of data races, the total number of writes\n            // should match the final value of `x`.\n            assert_eq!(total_modifications, inst.borrow(py).x);\n        });\n    }\n\n    #[test]\n    #[cfg(not(target_arch = \"wasm32\"))]\n    fn test_thread_safety_2() {\n        struct SyncUnsafeCell<T>(UnsafeCell<T>);\n        unsafe impl<T> Sync for SyncUnsafeCell<T> {}\n\n        impl<T> SyncUnsafeCell<T> {\n            fn get(&self) -> *mut T {\n                self.0.get()\n            }\n        }\n\n        let data = SyncUnsafeCell(UnsafeCell::new(0));\n        let data2 = SyncUnsafeCell(UnsafeCell::new(0));\n        let borrow_checker = BorrowChecker(BorrowFlag(AtomicUsize::new(BorrowFlag::UNUSED)));\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                for _ in 0..1_000_000 {\n                    if borrow_checker.try_borrow_mut().is_ok() {\n                        // thread 1 writes to both values during the mutable borrow\n                        unsafe { *data.get() += 1 };\n                        unsafe { *data2.get() += 1 };\n                        borrow_checker.release_borrow_mut();\n                    }\n                }\n            });\n\n            s.spawn(|| {\n                for _ in 0..1_000_000 {\n                    if borrow_checker.try_borrow().is_ok() {\n                        // if the borrow checker is working correctly, it should be impossible\n                        // for thread 2 to observe a difference in the two values\n                        assert_eq!(unsafe { *data.get() }, unsafe { *data2.get() });\n                        borrow_checker.release_borrow();\n                    }\n                }\n            });\n        });\n    }\n}\n"
  },
  {
    "path": "src/pycell.rs",
    "content": "//! PyO3's interior mutability primitive.\n//!\n//! Rust has strict aliasing rules - you can either have any number of immutable (shared) references or one mutable\n//! reference. Python's ownership model is the complete opposite of that - any Python object\n//! can be referenced any number of times, and mutation is allowed from any reference.\n//!\n//! PyO3 deals with these differences by employing the [Interior Mutability]\n//! pattern. This requires that PyO3 enforces the borrowing rules and it has two mechanisms for\n//! doing so:\n//! - Statically it can enforce thread-safe access with the [`Python<'py>`](crate::Python) token.\n//!   All Rust code holding that token, or anything derived from it, can assume that they have\n//!   safe access to the Python interpreter's state. For this reason all the native Python objects\n//!   can be mutated through shared references.\n//! - However, methods and functions in Rust usually *do* need `&mut` references. While PyO3 can\n//!   use the [`Python<'py>`](crate::Python) token to guarantee thread-safe access to them, it cannot\n//!   statically guarantee uniqueness of `&mut` references. As such those references have to be tracked\n//!   dynamically at runtime, using `PyCell` and the other types defined in this module. This works\n//!   similar to std's [`RefCell`](std::cell::RefCell) type.\n//!\n//! # When *not* to use PyCell\n//!\n//! Usually you can use `&mut` references as method and function receivers and arguments, and you\n//! won't need to use `PyCell` directly:\n//!\n//! ```rust,no_run\n//! use pyo3::prelude::*;\n//!\n//! #[pyclass]\n//! struct Number {\n//!     inner: u32,\n//! }\n//!\n//! #[pymethods]\n//! impl Number {\n//!     fn increment(&mut self) {\n//!         self.inner += 1;\n//!     }\n//! }\n//! ```\n//!\n//! The [`#[pymethods]`](crate::pymethods) proc macro will generate this wrapper function (and more),\n//! using `PyCell` under the hood:\n//!\n//! ```rust,ignore\n//! # use pyo3::prelude::*;\n//! # #[pyclass]\n//! # struct Number {\n//! #    inner: u32,\n//! # }\n//! #\n//! # #[pymethods]\n//! # impl Number {\n//! #    fn increment(&mut self) {\n//! #        self.inner += 1;\n//! #    }\n//! # }\n//! #\n//! // The function which is exported to Python looks roughly like the following\n//! unsafe extern \"C\" fn __pymethod_increment__(\n//!     _slf: *mut pyo3::ffi::PyObject,\n//!     _args: *mut pyo3::ffi::PyObject,\n//! ) -> *mut pyo3::ffi::PyObject {\n//!     use :: pyo3 as _pyo3;\n//!     _pyo3::impl_::trampoline::noargs(_slf, _args, |py, _slf| {\n//! #       #[allow(deprecated)]\n//!         let _cell = py\n//!             .from_borrowed_ptr::<_pyo3::PyAny>(_slf)\n//!             .cast::<_pyo3::PyCell<Number>>()?;\n//!         let mut _ref = _cell.try_borrow_mut()?;\n//!         let _slf: &mut Number = &mut *_ref;\n//!         _pyo3::impl_::callback::convert(py, Number::increment(_slf))\n//!     })\n//! }\n//! ```\n//!\n//! # When to use PyCell\n//! ## Using pyclasses from Rust\n//!\n//! However, we *do* need `PyCell` if we want to call its methods from Rust:\n//! ```rust\n//! # use pyo3::prelude::*;\n//! #\n//! # #[pyclass]\n//! # struct Number {\n//! #     inner: u32,\n//! # }\n//! #\n//! # #[pymethods]\n//! # impl Number {\n//! #     fn increment(&mut self) {\n//! #         self.inner += 1;\n//! #     }\n//! # }\n//! # fn main() -> PyResult<()> {\n//! Python::attach(|py| {\n//!     let n = Py::new(py, Number { inner: 0 })?;\n//!\n//!     // We borrow the guard and then dereference\n//!     // it to get a mutable reference to Number\n//!     let mut guard: PyRefMut<'_, Number> = n.bind(py).borrow_mut();\n//!     let n_mutable: &mut Number = &mut *guard;\n//!\n//!     n_mutable.increment();\n//!\n//!     // To avoid panics we must dispose of the\n//!     // `PyRefMut` before borrowing again.\n//!     drop(guard);\n//!\n//!     let n_immutable: &Number = &n.bind(py).borrow();\n//!     assert_eq!(n_immutable.inner, 1);\n//!\n//!     Ok(())\n//! })\n//! # }\n//! ```\n//! ## Dealing with possibly overlapping mutable references\n//!\n//! It is also necessary to use `PyCell` if you can receive mutable arguments that may overlap.\n//! Suppose the following function that swaps the values of two `Number`s:\n//! ```\n//! # use pyo3::prelude::*;\n//! # #[pyclass]\n//! # pub struct Number {\n//! #     inner: u32,\n//! # }\n//! #[pyfunction]\n//! fn swap_numbers(a: &mut Number, b: &mut Number) {\n//!     std::mem::swap(&mut a.inner, &mut b.inner);\n//! }\n//! # fn main() {\n//! #     Python::attach(|py| {\n//! #         let n = Py::new(py, Number{inner: 35}).unwrap();\n//! #         let n2 = n.clone_ref(py);\n//! #         assert!(n.is(&n2));\n//! #         let fun = pyo3::wrap_pyfunction!(swap_numbers, py).unwrap();\n//! #         fun.call1((n, n2)).expect_err(\"Managed to create overlapping mutable references. Note: this is undefined behaviour.\");\n//! #     });\n//! # }\n//! ```\n//! When users pass in the same `Number` as both arguments, one of the mutable borrows will\n//! fail and raise a `RuntimeError`:\n//! ```text\n//! >>> a = Number()\n//! >>> swap_numbers(a, a)\n//! Traceback (most recent call last):\n//!   File \"<stdin>\", line 1, in <module>\n//!   RuntimeError: Already borrowed\n//! ```\n//!\n//! It is better to write that function like this:\n//! ```rust,ignore\n//! # #![allow(deprecated)]\n//! # use pyo3::prelude::*;\n//! # #[pyclass]\n//! # pub struct Number {\n//! #     inner: u32,\n//! # }\n//! #[pyfunction]\n//! fn swap_numbers(a: &PyCell<Number>, b: &PyCell<Number>) {\n//!     // Check that the pointers are unequal\n//!     if !a.is(b) {\n//!         std::mem::swap(&mut a.borrow_mut().inner, &mut b.borrow_mut().inner);\n//!     } else {\n//!         // Do nothing - they are the same object, so don't need swapping.\n//!     }\n//! }\n//! # fn main() {\n//! #     // With duplicate numbers\n//! #     Python::attach(|py| {\n//! #         let n = Py::new(py, Number{inner: 35}).unwrap();\n//! #         let n2 = n.clone_ref(py);\n//! #         assert!(n.is(&n2));\n//! #         let fun = pyo3::wrap_pyfunction!(swap_numbers, py).unwrap();\n//! #         fun.call1((n, n2)).unwrap();\n//! #     });\n//! #\n//! #     // With two different numbers\n//! #     Python::attach(|py| {\n//! #         let n = Py::new(py, Number{inner: 35}).unwrap();\n//! #         let n2 = Py::new(py, Number{inner: 42}).unwrap();\n//! #         assert!(!n.is(&n2));\n//! #         let fun = pyo3::wrap_pyfunction!(swap_numbers, py).unwrap();\n//! #         fun.call1((&n, &n2)).unwrap();\n//! #         let n: u32 = n.borrow(py).inner;\n//! #         let n2: u32 = n2.borrow(py).inner;\n//! #         assert_eq!(n, 42);\n//! #         assert_eq!(n2, 35);\n//! #     });\n//! # }\n//! ```\n//! See the [guide] for more information.\n//!\n//! [guide]: https://pyo3.rs/latest/class.html#pycell-and-interior-mutability \"PyCell and interior mutability\"\n//! [Interior Mutability]: https://doc.rust-lang.org/book/ch15-05-interior-mutability.html \"RefCell<T> and the Interior Mutability Pattern - The Rust Programming Language\"\n\nuse crate::conversion::IntoPyObject;\nuse crate::exceptions::PyRuntimeError;\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::pyclass::{boolean_struct::False, PyClass};\nuse crate::{ffi, Borrowed, Bound, PyErr, Python};\nuse std::convert::Infallible;\nuse std::fmt;\nuse std::mem::ManuallyDrop;\nuse std::ops::{Deref, DerefMut};\nuse std::ptr::NonNull;\n\npub(crate) mod impl_;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\nuse impl_::{PyClassBorrowChecker, PyClassObjectBaseLayout, PyClassObjectLayout};\n\n/// A wrapper type for an immutably borrowed value from a [`Bound<'py, T>`].\n///\n/// See the [`Bound`] documentation for more information.\n///\n/// # Examples\n///\n/// You can use [`PyRef`] as an alternative to a `&self` receiver when\n/// - you need to access the pointer of the [`Bound`], or\n/// - you want to get a super class.\n/// ```\n/// # use pyo3::prelude::*;\n/// #[pyclass(subclass)]\n/// struct Parent {\n///     basename: &'static str,\n/// }\n///\n/// #[pyclass(extends=Parent)]\n/// struct Child {\n///     name: &'static str,\n///  }\n///\n/// #[pymethods]\n/// impl Child {\n///     #[new]\n///     fn new() -> (Self, Parent) {\n///         (Child { name: \"Caterpillar\" }, Parent { basename: \"Butterfly\" })\n///     }\n///\n///     fn format(slf: PyRef<'_, Self>) -> String {\n///         // We can get *mut ffi::PyObject from PyRef\n///         let refcnt = unsafe { pyo3::ffi::Py_REFCNT(slf.as_ptr()) };\n///         // We can get &Self::BaseType by as_ref\n///         let basename = slf.as_ref().basename;\n///         format!(\"{}(base: {}, cnt: {})\", slf.name, basename, refcnt)\n///     }\n/// }\n/// # Python::attach(|py| {\n/// #     let sub = Py::new(py, Child::new()).unwrap();\n/// #     pyo3::py_run!(py, sub, \"assert sub.format() == 'Caterpillar(base: Butterfly, cnt: 4)', sub.format()\");\n/// # });\n/// ```\n///\n/// See the [module-level documentation](self) for more information.\n#[repr(transparent)]\npub struct PyRef<'p, T: PyClass> {\n    // TODO: once the GIL Ref API is removed, consider adding a lifetime parameter to `PyRef` to\n    // store `Borrowed` here instead, avoiding reference counting overhead.\n    inner: Bound<'p, T>,\n}\n\nimpl<'p, T: PyClass> PyRef<'p, T> {\n    /// Returns a `Python` token that is bound to the lifetime of the `PyRef`.\n    pub fn py(&self) -> Python<'p> {\n        self.inner.py()\n    }\n}\n\nimpl<T, U> AsRef<U> for PyRef<'_, T>\nwhere\n    T: PyClass<BaseType = U>,\n    U: PyClass,\n{\n    fn as_ref(&self) -> &T::BaseType {\n        self.as_super()\n    }\n}\n\nimpl<'py, T: PyClass> PyRef<'py, T> {\n    /// Returns the raw FFI pointer represented by self.\n    ///\n    /// # Safety\n    ///\n    /// Callers are responsible for ensuring that the pointer does not outlive self.\n    ///\n    /// The reference is borrowed; callers should not decrease the reference count\n    /// when they are finished with the pointer.\n    #[inline]\n    pub fn as_ptr(&self) -> *mut ffi::PyObject {\n        self.inner.as_ptr()\n    }\n\n    /// Returns an owned raw FFI pointer represented by self.\n    ///\n    /// # Safety\n    ///\n    /// The reference is owned; when finished the caller should either transfer ownership\n    /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)).\n    #[inline]\n    pub fn into_ptr(self) -> *mut ffi::PyObject {\n        self.inner.clone().into_ptr()\n    }\n\n    #[track_caller]\n    pub(crate) fn borrow(obj: &Bound<'py, T>) -> Self {\n        Self::try_borrow(obj).expect(\"Already mutably borrowed\")\n    }\n\n    pub(crate) fn try_borrow(obj: &Bound<'py, T>) -> Result<Self, PyBorrowError> {\n        let cell = obj.get_class_object();\n        cell.ensure_threadsafe();\n        cell.borrow_checker()\n            .try_borrow()\n            .map(|_| Self { inner: obj.clone() })\n    }\n}\n\nimpl<'p, T> PyRef<'p, T>\nwhere\n    T: PyClass,\n    T::BaseType: PyClass,\n{\n    /// Gets a `PyRef<T::BaseType>`.\n    ///\n    /// While `as_ref()` returns a reference of type `&T::BaseType`, this cannot be\n    /// used to get the base of `T::BaseType`.\n    ///\n    /// But with the help of this method, you can get hold of instances of the\n    /// super-superclass when needed.\n    ///\n    /// # Examples\n    /// ```\n    /// # use pyo3::prelude::*;\n    /// #[pyclass(subclass)]\n    /// struct Base1 {\n    ///     name1: &'static str,\n    /// }\n    ///\n    /// #[pyclass(extends=Base1, subclass)]\n    /// struct Base2 {\n    ///     name2: &'static str,\n    /// }\n    ///\n    /// #[pyclass(extends=Base2)]\n    /// struct Sub {\n    ///     name3: &'static str,\n    /// }\n    ///\n    /// #[pymethods]\n    /// impl Sub {\n    ///     #[new]\n    ///     fn new() -> PyClassInitializer<Self> {\n    ///         PyClassInitializer::from(Base1 { name1: \"base1\" })\n    ///             .add_subclass(Base2 { name2: \"base2\" })\n    ///             .add_subclass(Self { name3: \"sub\" })\n    ///     }\n    ///     fn name(slf: PyRef<'_, Self>) -> String {\n    ///         let subname = slf.name3;\n    ///         let super_ = slf.into_super();\n    ///         format!(\"{} {} {}\", super_.as_ref().name1, super_.name2, subname)\n    ///     }\n    /// }\n    /// # Python::attach(|py| {\n    /// #     let sub = Py::new(py, Sub::new()).unwrap();\n    /// #     pyo3::py_run!(py, sub, \"assert sub.name() == 'base1 base2 sub'\")\n    /// # });\n    /// ```\n    pub fn into_super(self) -> PyRef<'p, T::BaseType> {\n        let py = self.py();\n        let t_not_frozen = !<T::Frozen as crate::pyclass::boolean_struct::private::Boolean>::VALUE;\n        let u_frozen = <<T::BaseType as PyClass>::Frozen as crate::pyclass::boolean_struct::private::Boolean>::VALUE;\n        if t_not_frozen && u_frozen {\n            // If `T` is mutable subclass of `U` differ, then it is possible that we need to\n            // release the borrow count now. (e.g. `U` may have a noop borrow checker so\n            // dropping the `PyRef<U>` later would noop and leak the borrow we currently hold.)\n            //\n            // However it's nontrivial, if `U` itself has a mutable base class `V`,\n            // then the borrow checker of both `T` and `U` is the shared borrow checker of `V`.\n            //\n            // But it's really hard to prove that in the type system, the soundest thing we\n            // can do is just add a borrow to `U` now and then release the borrow of `T`.\n\n            self.inner\n                .as_super()\n                .get_class_object()\n                .borrow_checker()\n                .try_borrow()\n                .expect(\"this object is already borrowed\");\n\n            self.inner\n                .get_class_object()\n                .borrow_checker()\n                .release_borrow()\n        };\n        PyRef {\n            inner: unsafe {\n                ManuallyDrop::new(self)\n                    .as_ptr()\n                    .assume_owned_unchecked(py)\n                    .cast_into_unchecked()\n            },\n        }\n    }\n\n    /// Borrows a shared reference to `PyRef<T::BaseType>`.\n    ///\n    /// With the help of this method, you can access attributes and call methods\n    /// on the superclass without consuming the `PyRef<T>`. This method can also\n    /// be chained to access the super-superclass (and so on).\n    ///\n    /// # Examples\n    /// ```\n    /// # use pyo3::prelude::*;\n    /// #[pyclass(subclass)]\n    /// struct Base {\n    ///     base_name: &'static str,\n    /// }\n    /// #[pymethods]\n    /// impl Base {\n    ///     fn base_name_len(&self) -> usize {\n    ///         self.base_name.len()\n    ///     }\n    /// }\n    ///\n    /// #[pyclass(extends=Base)]\n    /// struct Sub {\n    ///     sub_name: &'static str,\n    /// }\n    ///\n    /// #[pymethods]\n    /// impl Sub {\n    ///     #[new]\n    ///     fn new() -> (Self, Base) {\n    ///         (Self { sub_name: \"sub_name\" }, Base { base_name: \"base_name\" })\n    ///     }\n    ///     fn sub_name_len(&self) -> usize {\n    ///         self.sub_name.len()\n    ///     }\n    ///     fn format_name_lengths(slf: PyRef<'_, Self>) -> String {\n    ///         format!(\"{} {}\", slf.as_super().base_name_len(), slf.sub_name_len())\n    ///     }\n    /// }\n    /// # Python::attach(|py| {\n    /// #     let sub = Py::new(py, Sub::new()).unwrap();\n    /// #     pyo3::py_run!(py, sub, \"assert sub.format_name_lengths() == '9 8'\")\n    /// # });\n    /// ```\n    pub fn as_super(&self) -> &PyRef<'p, T::BaseType> {\n        let ptr = NonNull::from(&self.inner)\n            // `Bound<T>` has the same layout as `Bound<T::BaseType>`\n            .cast::<Bound<'p, T::BaseType>>()\n            // `Bound<T::BaseType>` has the same layout as `PyRef<T::BaseType>`\n            .cast::<PyRef<'p, T::BaseType>>();\n        // SAFETY: lifetimes are correctly transferred, and `PyRef<T>` and `PyRef<U>` have the same layout\n        unsafe { ptr.as_ref() }\n    }\n}\n\nimpl<T: PyClass> Deref for PyRef<'_, T> {\n    type Target = T;\n\n    #[inline]\n    fn deref(&self) -> &T {\n        unsafe { &*self.inner.get_class_object().get_ptr() }\n    }\n}\n\nimpl<T: PyClass> Drop for PyRef<'_, T> {\n    fn drop(&mut self) {\n        self.inner\n            .get_class_object()\n            .borrow_checker()\n            .release_borrow()\n    }\n}\n\nimpl<'py, T: PyClass> IntoPyObject<'py> for PyRef<'py, T> {\n    type Target = T;\n    type Output = Bound<'py, T>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.inner.clone())\n    }\n}\n\nimpl<'a, 'py, T: PyClass> IntoPyObject<'py> for &'a PyRef<'py, T> {\n    type Target = T;\n    type Output = Borrowed<'a, 'py, T>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.inner.as_borrowed())\n    }\n}\n\nimpl<T: PyClass + fmt::Debug> fmt::Debug for PyRef<'_, T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt::Debug::fmt(&**self, f)\n    }\n}\n\n/// A wrapper type for a mutably borrowed value from a [`Bound<'py, T>`].\n///\n/// See the [module-level documentation](self) for more information.\n#[repr(transparent)]\npub struct PyRefMut<'p, T: PyClass<Frozen = False>> {\n    // TODO: once the GIL Ref API is removed, consider adding a lifetime parameter to `PyRef` to\n    // store `Borrowed` here instead, avoiding reference counting overhead.\n    inner: Bound<'p, T>,\n}\n\nimpl<'p, T: PyClass<Frozen = False>> PyRefMut<'p, T> {\n    /// Returns a `Python` token that is bound to the lifetime of the `PyRefMut`.\n    pub fn py(&self) -> Python<'p> {\n        self.inner.py()\n    }\n}\n\nimpl<T> AsRef<T::BaseType> for PyRefMut<'_, T>\nwhere\n    T: PyClass<Frozen = False>,\n    T::BaseType: PyClass<Frozen = False>,\n{\n    fn as_ref(&self) -> &T::BaseType {\n        PyRefMut::downgrade(self).as_super()\n    }\n}\n\nimpl<T> AsMut<T::BaseType> for PyRefMut<'_, T>\nwhere\n    T: PyClass<Frozen = False>,\n    T::BaseType: PyClass<Frozen = False>,\n{\n    fn as_mut(&mut self) -> &mut T::BaseType {\n        self.as_super()\n    }\n}\n\nimpl<'py, T: PyClass<Frozen = False>> PyRefMut<'py, T> {\n    /// Returns the raw FFI pointer represented by self.\n    ///\n    /// # Safety\n    ///\n    /// Callers are responsible for ensuring that the pointer does not outlive self.\n    ///\n    /// The reference is borrowed; callers should not decrease the reference count\n    /// when they are finished with the pointer.\n    #[inline]\n    pub fn as_ptr(&self) -> *mut ffi::PyObject {\n        self.inner.as_ptr()\n    }\n\n    /// Returns an owned raw FFI pointer represented by self.\n    ///\n    /// # Safety\n    ///\n    /// The reference is owned; when finished the caller should either transfer ownership\n    /// of the pointer or decrease the reference count (e.g. with [`pyo3::ffi::Py_DecRef`](crate::ffi::Py_DecRef)).\n    #[inline]\n    pub fn into_ptr(self) -> *mut ffi::PyObject {\n        self.inner.clone().into_ptr()\n    }\n\n    #[inline]\n    #[track_caller]\n    pub(crate) fn borrow(obj: &Bound<'py, T>) -> Self {\n        Self::try_borrow(obj).expect(\"Already borrowed\")\n    }\n\n    pub(crate) fn try_borrow(obj: &Bound<'py, T>) -> Result<Self, PyBorrowMutError> {\n        let cell = obj.get_class_object();\n        cell.ensure_threadsafe();\n        cell.borrow_checker()\n            .try_borrow_mut()\n            .map(|_| Self { inner: obj.clone() })\n    }\n\n    pub(crate) fn downgrade(slf: &Self) -> &PyRef<'py, T> {\n        let ptr = NonNull::from(slf).cast();\n        // SAFETY: `PyRefMut<T>` and `PyRef<T>` have the same layout\n        unsafe { ptr.as_ref() }\n    }\n}\n\nimpl<'p, T> PyRefMut<'p, T>\nwhere\n    T: PyClass<Frozen = False>,\n    T::BaseType: PyClass<Frozen = False>,\n{\n    /// Gets a `PyRef<T::BaseType>`.\n    ///\n    /// See [`PyRef::into_super`] for more.\n    pub fn into_super(self) -> PyRefMut<'p, T::BaseType> {\n        let py = self.py();\n        PyRefMut {\n            inner: unsafe {\n                ManuallyDrop::new(self)\n                    .as_ptr()\n                    .assume_owned_unchecked(py)\n                    .cast_into_unchecked()\n            },\n        }\n    }\n\n    /// Borrows a mutable reference to `PyRefMut<T::BaseType>`.\n    ///\n    /// With the help of this method, you can mutate attributes and call mutating\n    /// methods on the superclass without consuming the `PyRefMut<T>`. This method\n    /// can also be chained to access the super-superclass (and so on).\n    ///\n    /// See [`PyRef::as_super`] for more.\n    pub fn as_super(&mut self) -> &mut PyRefMut<'p, T::BaseType> {\n        let mut ptr = NonNull::from(&mut self.inner)\n            // `Bound<T>` has the same layout as `Bound<T::BaseType>`\n            .cast::<Bound<'p, T::BaseType>>()\n            // `Bound<T::BaseType>` has the same layout as `PyRefMut<T::BaseType>`,\n            // and the mutable borrow on `self` prevents aliasing\n            .cast::<PyRefMut<'p, T::BaseType>>();\n        // SAFETY: lifetimes are correctly transferred, and `PyRefMut<T>` and `PyRefMut<U>` have the same layout\n        unsafe { ptr.as_mut() }\n    }\n}\n\nimpl<T: PyClass<Frozen = False>> Deref for PyRefMut<'_, T> {\n    type Target = T;\n\n    #[inline]\n    fn deref(&self) -> &T {\n        unsafe { &*self.inner.get_class_object().get_ptr() }\n    }\n}\n\nimpl<T: PyClass<Frozen = False>> DerefMut for PyRefMut<'_, T> {\n    #[inline]\n    fn deref_mut(&mut self) -> &mut T {\n        unsafe { &mut *self.inner.get_class_object().get_ptr() }\n    }\n}\n\nimpl<T: PyClass<Frozen = False>> Drop for PyRefMut<'_, T> {\n    fn drop(&mut self) {\n        self.inner\n            .get_class_object()\n            .borrow_checker()\n            .release_borrow_mut()\n    }\n}\n\nimpl<'py, T: PyClass<Frozen = False>> IntoPyObject<'py> for PyRefMut<'py, T> {\n    type Target = T;\n    type Output = Bound<'py, T>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.inner.clone())\n    }\n}\n\nimpl<'a, 'py, T: PyClass<Frozen = False>> IntoPyObject<'py> for &'a PyRefMut<'py, T> {\n    type Target = T;\n    type Output = Borrowed<'a, 'py, T>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\n\n    fn into_pyobject(self, _py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(self.inner.as_borrowed())\n    }\n}\n\nimpl<T: PyClass<Frozen = False> + fmt::Debug> fmt::Debug for PyRefMut<'_, T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt::Debug::fmt(self.deref(), f)\n    }\n}\n\n/// An error type returned by [`Bound::try_borrow`].\n///\n/// If this error is allowed to bubble up into Python code it will raise a `RuntimeError`.\npub struct PyBorrowError {\n    _private: (),\n}\n\nimpl PyBorrowError {\n    pub(crate) fn new() -> Self {\n        Self { _private: () }\n    }\n}\n\nimpl fmt::Debug for PyBorrowError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"PyBorrowError\").finish()\n    }\n}\n\nimpl fmt::Display for PyBorrowError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt::Display::fmt(\"Already mutably borrowed\", f)\n    }\n}\n\nimpl From<PyBorrowError> for PyErr {\n    fn from(other: PyBorrowError) -> Self {\n        PyRuntimeError::new_err(other.to_string())\n    }\n}\n\n/// An error type returned by [`Bound::try_borrow_mut`].\n///\n/// If this error is allowed to bubble up into Python code it will raise a `RuntimeError`.\npub struct PyBorrowMutError {\n    _private: (),\n}\n\nimpl PyBorrowMutError {\n    pub(crate) fn new() -> Self {\n        Self { _private: () }\n    }\n}\n\nimpl fmt::Debug for PyBorrowMutError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        f.debug_struct(\"PyBorrowMutError\").finish()\n    }\n}\n\nimpl fmt::Display for PyBorrowMutError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        fmt::Display::fmt(\"Already borrowed\", f)\n    }\n}\n\nimpl From<PyBorrowMutError> for PyErr {\n    fn from(other: PyBorrowMutError) -> Self {\n        PyRuntimeError::new_err(other.to_string())\n    }\n}\n\n#[cfg(test)]\n#[cfg(feature = \"macros\")]\nmod tests {\n\n    use super::*;\n\n    #[crate::pyclass(skip_from_py_object)]\n    #[pyo3(crate = \"crate\")]\n    #[derive(Copy, Clone, PartialEq, Eq, Debug)]\n    struct SomeClass(i32);\n\n    #[test]\n    fn test_as_ptr() {\n        Python::attach(|py| {\n            let cell = Bound::new(py, SomeClass(0)).unwrap();\n            let ptr = cell.as_ptr();\n\n            assert_eq!(cell.borrow().as_ptr(), ptr);\n            assert_eq!(cell.borrow_mut().as_ptr(), ptr);\n        })\n    }\n\n    #[test]\n    fn test_into_ptr() {\n        Python::attach(|py| {\n            let cell = Bound::new(py, SomeClass(0)).unwrap();\n            let ptr = cell.as_ptr();\n\n            assert_eq!(cell.borrow().into_ptr(), ptr);\n            unsafe { ffi::Py_DECREF(ptr) };\n\n            assert_eq!(cell.borrow_mut().into_ptr(), ptr);\n            unsafe { ffi::Py_DECREF(ptr) };\n        })\n    }\n\n    #[crate::pyclass]\n    #[pyo3(crate = \"crate\", subclass)]\n    struct BaseClass {\n        val1: usize,\n    }\n\n    #[crate::pyclass]\n    #[pyo3(crate = \"crate\", extends=BaseClass, subclass)]\n    struct SubClass {\n        val2: usize,\n    }\n\n    #[crate::pyclass]\n    #[pyo3(crate = \"crate\", extends=SubClass)]\n    struct SubSubClass {\n        val3: usize,\n    }\n\n    #[crate::pymethods]\n    #[pyo3(crate = \"crate\")]\n    impl SubSubClass {\n        #[new]\n        fn new(py: Python<'_>) -> crate::Py<SubSubClass> {\n            let init = crate::PyClassInitializer::from(BaseClass { val1: 10 })\n                .add_subclass(SubClass { val2: 15 })\n                .add_subclass(SubSubClass { val3: 20 });\n            crate::Py::new(py, init).expect(\"allocation error\")\n        }\n\n        fn get_values(self_: PyRef<'_, Self>) -> (usize, usize, usize) {\n            let val1 = self_.as_super().as_super().val1;\n            let val2 = self_.as_super().val2;\n            (val1, val2, self_.val3)\n        }\n\n        fn double_values(mut self_: PyRefMut<'_, Self>) {\n            self_.as_super().as_super().val1 *= 2;\n            self_.as_super().val2 *= 2;\n            self_.val3 *= 2;\n        }\n    }\n\n    #[test]\n    fn test_pyref_as_super() {\n        Python::attach(|py| {\n            let obj = SubSubClass::new(py).into_bound(py);\n            let pyref = obj.borrow();\n            assert_eq!(pyref.as_super().as_super().val1, 10);\n            assert_eq!(pyref.as_super().val2, 15);\n            assert_eq!(pyref.as_ref().val2, 15); // `as_ref` also works\n            assert_eq!(pyref.val3, 20);\n            assert_eq!(SubSubClass::get_values(pyref), (10, 15, 20));\n        });\n    }\n\n    #[test]\n    fn test_pyrefmut_as_super() {\n        Python::attach(|py| {\n            let obj = SubSubClass::new(py).into_bound(py);\n            assert_eq!(SubSubClass::get_values(obj.borrow()), (10, 15, 20));\n            {\n                let mut pyrefmut = obj.borrow_mut();\n                assert_eq!(pyrefmut.as_super().as_ref().val1, 10);\n                pyrefmut.as_super().as_super().val1 -= 5;\n                pyrefmut.as_super().val2 -= 3;\n                pyrefmut.as_mut().val2 -= 2; // `as_mut` also works\n                pyrefmut.val3 -= 5;\n            }\n            assert_eq!(SubSubClass::get_values(obj.borrow()), (5, 10, 15));\n            SubSubClass::double_values(obj.borrow_mut());\n            assert_eq!(SubSubClass::get_values(obj.borrow()), (10, 20, 30));\n        });\n    }\n\n    #[test]\n    fn test_pyrefs_in_python() {\n        Python::attach(|py| {\n            let obj = SubSubClass::new(py);\n            crate::py_run!(py, obj, \"assert obj.get_values() == (10, 15, 20)\");\n            crate::py_run!(py, obj, \"assert obj.double_values() is None\");\n            crate::py_run!(py, obj, \"assert obj.get_values() == (20, 30, 40)\");\n        });\n    }\n\n    #[test]\n    fn test_into_frozen_super_released_borrow() {\n        #[crate::pyclass]\n        #[pyo3(crate = \"crate\", subclass, frozen)]\n        struct BaseClass {}\n\n        #[crate::pyclass]\n        #[pyo3(crate = \"crate\", extends=BaseClass, subclass)]\n        struct SubClass {}\n\n        #[crate::pymethods]\n        #[pyo3(crate = \"crate\")]\n        impl SubClass {\n            #[new]\n            fn new(py: Python<'_>) -> Bound<'_, SubClass> {\n                let init = crate::PyClassInitializer::from(BaseClass {}).add_subclass(SubClass {});\n                Bound::new(py, init).expect(\"allocation error\")\n            }\n        }\n\n        Python::attach(|py| {\n            let obj = SubClass::new(py);\n            drop(obj.borrow().into_super());\n            assert!(obj.try_borrow_mut().is_ok());\n        })\n    }\n\n    #[test]\n    fn test_into_frozen_super_mutable_base_holds_borrow() {\n        #[crate::pyclass]\n        #[pyo3(crate = \"crate\", subclass)]\n        struct BaseClass {}\n\n        #[crate::pyclass]\n        #[pyo3(crate = \"crate\", extends=BaseClass, subclass, frozen)]\n        struct SubClass {}\n\n        #[crate::pyclass]\n        #[pyo3(crate = \"crate\", extends=SubClass, subclass)]\n        struct SubSubClass {}\n\n        #[crate::pymethods]\n        #[pyo3(crate = \"crate\")]\n        impl SubSubClass {\n            #[new]\n            fn new(py: Python<'_>) -> Bound<'_, SubSubClass> {\n                let init = crate::PyClassInitializer::from(BaseClass {})\n                    .add_subclass(SubClass {})\n                    .add_subclass(SubSubClass {});\n                Bound::new(py, init).expect(\"allocation error\")\n            }\n        }\n\n        Python::attach(|py| {\n            let obj = SubSubClass::new(py);\n            let _super_borrow = obj.borrow().into_super();\n            // the whole object still has an immutable borrow, so we cannot\n            // borrow any part mutably (the borrowflag is shared)\n            assert!(obj.try_borrow_mut().is_err());\n        })\n    }\n}\n"
  },
  {
    "path": "src/pyclass/create_type_object.rs",
    "content": "use crate::exceptions::PyAttributeError;\nuse crate::impl_::pymethods::{Deleter, PyDeleterDef};\n#[cfg(not(Py_3_10))]\nuse crate::types::typeobject::PyTypeMethods;\nuse crate::{\n    exceptions::PyTypeError,\n    ffi,\n    ffi_ptr_ext::FfiPtrExt,\n    impl_::{\n        pyclass::{\n            assign_sequence_item_from_mapping, get_sequence_item_from_mapping, tp_dealloc,\n            tp_dealloc_with_gc, PyClassImpl, PyClassItemsIter, PyObjectOffset,\n        },\n        pymethods::{Getter, PyGetterDef, PyMethodDefType, PySetterDef, Setter, _call_clear},\n        trampoline::trampoline,\n    },\n    pycell::impl_::PyClassObjectLayout,\n    types::PyType,\n    Py, PyClass, PyResult, PyTypeInfo, Python,\n};\nuse std::{\n    collections::HashMap,\n    ffi::{CStr, CString},\n    os::raw::{c_char, c_int, c_ulong, c_void},\n    ptr::{self, NonNull},\n};\n\npub(crate) struct PyClassTypeObject {\n    pub type_object: Py<PyType>,\n    pub is_immutable_type: bool,\n    #[expect(\n        dead_code,\n        reason = \"this is just storage that must live as long as the type object\"\n    )]\n    getset_defs: Vec<GetSetDefType>,\n}\n\npub(crate) fn create_type_object<T>(py: Python<'_>) -> PyResult<PyClassTypeObject>\nwhere\n    T: PyClass,\n{\n    // Written this way to monomorphize the majority of the logic.\n    #[expect(clippy::too_many_arguments)]\n    unsafe fn inner(\n        py: Python<'_>,\n        base: *mut ffi::PyTypeObject,\n        dealloc: unsafe extern \"C\" fn(*mut ffi::PyObject),\n        dealloc_with_gc: unsafe extern \"C\" fn(*mut ffi::PyObject),\n        is_mapping: bool,\n        is_sequence: bool,\n        is_immutable_type: bool,\n        doc: &'static CStr,\n        dict_offset: Option<PyObjectOffset>,\n        weaklist_offset: Option<PyObjectOffset>,\n        is_basetype: bool,\n        items_iter: PyClassItemsIter,\n        name: &'static str,\n        module: Option<&'static str>,\n        basicsize: ffi::Py_ssize_t,\n    ) -> PyResult<PyClassTypeObject> {\n        unsafe {\n            PyTypeBuilder {\n                slots: Vec::new(),\n                method_defs: Vec::new(),\n                member_defs: Vec::new(),\n                getset_builders: HashMap::new(),\n                #[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))]\n                cleanup: Vec::new(),\n                tp_base: base,\n                tp_dealloc: dealloc,\n                tp_dealloc_with_gc: dealloc_with_gc,\n                is_mapping,\n                is_sequence,\n                is_immutable_type,\n                has_new: false,\n                has_dealloc: false,\n                has_getitem: false,\n                has_setitem: false,\n                has_traverse: false,\n                has_clear: false,\n                dict_offset: None,\n                class_flags: 0,\n                #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))]\n                buffer_procs: Default::default(),\n            }\n            .type_doc(doc)\n            .offsets(dict_offset, weaklist_offset)\n            .set_is_basetype(is_basetype)\n            .class_items(items_iter)\n            .build(py, name, module, basicsize)\n        }\n    }\n\n    unsafe {\n        inner(\n            py,\n            T::BaseType::type_object_raw(py),\n            tp_dealloc::<T>,\n            tp_dealloc_with_gc::<T>,\n            T::IS_MAPPING,\n            T::IS_SEQUENCE,\n            T::IS_IMMUTABLE_TYPE,\n            T::DOC,\n            T::dict_offset(),\n            T::weaklist_offset(),\n            T::IS_BASETYPE,\n            T::items_iter(),\n            <T as PyClass>::NAME,\n            <T as PyClassImpl>::MODULE,\n            <T as PyClassImpl>::Layout::BASIC_SIZE,\n        )\n    }\n}\n\n#[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))]\ntype PyTypeBuilderCleanup = Box<dyn Fn(&PyTypeBuilder, *mut ffi::PyTypeObject)>;\n\nstruct PyTypeBuilder {\n    slots: Vec<ffi::PyType_Slot>,\n    method_defs: Vec<ffi::PyMethodDef>,\n    member_defs: Vec<ffi::PyMemberDef>,\n    getset_builders: HashMap<&'static CStr, GetSetDefBuilder>,\n    /// Used to patch the type objects for the things there's no\n    /// PyType_FromSpec API for... there's no reason this should work,\n    /// except for that it does and we have tests.\n    #[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))]\n    cleanup: Vec<PyTypeBuilderCleanup>,\n    tp_base: *mut ffi::PyTypeObject,\n    tp_dealloc: ffi::destructor,\n    tp_dealloc_with_gc: ffi::destructor,\n    is_mapping: bool,\n    is_sequence: bool,\n    is_immutable_type: bool,\n    has_new: bool,\n    has_dealloc: bool,\n    has_getitem: bool,\n    has_setitem: bool,\n    has_traverse: bool,\n    has_clear: bool,\n    dict_offset: Option<PyObjectOffset>,\n    class_flags: c_ulong,\n    // Before Python 3.9, need to patch in buffer methods manually (they don't work in slots)\n    #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))]\n    buffer_procs: ffi::PyBufferProcs,\n}\n\nimpl PyTypeBuilder {\n    /// # Safety\n    /// The given pointer must be of the correct type for the given slot\n    unsafe fn push_slot<T>(&mut self, slot: c_int, pfunc: *mut T) {\n        match slot {\n            ffi::Py_tp_new => self.has_new = true,\n            ffi::Py_tp_dealloc => self.has_dealloc = true,\n            ffi::Py_mp_subscript => self.has_getitem = true,\n            ffi::Py_mp_ass_subscript => self.has_setitem = true,\n            ffi::Py_tp_traverse => {\n                self.has_traverse = true;\n                self.class_flags |= ffi::Py_TPFLAGS_HAVE_GC;\n            }\n            ffi::Py_tp_clear => self.has_clear = true,\n            #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))]\n            ffi::Py_bf_getbuffer => {\n                // Safety: slot.pfunc is a valid function pointer\n                self.buffer_procs.bf_getbuffer =\n                    Some(unsafe { std::mem::transmute::<*mut T, ffi::getbufferproc>(pfunc) });\n            }\n            #[cfg(all(not(Py_3_9), not(Py_LIMITED_API)))]\n            ffi::Py_bf_releasebuffer => {\n                // Safety: slot.pfunc is a valid function pointer\n                self.buffer_procs.bf_releasebuffer =\n                    Some(unsafe { std::mem::transmute::<*mut T, ffi::releasebufferproc>(pfunc) });\n            }\n            _ => {}\n        }\n\n        self.slots.push(ffi::PyType_Slot {\n            slot,\n            pfunc: pfunc as _,\n        });\n    }\n\n    /// # Safety\n    /// It is the caller's responsibility that `data` is of the correct type for the given slot.\n    unsafe fn push_raw_vec_slot<T>(&mut self, slot: c_int, mut data: Vec<T>) {\n        if !data.is_empty() {\n            // Python expects a zeroed entry to mark the end of the defs\n            unsafe {\n                data.push(std::mem::zeroed());\n                self.push_slot(slot, Box::into_raw(data.into_boxed_slice()) as *mut c_void);\n            }\n        }\n    }\n\n    fn pymethod_def(&mut self, def: &PyMethodDefType) {\n        match def {\n            PyMethodDefType::Getter(getter) => self\n                .getset_builders\n                .entry(getter.name)\n                .or_default()\n                .add_getter(getter),\n            PyMethodDefType::Setter(setter) => self\n                .getset_builders\n                .entry(setter.name)\n                .or_default()\n                .add_setter(setter),\n            PyMethodDefType::Deleter(deleter) => self\n                .getset_builders\n                .entry(deleter.name)\n                .or_default()\n                .add_deleter(deleter),\n            PyMethodDefType::Method(def) => self.method_defs.push(def.into_raw()),\n            // These class attributes are added after the type gets created by LazyStaticType\n            PyMethodDefType::ClassAttribute(_) => {}\n            PyMethodDefType::StructMember(def) => self.member_defs.push(*def),\n        }\n    }\n\n    fn finalize_methods_and_properties(&mut self) -> Vec<GetSetDefType> {\n        let method_defs: Vec<pyo3_ffi::PyMethodDef> = std::mem::take(&mut self.method_defs);\n        // Safety: Py_tp_methods expects a raw vec of PyMethodDef\n        unsafe { self.push_raw_vec_slot(ffi::Py_tp_methods, method_defs) };\n\n        let member_defs = std::mem::take(&mut self.member_defs);\n        // Safety: Py_tp_members expects a raw vec of PyMemberDef\n        unsafe { self.push_raw_vec_slot(ffi::Py_tp_members, member_defs) };\n\n        let mut getset_destructors = Vec::with_capacity(self.getset_builders.len());\n\n        #[allow(unused_mut, reason = \"not modified on PyPy\")]\n        let mut property_defs: Vec<_> = self\n            .getset_builders\n            .iter()\n            .map(|(name, builder)| {\n                let (def, destructor) = builder.as_get_set_def(name);\n                getset_destructors.push(destructor);\n                def\n            })\n            .collect();\n\n        // PyPy automatically adds __dict__ getter / setter.\n        #[cfg(not(PyPy))]\n        // Supported on unlimited API for all versions, and on 3.9+ for limited API\n        #[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\n        if let Some(dict_offset) = self.dict_offset {\n            let get_dict;\n            let closure;\n            // PyObject_GenericGetDict not in the limited API until Python 3.10.\n            #[cfg(any(not(Py_LIMITED_API), Py_3_10))]\n            {\n                let _ = dict_offset;\n                get_dict = ffi::PyObject_GenericGetDict;\n                closure = ptr::null_mut();\n            }\n\n            // ... so we write a basic implementation ourselves\n            #[cfg(not(any(not(Py_LIMITED_API), Py_3_10)))]\n            {\n                extern \"C\" fn get_dict_impl(\n                    object: *mut ffi::PyObject,\n                    closure: *mut c_void,\n                ) -> *mut ffi::PyObject {\n                    unsafe {\n                        trampoline(|_| {\n                            let dict_offset = closure as ffi::Py_ssize_t;\n                            // we don't support negative dict_offset here; PyO3 doesn't set it negative\n                            assert!(dict_offset > 0);\n                            let dict_ptr =\n                                object.byte_offset(dict_offset).cast::<*mut ffi::PyObject>();\n                            if (*dict_ptr).is_null() {\n                                std::ptr::write(dict_ptr, ffi::PyDict_New());\n                            }\n                            Ok(ffi::compat::Py_XNewRef(*dict_ptr))\n                        })\n                    }\n                }\n\n                get_dict = get_dict_impl;\n                let PyObjectOffset::Absolute(offset) = dict_offset;\n                closure = offset as _;\n            }\n\n            property_defs.push(ffi::PyGetSetDef {\n                name: c\"__dict__\".as_ptr(),\n                get: Some(get_dict),\n                set: Some(ffi::PyObject_GenericSetDict),\n                doc: ptr::null(),\n                closure,\n            });\n        }\n\n        // Safety: Py_tp_getset expects a raw vec of PyGetSetDef\n        unsafe { self.push_raw_vec_slot(ffi::Py_tp_getset, property_defs) };\n\n        // If mapping methods implemented, define sequence methods get implemented too.\n        // CPython does the same for Python `class` statements.\n\n        // NB we don't implement sq_length to avoid annoying CPython behaviour of automatically adding\n        // the length to negative indices.\n\n        // Don't add these methods for \"pure\" mappings.\n\n        if !self.is_mapping && self.has_getitem {\n            // Safety: This is the correct slot type for Py_sq_item\n            unsafe {\n                self.push_slot(\n                    ffi::Py_sq_item,\n                    get_sequence_item_from_mapping as *mut c_void,\n                )\n            }\n        }\n\n        if !self.is_mapping && self.has_setitem {\n            // Safety: This is the correct slot type for Py_sq_ass_item\n            unsafe {\n                self.push_slot(\n                    ffi::Py_sq_ass_item,\n                    assign_sequence_item_from_mapping as *mut c_void,\n                )\n            }\n        }\n\n        getset_destructors\n    }\n\n    fn set_is_basetype(mut self, is_basetype: bool) -> Self {\n        if is_basetype {\n            self.class_flags |= ffi::Py_TPFLAGS_BASETYPE;\n        }\n        self\n    }\n\n    /// # Safety\n    /// All slots in the PyClassItemsIter should be correct\n    unsafe fn class_items(mut self, iter: PyClassItemsIter) -> Self {\n        for items in iter {\n            for slot in items.slots {\n                unsafe { self.push_slot(slot.slot, slot.pfunc) };\n            }\n            for method in items.methods {\n                self.pymethod_def(method);\n            }\n        }\n        self\n    }\n\n    fn type_doc(mut self, type_doc: &'static CStr) -> Self {\n        let slice = type_doc.to_bytes();\n        if !slice.is_empty() {\n            unsafe { self.push_slot(ffi::Py_tp_doc, type_doc.as_ptr() as *mut c_char) }\n\n            #[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))]\n            {\n                // Until CPython 3.10, tp_doc was treated specially for\n                // heap-types, and it removed the text_signature value from it.\n                // We go in after the fact and replace tp_doc with something\n                // that _does_ include the text_signature value!\n                self.cleanup\n                    .push(Box::new(move |_self, type_object| unsafe {\n                        ffi::PyObject_Free((*type_object).tp_doc as _);\n                        let data = ffi::PyMem_Malloc(slice.len());\n                        data.copy_from(slice.as_ptr() as _, slice.len());\n                        (*type_object).tp_doc = data as _;\n                    }))\n            }\n        }\n        self\n    }\n\n    fn offsets(\n        mut self,\n        dict_offset: Option<PyObjectOffset>,\n        #[allow(unused_variables)] weaklist_offset: Option<PyObjectOffset>,\n    ) -> Self {\n        self.dict_offset = dict_offset;\n\n        #[cfg(Py_3_9)]\n        {\n            #[inline(always)]\n            fn offset_def(name: &'static CStr, offset: PyObjectOffset) -> ffi::PyMemberDef {\n                let (offset, flags) = match offset {\n                    PyObjectOffset::Absolute(offset) => (offset, ffi::Py_READONLY),\n                    #[cfg(Py_3_12)]\n                    PyObjectOffset::Relative(offset) => {\n                        (offset, ffi::Py_READONLY | ffi::Py_RELATIVE_OFFSET)\n                    }\n                };\n                ffi::PyMemberDef {\n                    name: name.as_ptr().cast(),\n                    type_code: ffi::Py_T_PYSSIZET,\n                    offset,\n                    flags,\n                    doc: std::ptr::null_mut(),\n                }\n            }\n\n            // __dict__ support\n            if let Some(dict_offset) = dict_offset {\n                self.member_defs\n                    .push(offset_def(c\"__dictoffset__\", dict_offset));\n            }\n\n            // weakref support\n            if let Some(weaklist_offset) = weaklist_offset {\n                self.member_defs\n                    .push(offset_def(c\"__weaklistoffset__\", weaklist_offset));\n            }\n        }\n\n        // Setting buffer protocols, tp_dictoffset and tp_weaklistoffset via slots doesn't work until\n        // Python 3.9, so on older versions we must manually fixup the type object.\n        #[cfg(all(not(Py_LIMITED_API), not(Py_3_9)))]\n        {\n            self.cleanup\n                .push(Box::new(move |builder, type_object| unsafe {\n                    (*(*type_object).tp_as_buffer).bf_getbuffer = builder.buffer_procs.bf_getbuffer;\n                    (*(*type_object).tp_as_buffer).bf_releasebuffer =\n                        builder.buffer_procs.bf_releasebuffer;\n\n                    match dict_offset {\n                        Some(PyObjectOffset::Absolute(offset)) => {\n                            (*type_object).tp_dictoffset = offset;\n                        }\n                        None => {}\n                    }\n                    match weaklist_offset {\n                        Some(PyObjectOffset::Absolute(offset)) => {\n                            (*type_object).tp_weaklistoffset = offset;\n                        }\n                        None => {}\n                    }\n                }));\n        }\n        self\n    }\n\n    fn build(\n        mut self,\n        py: Python<'_>,\n        name: &'static str,\n        module_name: Option<&'static str>,\n        basicsize: ffi::Py_ssize_t,\n    ) -> PyResult<PyClassTypeObject> {\n        // `c_ulong` and `c_uint` have the same size\n        // on some platforms (like windows)\n        #![allow(clippy::useless_conversion)]\n\n        let getset_defs = self.finalize_methods_and_properties();\n\n        unsafe { self.push_slot(ffi::Py_tp_base, self.tp_base) }\n\n        if !self.has_new {\n            #[cfg(not(Py_3_10))]\n            {\n                // Safety: This is the correct slot type for Py_tp_new\n                unsafe { self.push_slot(ffi::Py_tp_new, no_constructor_defined as *mut c_void) }\n            }\n            #[cfg(Py_3_10)]\n            {\n                self.class_flags |= ffi::Py_TPFLAGS_DISALLOW_INSTANTIATION;\n            }\n        }\n\n        let base_is_gc = unsafe { ffi::PyType_IS_GC(self.tp_base) == 1 };\n        let tp_dealloc = if self.has_traverse || base_is_gc {\n            self.tp_dealloc_with_gc\n        } else {\n            self.tp_dealloc\n        };\n        unsafe { self.push_slot(ffi::Py_tp_dealloc, tp_dealloc as *mut c_void) }\n\n        if self.has_clear && !self.has_traverse {\n            return Err(PyTypeError::new_err(format!(\n                \"`#[pyclass]` {name} implements __clear__ without __traverse__\"\n            )));\n        }\n\n        // If this type is a GC type, and the base also is, we may need to add\n        // `tp_traverse` / `tp_clear` implementations to call the base, if this type didn't\n        // define `__traverse__` or `__clear__`.\n        //\n        // This is because when Py_TPFLAGS_HAVE_GC is set, then `tp_traverse` and\n        // `tp_clear` are not inherited.\n        if ((self.class_flags & ffi::Py_TPFLAGS_HAVE_GC) != 0) && base_is_gc {\n            // If this assertion breaks, need to consider doing the same for __traverse__.\n            assert!(self.has_traverse); // Py_TPFLAGS_HAVE_GC is set when a `__traverse__` method is found\n\n            if !self.has_clear {\n                // Safety: This is the correct slot type for Py_tp_clear\n                unsafe { self.push_slot(ffi::Py_tp_clear, call_super_clear as *mut c_void) }\n            }\n        }\n\n        // For sequences, implement sq_length instead of mp_length\n        if self.is_sequence {\n            for slot in &mut self.slots {\n                if slot.slot == ffi::Py_mp_length {\n                    slot.slot = ffi::Py_sq_length;\n                }\n            }\n        }\n\n        // Add empty sentinel at the end\n        // Safety: python expects this empty slot\n        unsafe { self.push_slot(0, ptr::null_mut::<c_void>()) }\n\n        let class_name = py_class_qualified_name(module_name, name)?;\n        let mut spec = ffi::PyType_Spec {\n            name: class_name.as_ptr() as _,\n            basicsize: basicsize as c_int,\n            itemsize: 0,\n\n            flags: (ffi::Py_TPFLAGS_DEFAULT | self.class_flags)\n                .try_into()\n                .unwrap(),\n            slots: self.slots.as_mut_ptr(),\n        };\n\n        // SAFETY: We've correctly setup the PyType_Spec at this point\n        // The FFI call is known to return a new type object or null on error\n        let type_object = unsafe {\n            ffi::PyType_FromSpec(&mut spec)\n                .assume_owned_or_err(py)?\n                .cast_into_unchecked::<PyType>()\n        };\n\n        #[cfg(not(Py_3_11))]\n        bpo_45315_workaround(py, class_name);\n\n        #[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))]\n        for cleanup in std::mem::take(&mut self.cleanup) {\n            cleanup(&self, type_object.as_type_ptr());\n        }\n\n        Ok(PyClassTypeObject {\n            type_object: type_object.unbind(),\n            is_immutable_type: self.is_immutable_type,\n            getset_defs,\n        })\n    }\n}\n\nfn py_class_qualified_name(module_name: Option<&str>, class_name: &str) -> PyResult<CString> {\n    Ok(CString::new(format!(\n        \"{}.{}\",\n        module_name.unwrap_or(\"builtins\"),\n        class_name\n    ))?)\n}\n\n/// Workaround for Python issue 45315; no longer necessary in Python 3.11\n#[inline]\n#[cfg(not(Py_3_11))]\nfn bpo_45315_workaround(py: Python<'_>, class_name: CString) {\n    #[cfg(Py_LIMITED_API)]\n    {\n        // Must check version at runtime for abi3 wheels - they could run against a higher version\n        // than the build config suggests.\n        use crate::sync::PyOnceLock;\n        static IS_PYTHON_3_11: PyOnceLock<bool> = PyOnceLock::new();\n\n        if *IS_PYTHON_3_11.get_or_init(py, || py.version_info() >= (3, 11)) {\n            // No fix needed - the wheel is running on a sufficiently new interpreter.\n            return;\n        }\n    }\n    #[cfg(not(Py_LIMITED_API))]\n    {\n        // suppress unused variable warning\n        let _ = py;\n    }\n\n    std::mem::forget(class_name);\n}\n\n/// Default new implementation\n#[cfg(not(Py_3_10))]\nunsafe extern \"C\" fn no_constructor_defined(\n    subtype: *mut ffi::PyTypeObject,\n    _args: *mut ffi::PyObject,\n    _kwds: *mut ffi::PyObject,\n) -> *mut ffi::PyObject {\n    unsafe {\n        trampoline(|py| {\n            let tpobj = PyType::from_borrowed_type_ptr(py, subtype);\n            // unlike `fully_qualified_name`, this always include the module\n            let module = tpobj\n                .module()\n                .map_or_else(|_| \"<unknown>\".into(), |s| s.to_string());\n            let qualname = tpobj.qualname();\n            let qualname = qualname.map_or_else(|_| \"<unknown>\".into(), |s| s.to_string());\n            Err(crate::exceptions::PyTypeError::new_err(format!(\n                \"cannot create '{module}.{qualname}' instances\"\n            )))\n        })\n    }\n}\n\nunsafe extern \"C\" fn call_super_clear(slf: *mut ffi::PyObject) -> c_int {\n    unsafe { _call_clear(slf, |_, _| Ok(()), call_super_clear) }\n}\n\n#[derive(Default)]\nstruct GetSetDefBuilder {\n    doc: Option<&'static CStr>,\n    getter: Option<Getter>,\n    setter: Option<Setter>,\n    deleter: Option<Deleter>,\n}\n\nimpl GetSetDefBuilder {\n    fn add_getter(&mut self, getter: &PyGetterDef) {\n        // TODO: be smarter about merging getter and setter docs\n        if self.doc.is_none() {\n            self.doc = getter.doc;\n        }\n        // TODO: return an error if getter already defined?\n        self.getter = Some(getter.meth)\n    }\n\n    fn add_setter(&mut self, setter: &PySetterDef) {\n        // TODO: be smarter about merging getter and setter docs\n        if self.doc.is_none() {\n            self.doc = setter.doc;\n        }\n        // TODO: return an error if setter already defined?\n        self.setter = Some(setter.meth)\n    }\n\n    fn add_deleter(&mut self, deleter: &PyDeleterDef) {\n        // TODO: be smarter about merging getter, setter and deleter docs\n        if self.doc.is_none() {\n            self.doc = deleter.doc;\n        }\n        // TODO: return an error if deleter already defined?\n        self.deleter = Some(deleter.meth)\n    }\n\n    fn as_get_set_def(&self, name: &'static CStr) -> (ffi::PyGetSetDef, GetSetDefType) {\n        let getset_type = match (self.getter, self.setter, self.deleter) {\n            (None, None, None) => {\n                unreachable!(\"GetSetDefBuilder expected to always have either getter or setter\")\n            }\n            (Some(getter), None, None) => GetSetDefType::Getter(getter),\n            (None, Some(setter), None) => GetSetDefType::Setter(setter),\n            (getter, setter, deleter) => {\n                GetSetDefType::Combination(Box::new(GetSetDeleteCombination {\n                    getter,\n                    setter,\n                    deleter,\n                }))\n            }\n        };\n\n        let getset_def = getset_type.create_py_get_set_def(name, self.doc);\n        (getset_def, getset_type)\n    }\n}\n\n/// Possible forms of property - either a getter, setter, or both\nenum GetSetDefType {\n    Getter(Getter),\n    Setter(Setter),\n    // The box is here so that the `GetSetDeleteCombination` has a stable\n    // memory address even if the `GetSetDeleteCombination` enum is moved\n    Combination(Box<GetSetDeleteCombination>),\n}\n\npub(crate) struct GetSetDeleteCombination {\n    getter: Option<Getter>,\n    setter: Option<Setter>,\n    deleter: Option<Deleter>,\n}\n\nimpl GetSetDefType {\n    /// Fills a PyGetSetDef structure\n    /// It is only valid for as long as this GetSetDefType remains alive,\n    /// as well as name and doc members\n    pub(crate) fn create_py_get_set_def(\n        &self,\n        name: &CStr,\n        doc: Option<&CStr>,\n    ) -> ffi::PyGetSetDef {\n        let (get, set, closure): (Option<ffi::getter>, Option<ffi::setter>, *mut c_void) =\n            match self {\n                &Self::Getter(closure) => {\n                    unsafe extern \"C\" fn getter(\n                        slf: *mut ffi::PyObject,\n                        closure: *mut c_void,\n                    ) -> *mut ffi::PyObject {\n                        let slf = unsafe { NonNull::new_unchecked(slf) };\n                        // Safety: PyO3 sets the closure when constructing the ffi getter so this cast should always be valid\n                        let getter: Getter = unsafe { std::mem::transmute(closure) };\n                        unsafe { trampoline(|py| getter(py, slf)) }\n                    }\n                    (Some(getter), None, closure as Getter as _)\n                }\n                &Self::Setter(closure) => {\n                    unsafe extern \"C\" fn setter(\n                        slf: *mut ffi::PyObject,\n                        value: *mut ffi::PyObject,\n                        closure: *mut c_void,\n                    ) -> c_int {\n                        let slf = unsafe { NonNull::new_unchecked(slf) };\n                        // Safety: PyO3 sets the closure when constructing the ffi setter so this cast should always be valid\n                        let setter: Setter = unsafe { std::mem::transmute(closure) };\n                        unsafe {\n                            trampoline(|py| {\n                                if let Some(value) = NonNull::new(value) {\n                                    setter(py, slf, value)\n                                } else {\n                                    Err(PyAttributeError::new_err(\"property has no deleter\"))\n                                }\n                            })\n                        }\n                    }\n                    (None, Some(setter), closure as Setter as _)\n                }\n                Self::Combination(closure) => {\n                    unsafe extern \"C\" fn getset_getter(\n                        slf: *mut ffi::PyObject,\n                        closure: *mut c_void,\n                    ) -> *mut ffi::PyObject {\n                        let slf = unsafe { NonNull::new_unchecked(slf) };\n                        let getset: &GetSetDeleteCombination = unsafe { &*closure.cast() };\n                        // we only call this method if getter is set\n                        unsafe { trampoline(|py| getset.getter.unwrap_unchecked()(py, slf)) }\n                    }\n\n                    unsafe extern \"C\" fn getset_setter(\n                        slf: *mut ffi::PyObject,\n                        value: *mut ffi::PyObject,\n                        closure: *mut c_void,\n                    ) -> c_int {\n                        let slf = unsafe { NonNull::new_unchecked(slf) };\n                        let getset: &GetSetDeleteCombination = unsafe { &*closure.cast() };\n                        unsafe {\n                            trampoline(|py| {\n                                if let Some(value) = NonNull::new(value) {\n                                    getset.setter.ok_or_else(|| {\n                                        PyAttributeError::new_err(\"property has no setter\")\n                                    })?(py, slf, value)\n                                } else {\n                                    getset.deleter.ok_or_else(|| {\n                                        PyAttributeError::new_err(\"property has no deleter\")\n                                    })?(py, slf)\n                                }\n                            })\n                        }\n                    }\n                    (\n                        closure.getter.is_some().then_some(getset_getter),\n                        Some(getset_setter),\n                        NonNull::<GetSetDeleteCombination>::from(closure.as_ref())\n                            .cast()\n                            .as_ptr(),\n                    )\n                }\n            };\n        ffi::PyGetSetDef {\n            name: name.as_ptr(),\n            doc: doc.map_or(ptr::null(), CStr::as_ptr),\n            get,\n            set,\n            closure,\n        }\n    }\n}\n"
  },
  {
    "path": "src/pyclass/gc.rs",
    "content": "use std::{\n    marker::PhantomData,\n    num::NonZero,\n    os::raw::{c_int, c_void},\n};\n\nuse crate::{ffi, Py};\n\n/// Error returned by a `__traverse__` visitor implementation.\n#[repr(transparent)]\npub struct PyTraverseError(NonZero<c_int>);\n\nimpl PyTraverseError {\n    /// Returns the error code.\n    pub(crate) fn into_inner(self) -> c_int {\n        self.0.into()\n    }\n}\n\n/// Object visitor for GC.\n#[derive(Clone)]\npub struct PyVisit<'a> {\n    pub(crate) visit: ffi::visitproc,\n    pub(crate) arg: *mut c_void,\n    /// Prevents the `PyVisit` from outliving the `__traverse__` call.\n    pub(crate) _guard: PhantomData<&'a ()>,\n}\n\nimpl PyVisit<'_> {\n    /// Visit `obj`.\n    ///\n    /// Note: `obj` accepts a variety of types, including\n    /// - `&Py<T>`\n    /// - `&Option<Py<T>>`\n    /// - `Option<&Py<T>>`\n    pub fn call<'a, T, U: 'a>(&self, obj: T) -> Result<(), PyTraverseError>\n    where\n        T: Into<Option<&'a Py<U>>>,\n    {\n        let ptr = obj.into().map_or_else(std::ptr::null_mut, Py::as_ptr);\n        if !ptr.is_null() {\n            match NonZero::new(unsafe { (self.visit)(ptr, self.arg) }) {\n                None => Ok(()),\n                Some(r) => Err(PyTraverseError(r)),\n            }\n        } else {\n            Ok(())\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::PyVisit;\n    use static_assertions::assert_not_impl_any;\n\n    #[test]\n    fn py_visit_not_send_sync() {\n        assert_not_impl_any!(PyVisit<'_>: Send, Sync);\n    }\n}\n"
  },
  {
    "path": "src/pyclass/guard.rs",
    "content": "use crate::impl_::pycell::PyClassObjectBaseLayout as _;\r\nuse crate::impl_::pyclass::PyClassImpl;\r\n#[cfg(feature = \"experimental-inspect\")]\r\nuse crate::inspect::PyStaticExpr;\r\nuse crate::pycell::impl_::PyClassObjectLayout as _;\r\nuse crate::pycell::PyBorrowMutError;\r\nuse crate::pycell::{impl_::PyClassBorrowChecker, PyBorrowError};\r\nuse crate::pyclass::boolean_struct::False;\r\nuse crate::{ffi, Borrowed, CastError, FromPyObject, IntoPyObject, Py, PyClass, PyErr};\r\nuse std::convert::Infallible;\r\nuse std::fmt;\r\nuse std::marker::PhantomData;\r\nuse std::ops::{Deref, DerefMut};\r\nuse std::ptr::NonNull;\r\n\r\n/// A wrapper type for an immutably borrowed value from a `PyClass`.\r\n///\r\n/// Rust has strict aliasing rules - you can either have any number of immutable\r\n/// (shared) references or one mutable reference. Python's ownership model is\r\n/// the complete opposite of that - any Python object can be referenced any\r\n/// number of times, and mutation is allowed from any reference.\r\n///\r\n/// PyO3 deals with these differences by employing the [Interior Mutability]\r\n/// pattern. This requires that PyO3 enforces the borrowing rules and it has two\r\n/// mechanisms for doing so:\r\n/// - Statically it can enforce thread-safe access with the\r\n///   [`Python<'py>`](crate::Python) token. All Rust code holding that token, or\r\n///   anything derived from it, can assume that they have safe access to the\r\n///   Python interpreter's state. For this reason all the native Python objects\r\n///   can be mutated through shared references.\r\n/// - However, methods and functions in Rust usually *do* need `&mut`\r\n///   references. While PyO3 can use the [`Python<'py>`](crate::Python) token to\r\n///   guarantee thread-safe access to them, it cannot statically guarantee\r\n///   uniqueness of `&mut` references. As such those references have to be\r\n///   tracked dynamically at runtime, using [`PyClassGuard`] and\r\n///   [`PyClassGuardMut`] defined in this module. This works similar to std's\r\n///   [`RefCell`](std::cell::RefCell) type. Especially when building for\r\n///   free-threaded Python it gets harder to track which thread borrows which\r\n///   object at any time. This can lead to method calls failing with\r\n///   [`PyBorrowError`]. In these cases consider using `frozen` classes together\r\n///   with Rust interior mutability primitives like [`Mutex`](std::sync::Mutex)\r\n///   instead of using [`PyClassGuardMut`] to get mutable access.\r\n///\r\n/// # Examples\r\n///\r\n/// You can use [`PyClassGuard`] as an alternative to a `&self` receiver when\r\n/// - you need to access the pointer of the `PyClass`, or\r\n/// - you want to get a super class.\r\n/// ```\r\n/// # use pyo3::prelude::*;\r\n/// # use pyo3::PyClassGuard;\r\n/// #[pyclass(subclass)]\r\n/// struct Parent {\r\n///     basename: &'static str,\r\n/// }\r\n///\r\n/// #[pyclass(extends=Parent)]\r\n/// struct Child {\r\n///     name: &'static str,\r\n///  }\r\n///\r\n/// #[pymethods]\r\n/// impl Child {\r\n///     #[new]\r\n///     fn new() -> (Self, Parent) {\r\n///         (Child { name: \"Caterpillar\" }, Parent { basename: \"Butterfly\" })\r\n///     }\r\n///\r\n///     fn format(slf: PyClassGuard<'_, Self>) -> String {\r\n///         // We can get &Self::BaseType by as_super\r\n///         let basename = slf.as_super().basename;\r\n///         format!(\"{}(base: {})\", slf.name, basename)\r\n///     }\r\n/// }\r\n/// # Python::attach(|py| {\r\n/// #     let sub = Py::new(py, Child::new()).unwrap();\r\n/// #     pyo3::py_run!(py, sub, \"assert sub.format() == 'Caterpillar(base: Butterfly)', sub.format()\");\r\n/// # });\r\n/// ```\r\n///\r\n/// See also [`PyClassGuardMut`] and the [guide] for more information.\r\n///\r\n/// [Interior Mutability]:\r\n///     https://doc.rust-lang.org/book/ch15-05-interior-mutability.html\r\n///     \"RefCell<T> and the Interior Mutability Pattern - The Rust Programming\r\n///     Language\"\r\n/// [guide]: https://pyo3.rs/latest/class.html#bound-and-interior-mutability\r\n///     \"Bound and interior mutability\"\r\n#[repr(transparent)]\r\npub struct PyClassGuard<'a, T: PyClass> {\r\n    ptr: NonNull<ffi::PyObject>,\r\n    marker: PhantomData<&'a Py<T>>,\r\n}\r\n\r\nimpl<'a, T: PyClass> PyClassGuard<'a, T> {\r\n    pub(crate) fn try_borrow(obj: &'a Py<T>) -> Result<Self, PyBorrowError> {\r\n        Self::try_from_class_object(obj.get_class_object())\r\n    }\r\n\r\n    pub(crate) fn try_borrow_from_borrowed(\r\n        obj: Borrowed<'a, '_, T>,\r\n    ) -> Result<Self, PyBorrowError> {\r\n        Self::try_from_class_object(obj.get_class_object())\r\n    }\r\n\r\n    fn try_from_class_object(obj: &'a <T as PyClassImpl>::Layout) -> Result<Self, PyBorrowError> {\r\n        obj.ensure_threadsafe();\r\n        obj.borrow_checker().try_borrow().map(|_| Self {\r\n            ptr: NonNull::from(obj).cast(),\r\n            marker: PhantomData,\r\n        })\r\n    }\r\n\r\n    pub(crate) fn as_class_object(&self) -> &'a <T as PyClassImpl>::Layout {\r\n        // SAFETY: `ptr` by construction points to a `PyClassObject<T>` and is\r\n        // valid for at least 'a\r\n        unsafe { self.ptr.cast().as_ref() }\r\n    }\r\n\r\n    /// Consumes the [`PyClassGuard`] and returns a [`PyClassGuardMap`] for a component of the\r\n    /// borrowed data\r\n    ///\r\n    /// # Examples\r\n    ///\r\n    /// ```\r\n    /// # use pyo3::prelude::*;\r\n    /// # use pyo3::PyClassGuard;\r\n    ///\r\n    /// #[pyclass]\r\n    /// pub struct MyClass {\r\n    ///     msg: String,\r\n    /// }\r\n    ///\r\n    /// # Python::attach(|py| {\r\n    /// let obj = Bound::new(py, MyClass { msg: String::from(\"hello\") })?;\r\n    /// let msg = obj.extract::<PyClassGuard<'_, MyClass>>()?.map(|c| &c.msg);\r\n    /// assert_eq!(&*msg, \"hello\");\r\n    /// # Ok::<_, PyErr>(())\r\n    /// # }).unwrap();\r\n    /// ```\r\n    pub fn map<F, U: ?Sized>(self, f: F) -> PyClassGuardMap<'a, U, false>\r\n    where\r\n        F: FnOnce(&T) -> &U,\r\n    {\r\n        let slf = std::mem::ManuallyDrop::new(self); // the borrow is released when dropping the `PyClassGuardMap`\r\n        PyClassGuardMap {\r\n            ptr: NonNull::from(f(&slf)),\r\n            checker: slf.as_class_object().borrow_checker(),\r\n        }\r\n    }\r\n}\r\n\r\nimpl<'a, T> PyClassGuard<'a, T>\r\nwhere\r\n    T: PyClass,\r\n    T::BaseType: PyClass,\r\n{\r\n    /// Borrows a shared reference to `PyClassGuard<T::BaseType>`.\r\n    ///\r\n    /// With the help of this method, you can access attributes and call methods\r\n    /// on the superclass without consuming the `PyClassGuard<T>`. This method\r\n    /// can also be chained to access the super-superclass (and so on).\r\n    ///\r\n    /// # Examples\r\n    /// ```\r\n    /// # use pyo3::prelude::*;\r\n    /// # use pyo3::PyClassGuard;\r\n    /// #[pyclass(subclass)]\r\n    /// struct Base {\r\n    ///     base_name: &'static str,\r\n    /// }\r\n    /// #[pymethods]\r\n    /// impl Base {\r\n    ///     fn base_name_len(&self) -> usize {\r\n    ///         self.base_name.len()\r\n    ///     }\r\n    /// }\r\n    ///\r\n    /// #[pyclass(extends=Base)]\r\n    /// struct Sub {\r\n    ///     sub_name: &'static str,\r\n    /// }\r\n    ///\r\n    /// #[pymethods]\r\n    /// impl Sub {\r\n    ///     #[new]\r\n    ///     fn new() -> (Self, Base) {\r\n    ///         (Self { sub_name: \"sub_name\" }, Base { base_name: \"base_name\" })\r\n    ///     }\r\n    ///     fn sub_name_len(&self) -> usize {\r\n    ///         self.sub_name.len()\r\n    ///     }\r\n    ///     fn format_name_lengths(slf: PyClassGuard<'_, Self>) -> String {\r\n    ///         format!(\"{} {}\", slf.as_super().base_name_len(), slf.sub_name_len())\r\n    ///     }\r\n    /// }\r\n    /// # Python::attach(|py| {\r\n    /// #     let sub = Py::new(py, Sub::new()).unwrap();\r\n    /// #     pyo3::py_run!(py, sub, \"assert sub.format_name_lengths() == '9 8'\")\r\n    /// # });\r\n    /// ```\r\n    pub fn as_super(&self) -> &PyClassGuard<'a, T::BaseType> {\r\n        // SAFETY: `PyClassGuard<T>` and `PyClassGuard<U>` have the same layout\r\n        unsafe { NonNull::from(self).cast().as_ref() }\r\n    }\r\n\r\n    /// Gets a `PyClassGuard<T::BaseType>`.\r\n    ///\r\n    /// With the help of this method, you can get hold of instances of the\r\n    /// super-superclass when needed.\r\n    ///\r\n    /// # Examples\r\n    /// ```\r\n    /// # use pyo3::prelude::*;\r\n    /// # use pyo3::PyClassGuard;\r\n    /// #[pyclass(subclass)]\r\n    /// struct Base1 {\r\n    ///     name1: &'static str,\r\n    /// }\r\n    ///\r\n    /// #[pyclass(extends=Base1, subclass)]\r\n    /// struct Base2 {\r\n    ///     name2: &'static str,\r\n    /// }\r\n    ///\r\n    /// #[pyclass(extends=Base2)]\r\n    /// struct Sub {\r\n    ///     name3: &'static str,\r\n    /// }\r\n    ///\r\n    /// #[pymethods]\r\n    /// impl Sub {\r\n    ///     #[new]\r\n    ///     fn new() -> PyClassInitializer<Self> {\r\n    ///         PyClassInitializer::from(Base1 { name1: \"base1\" })\r\n    ///             .add_subclass(Base2 { name2: \"base2\" })\r\n    ///             .add_subclass(Self { name3: \"sub\" })\r\n    ///     }\r\n    ///     fn name(slf: PyClassGuard<'_, Self>) -> String {\r\n    ///         let subname = slf.name3;\r\n    ///         let super_ = slf.into_super();\r\n    ///         format!(\"{} {} {}\", super_.as_super().name1, super_.name2, subname)\r\n    ///     }\r\n    /// }\r\n    /// # Python::attach(|py| {\r\n    /// #     let sub = Py::new(py, Sub::new()).unwrap();\r\n    /// #     pyo3::py_run!(py, sub, \"assert sub.name() == 'base1 base2 sub'\")\r\n    /// # });\r\n    /// ```\r\n    pub fn into_super(self) -> PyClassGuard<'a, T::BaseType> {\r\n        let t_not_frozen = !<T::Frozen as crate::pyclass::boolean_struct::private::Boolean>::VALUE;\r\n        let u_frozen =\r\n            <<T::BaseType as PyClass>::Frozen as crate::pyclass::boolean_struct::private::Boolean>::VALUE;\r\n        if t_not_frozen && u_frozen {\r\n            // If `T` is a mutable subclass of a frozen `U` base, then it is possible that we need\r\n            // to release the borrow count now. (e.g. `U` may have a noop borrow checker so dropping\r\n            // the `PyRef<U>` later would noop and leak the borrow we currently hold.)\r\n            //\r\n            // However it's nontrivial, if `U` is frozen but itself has a mutable base class `V`,\r\n            // then the borrow checker of both `T` and `U` is the shared borrow checker of `V`.\r\n            //\r\n            // But it's really hard to prove that in the type system, the soundest thing we can do\r\n            // is just add a borrow to `U` now and then release the borrow of `T`.\r\n\r\n            self.as_super()\r\n                .as_class_object()\r\n                .borrow_checker()\r\n                .try_borrow()\r\n                .expect(\"this object is already borrowed\");\r\n\r\n            self.as_class_object().borrow_checker().release_borrow()\r\n        };\r\n        PyClassGuard {\r\n            ptr: std::mem::ManuallyDrop::new(self).ptr,\r\n            marker: PhantomData,\r\n        }\r\n    }\r\n}\r\n\r\nimpl<T: PyClass> Deref for PyClassGuard<'_, T> {\r\n    type Target = T;\r\n\r\n    #[inline]\r\n    fn deref(&self) -> &T {\r\n        // SAFETY: `PyClassObject<T>` contains a valid `T`, by construction no\r\n        // mutable alias is enforced\r\n        unsafe { &*self.as_class_object().get_ptr().cast_const() }\r\n    }\r\n}\r\n\r\nimpl<'a, 'py, T: PyClass> FromPyObject<'a, 'py> for PyClassGuard<'a, T> {\r\n    type Error = PyClassGuardError<'a, 'py>;\r\n\r\n    #[cfg(feature = \"experimental-inspect\")]\r\n    const INPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\r\n\r\n    fn extract(obj: Borrowed<'a, 'py, crate::PyAny>) -> Result<Self, Self::Error> {\r\n        Self::try_from_class_object(\r\n            obj.cast::<T>()\r\n                .map_err(|e| PyClassGuardError(Some(e)))?\r\n                .get_class_object(),\r\n        )\r\n        .map_err(|_| PyClassGuardError(None))\r\n    }\r\n}\r\n\r\nimpl<'a, 'py, T: PyClass> IntoPyObject<'py> for PyClassGuard<'a, T> {\r\n    type Target = T;\r\n    type Output = Borrowed<'a, 'py, T>;\r\n    type Error = Infallible;\r\n\r\n    #[cfg(feature = \"experimental-inspect\")]\r\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\r\n\r\n    #[inline]\r\n    fn into_pyobject(self, py: crate::Python<'py>) -> Result<Self::Output, Self::Error> {\r\n        (&self).into_pyobject(py)\r\n    }\r\n}\r\n\r\nimpl<'a, 'py, T: PyClass> IntoPyObject<'py> for &PyClassGuard<'a, T> {\r\n    type Target = T;\r\n    type Output = Borrowed<'a, 'py, T>;\r\n    type Error = Infallible;\r\n\r\n    #[cfg(feature = \"experimental-inspect\")]\r\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\r\n\r\n    #[inline]\r\n    fn into_pyobject(self, py: crate::Python<'py>) -> Result<Self::Output, Self::Error> {\r\n        // SAFETY: `ptr` is guaranteed to be valid for 'a and points to an\r\n        // object of type T\r\n        unsafe { Ok(Borrowed::from_non_null(py, self.ptr).cast_unchecked()) }\r\n    }\r\n}\r\n\r\nimpl<T: PyClass> Drop for PyClassGuard<'_, T> {\r\n    /// Releases the shared borrow\r\n    fn drop(&mut self) {\r\n        self.as_class_object().borrow_checker().release_borrow()\r\n    }\r\n}\r\n\r\n// SAFETY: `PyClassGuard` only provides access to the inner `T` (and no other\r\n// Python APIs) which does not require a Python thread state\r\n#[cfg(feature = \"nightly\")]\r\nunsafe impl<T: PyClass> crate::marker::Ungil for PyClassGuard<'_, T> {}\r\n// SAFETY: we provide access to\r\n// - `&T`, which requires `T: Sync` to be Send and `T: Sync` to be Sync\r\nunsafe impl<T: PyClass + Sync> Send for PyClassGuard<'_, T> {}\r\nunsafe impl<T: PyClass + Sync> Sync for PyClassGuard<'_, T> {}\r\n\r\n/// Custom error type for extracting a [PyClassGuard]\r\npub struct PyClassGuardError<'a, 'py>(pub(crate) Option<CastError<'a, 'py>>);\r\n\r\nimpl fmt::Debug for PyClassGuardError<'_, '_> {\r\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\r\n        if let Some(e) = &self.0 {\r\n            write!(f, \"{e:?}\")\r\n        } else {\r\n            write!(f, \"{:?}\", PyBorrowError::new())\r\n        }\r\n    }\r\n}\r\n\r\nimpl fmt::Display for PyClassGuardError<'_, '_> {\r\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\r\n        if let Some(e) = &self.0 {\r\n            write!(f, \"{e}\")\r\n        } else {\r\n            write!(f, \"{}\", PyBorrowError::new())\r\n        }\r\n    }\r\n}\r\n\r\nimpl From<PyClassGuardError<'_, '_>> for PyErr {\r\n    fn from(value: PyClassGuardError<'_, '_>) -> Self {\r\n        if let Some(e) = value.0 {\r\n            e.into()\r\n        } else {\r\n            PyBorrowError::new().into()\r\n        }\r\n    }\r\n}\r\n\r\n/// A wrapper type for a mutably borrowed value from a `PyClass`\r\n///\r\n/// # When *not* to use [`PyClassGuardMut`]\r\n///\r\n/// Usually you can use `&mut` references as method and function receivers and\r\n/// arguments, and you won't need to use [`PyClassGuardMut`] directly:\r\n///\r\n/// ```rust,no_run\r\n/// use pyo3::prelude::*;\r\n///\r\n/// #[pyclass]\r\n/// struct Number {\r\n///     inner: u32,\r\n/// }\r\n///\r\n/// #[pymethods]\r\n/// impl Number {\r\n///     fn increment(&mut self) {\r\n///         self.inner += 1;\r\n///     }\r\n/// }\r\n/// ```\r\n///\r\n/// The [`#[pymethods]`](crate::pymethods) proc macro will generate this wrapper\r\n/// function (and more), using [`PyClassGuardMut`] under the hood:\r\n///\r\n/// ```rust,no_run\r\n/// # use pyo3::prelude::*;\r\n/// # #[pyclass]\r\n/// # struct Number {\r\n/// #    inner: u32,\r\n/// # }\r\n/// #\r\n/// # #[pymethods]\r\n/// # impl Number {\r\n/// #    fn increment(&mut self) {\r\n/// #        self.inner += 1;\r\n/// #    }\r\n/// # }\r\n/// #\r\n/// // The function which is exported to Python looks roughly like the following\r\n/// unsafe extern \"C\" fn __pymethod_increment__(\r\n///     _slf: *mut ::pyo3::ffi::PyObject,\r\n///     _args: *mut ::pyo3::ffi::PyObject,\r\n/// ) -> *mut ::pyo3::ffi::PyObject {\r\n///     unsafe fn inner<'py>(\r\n///         py: ::pyo3::Python<'py>,\r\n///         _slf: *mut ::pyo3::ffi::PyObject,\r\n///     ) -> ::pyo3::PyResult<*mut ::pyo3::ffi::PyObject> {\r\n///         let function = Number::increment;\r\n/// #       #[allow(clippy::let_unit_value)]\r\n///         let mut holder_0 = ::pyo3::impl_::extract_argument::FunctionArgumentHolder::INIT;\r\n///         let result = {\r\n///             let ret = function(::pyo3::impl_::extract_argument::extract_pyclass_ref_mut::<Number>(\r\n///                 unsafe { ::pyo3::impl_::extract_argument::cast_function_argument(py, _slf) },\r\n///                 &mut holder_0,\r\n///             )?);\r\n///             {\r\n///                 let result = {\r\n///                     let obj = ret;\r\n/// #                   #[allow(clippy::useless_conversion)]\r\n///                     ::pyo3::impl_::wrap::converter(&obj)\r\n///                         .wrap(obj)\r\n///                         .map_err(::core::convert::Into::<::pyo3::PyErr>::into)\r\n///                 };\r\n///                 ::pyo3::impl_::wrap::converter(&result).map_into_ptr(py, result)\r\n///             }\r\n///         };\r\n///         result\r\n///     }\r\n///\r\n///     unsafe {\r\n///         ::pyo3::impl_::trampoline::get_trampoline_function!(noargs, inner)(\r\n///             _slf,\r\n///             _args,\r\n///         )\r\n///     }\r\n/// }\r\n/// ```\r\n///\r\n/// # When to use [`PyClassGuardMut`]\r\n/// ## Using PyClasses from Rust\r\n///\r\n/// However, we *do* need [`PyClassGuardMut`] if we want to call its methods\r\n/// from Rust:\r\n/// ```rust\r\n/// # use pyo3::prelude::*;\r\n/// # use pyo3::{PyClassGuard, PyClassGuardMut};\r\n/// #\r\n/// # #[pyclass]\r\n/// # struct Number {\r\n/// #     inner: u32,\r\n/// # }\r\n/// #\r\n/// # #[pymethods]\r\n/// # impl Number {\r\n/// #     fn increment(&mut self) {\r\n/// #         self.inner += 1;\r\n/// #     }\r\n/// # }\r\n/// # fn main() -> PyResult<()> {\r\n/// Python::attach(|py| {\r\n///     let n = Py::new(py, Number { inner: 0 })?;\r\n///\r\n///     // We borrow the guard and then dereference\r\n///     // it to get a mutable reference to Number\r\n///     let mut guard: PyClassGuardMut<'_, Number> = n.extract(py)?;\r\n///     let n_mutable: &mut Number = &mut *guard;\r\n///\r\n///     n_mutable.increment();\r\n///\r\n///     // To avoid panics we must dispose of the\r\n///     // `PyClassGuardMut` before borrowing again.\r\n///     drop(guard);\r\n///\r\n///     let n_immutable: &Number = &*n.extract::<PyClassGuard<'_, Number>>(py)?;\r\n///     assert_eq!(n_immutable.inner, 1);\r\n///\r\n///     Ok(())\r\n/// })\r\n/// # }\r\n/// ```\r\n/// ## Dealing with possibly overlapping mutable references\r\n///\r\n/// It is also necessary to use [`PyClassGuardMut`] if you can receive mutable\r\n/// arguments that may overlap. Suppose the following function that swaps the\r\n/// values of two `Number`s:\r\n/// ```\r\n/// # use pyo3::prelude::*;\r\n/// # #[pyclass]\r\n/// # pub struct Number {\r\n/// #     inner: u32,\r\n/// # }\r\n/// #[pyfunction]\r\n/// fn swap_numbers(a: &mut Number, b: &mut Number) {\r\n///     std::mem::swap(&mut a.inner, &mut b.inner);\r\n/// }\r\n/// # fn main() {\r\n/// #     Python::attach(|py| {\r\n/// #         let n = Py::new(py, Number{inner: 35}).unwrap();\r\n/// #         let n2 = n.clone_ref(py);\r\n/// #         assert!(n.is(&n2));\r\n/// #         let fun = pyo3::wrap_pyfunction!(swap_numbers, py).unwrap();\r\n/// #         fun.call1((n, n2)).expect_err(\"Managed to create overlapping mutable references. Note: this is undefined behaviour.\");\r\n/// #     });\r\n/// # }\r\n/// ```\r\n/// When users pass in the same `Number` as both arguments, one of the mutable\r\n/// borrows will fail and raise a `RuntimeError`:\r\n/// ```text\r\n/// >>> a = Number()\r\n/// >>> swap_numbers(a, a)\r\n/// Traceback (most recent call last):\r\n///   File \"<stdin>\", line 1, in <module>\r\n///   RuntimeError: Already borrowed\r\n/// ```\r\n///\r\n/// It is better to write that function like this:\r\n/// ```rust\r\n/// # use pyo3::prelude::*;\r\n/// # use pyo3::{PyClassGuard, PyClassGuardMut};\r\n/// # #[pyclass]\r\n/// # pub struct Number {\r\n/// #     inner: u32,\r\n/// # }\r\n/// #[pyfunction]\r\n/// fn swap_numbers(a: &Bound<'_, Number>, b: &Bound<'_, Number>) -> PyResult<()> {\r\n///     // Check that the pointers are unequal\r\n///     if !a.is(b) {\r\n///         let mut a: PyClassGuardMut<'_, Number> = a.extract()?;\r\n///         let mut b: PyClassGuardMut<'_, Number> = b.extract()?;\r\n///         std::mem::swap(&mut a.inner, &mut b.inner);\r\n///     } else {\r\n///         // Do nothing - they are the same object, so don't need swapping.\r\n///     }\r\n///     Ok(())\r\n/// }\r\n/// # fn main() {\r\n/// #     // With duplicate numbers\r\n/// #     Python::attach(|py| {\r\n/// #         let n = Py::new(py, Number{inner: 35}).unwrap();\r\n/// #         let n2 = n.clone_ref(py);\r\n/// #         assert!(n.is(&n2));\r\n/// #         let fun = pyo3::wrap_pyfunction!(swap_numbers, py).unwrap();\r\n/// #         fun.call1((n, n2)).unwrap();\r\n/// #     });\r\n/// #\r\n/// #     // With two different numbers\r\n/// #     Python::attach(|py| {\r\n/// #         let n = Py::new(py, Number{inner: 35}).unwrap();\r\n/// #         let n2 = Py::new(py, Number{inner: 42}).unwrap();\r\n/// #         assert!(!n.is(&n2));\r\n/// #         let fun = pyo3::wrap_pyfunction!(swap_numbers, py).unwrap();\r\n/// #         fun.call1((&n, &n2)).unwrap();\r\n/// #         let n: u32 = n.extract::<PyClassGuard<'_, Number>>(py).unwrap().inner;\r\n/// #         let n2: u32 = n2.extract::<PyClassGuard<'_, Number>>(py).unwrap().inner;\r\n/// #         assert_eq!(n, 42);\r\n/// #         assert_eq!(n2, 35);\r\n/// #     });\r\n/// # }\r\n/// ```\r\n/// See [`PyClassGuard`] and the [guide] for more information.\r\n///\r\n/// [guide]: https://pyo3.rs/latest/class.html#bound-and-interior-mutability\r\n///     \"Bound and interior mutability\"\r\n#[repr(transparent)]\r\npub struct PyClassGuardMut<'a, T: PyClass<Frozen = False>> {\r\n    ptr: NonNull<ffi::PyObject>,\r\n    marker: PhantomData<&'a Py<T>>,\r\n}\r\n\r\nimpl<'a, T: PyClass<Frozen = False>> PyClassGuardMut<'a, T> {\r\n    pub(crate) fn try_borrow_mut(obj: &'a Py<T>) -> Result<Self, PyBorrowMutError> {\r\n        Self::try_from_class_object(obj.get_class_object())\r\n    }\r\n\r\n    pub(crate) fn try_borrow_mut_from_borrowed(\r\n        obj: Borrowed<'a, '_, T>,\r\n    ) -> Result<Self, PyBorrowMutError> {\r\n        Self::try_from_class_object(obj.get_class_object())\r\n    }\r\n\r\n    fn try_from_class_object(\r\n        obj: &'a <T as PyClassImpl>::Layout,\r\n    ) -> Result<Self, PyBorrowMutError> {\r\n        obj.ensure_threadsafe();\r\n        obj.borrow_checker().try_borrow_mut().map(|_| Self {\r\n            ptr: NonNull::from(obj).cast(),\r\n            marker: PhantomData,\r\n        })\r\n    }\r\n\r\n    pub(crate) fn as_class_object(&self) -> &'a <T as PyClassImpl>::Layout {\r\n        // SAFETY: `ptr` by construction points to a `PyClassObject<T>` and is\r\n        // valid for at least 'a\r\n        unsafe { self.ptr.cast().as_ref() }\r\n    }\r\n\r\n    /// Consumes the [`PyClassGuardMut`] and returns a [`PyClassGuardMap`] for a component of the\r\n    /// borrowed data\r\n    ///\r\n    /// # Examples\r\n    ///\r\n    /// ```\r\n    /// # use pyo3::prelude::*;\r\n    /// # use pyo3::PyClassGuardMut;\r\n    ///\r\n    /// #[pyclass]\r\n    /// pub struct MyClass {\r\n    ///     data: [i32; 100],\r\n    /// }\r\n    ///\r\n    /// # Python::attach(|py| {\r\n    /// let obj = Bound::new(py, MyClass { data: [0; 100] })?;\r\n    /// let mut data = obj.extract::<PyClassGuardMut<'_, MyClass>>()?.map(|c| c.data.as_mut_slice());\r\n    /// data[0] = 42;\r\n    /// # Ok::<_, PyErr>(())\r\n    /// # }).unwrap();\r\n    /// ```\r\n    pub fn map<F, U: ?Sized>(self, f: F) -> PyClassGuardMap<'a, U, true>\r\n    where\r\n        F: FnOnce(&mut T) -> &mut U,\r\n    {\r\n        let mut slf = std::mem::ManuallyDrop::new(self); // the borrow is released when dropping the `PyClassGuardMap`\r\n        PyClassGuardMap {\r\n            ptr: NonNull::from(f(&mut slf)),\r\n            checker: slf.as_class_object().borrow_checker(),\r\n        }\r\n    }\r\n}\r\n\r\nimpl<'a, T> PyClassGuardMut<'a, T>\r\nwhere\r\n    T: PyClass<Frozen = False>,\r\n    T::BaseType: PyClass<Frozen = False>,\r\n{\r\n    /// Borrows a mutable reference to `PyClassGuardMut<T::BaseType>`.\r\n    ///\r\n    /// With the help of this method, you can mutate attributes and call\r\n    /// mutating methods on the superclass without consuming the\r\n    /// `PyClassGuardMut<T>`. This method can also be chained to access the\r\n    /// super-superclass (and so on).\r\n    ///\r\n    /// See [`PyClassGuard::as_super`] for more.\r\n    pub fn as_super(&mut self) -> &mut PyClassGuardMut<'a, T::BaseType> {\r\n        // SAFETY: `PyClassGuardMut<T>` and `PyClassGuardMut<U>` have the same layout\r\n        unsafe { NonNull::from(self).cast().as_mut() }\r\n    }\r\n\r\n    /// Gets a `PyClassGuardMut<T::BaseType>`.\r\n    ///\r\n    /// See [`PyClassGuard::into_super`] for more.\r\n    pub fn into_super(self) -> PyClassGuardMut<'a, T::BaseType> {\r\n        // `PyClassGuardMut` is only available for non-frozen classes, so there\r\n        // is no possibility of leaking borrows like `PyClassGuard`\r\n        PyClassGuardMut {\r\n            ptr: std::mem::ManuallyDrop::new(self).ptr,\r\n            marker: PhantomData,\r\n        }\r\n    }\r\n}\r\n\r\nimpl<T: PyClass<Frozen = False>> Deref for PyClassGuardMut<'_, T> {\r\n    type Target = T;\r\n\r\n    #[inline]\r\n    fn deref(&self) -> &T {\r\n        // SAFETY: `PyClassObject<T>` contains a valid `T`, by construction no\r\n        // alias is enforced\r\n        unsafe { &*self.as_class_object().get_ptr().cast_const() }\r\n    }\r\n}\r\nimpl<T: PyClass<Frozen = False>> DerefMut for PyClassGuardMut<'_, T> {\r\n    #[inline]\r\n    fn deref_mut(&mut self) -> &mut T {\r\n        // SAFETY: `PyClassObject<T>` contains a valid `T`, by construction no\r\n        // alias is enforced\r\n        unsafe { &mut *self.as_class_object().get_ptr() }\r\n    }\r\n}\r\n\r\nimpl<'a, 'py, T: PyClass<Frozen = False>> FromPyObject<'a, 'py> for PyClassGuardMut<'a, T> {\r\n    type Error = PyClassGuardMutError<'a, 'py>;\r\n\r\n    #[cfg(feature = \"experimental-inspect\")]\r\n    const INPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\r\n\r\n    fn extract(obj: Borrowed<'a, 'py, crate::PyAny>) -> Result<Self, Self::Error> {\r\n        Self::try_from_class_object(\r\n            obj.cast::<T>()\r\n                .map_err(|e| PyClassGuardMutError(Some(e)))?\r\n                .get_class_object(),\r\n        )\r\n        .map_err(|_| PyClassGuardMutError(None))\r\n    }\r\n}\r\n\r\nimpl<'a, 'py, T: PyClass<Frozen = False>> IntoPyObject<'py> for PyClassGuardMut<'a, T> {\r\n    type Target = T;\r\n    type Output = Borrowed<'a, 'py, T>;\r\n    type Error = Infallible;\r\n\r\n    #[cfg(feature = \"experimental-inspect\")]\r\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\r\n\r\n    #[inline]\r\n    fn into_pyobject(self, py: crate::Python<'py>) -> Result<Self::Output, Self::Error> {\r\n        (&self).into_pyobject(py)\r\n    }\r\n}\r\n\r\nimpl<'a, 'py, T: PyClass<Frozen = False>> IntoPyObject<'py> for &PyClassGuardMut<'a, T> {\r\n    type Target = T;\r\n    type Output = Borrowed<'a, 'py, T>;\r\n    type Error = Infallible;\r\n\r\n    #[cfg(feature = \"experimental-inspect\")]\r\n    const OUTPUT_TYPE: PyStaticExpr = T::TYPE_HINT;\r\n\r\n    #[inline]\r\n    fn into_pyobject(self, py: crate::Python<'py>) -> Result<Self::Output, Self::Error> {\r\n        // SAFETY: `ptr` is guaranteed to be valid for 'a and points to an\r\n        // object of type T\r\n        unsafe { Ok(Borrowed::from_non_null(py, self.ptr).cast_unchecked()) }\r\n    }\r\n}\r\n\r\nimpl<T: PyClass<Frozen = False>> Drop for PyClassGuardMut<'_, T> {\r\n    /// Releases the mutable borrow\r\n    fn drop(&mut self) {\r\n        self.as_class_object().borrow_checker().release_borrow_mut()\r\n    }\r\n}\r\n\r\n// SAFETY: `PyClassGuardMut` only provides access to the inner `T` (and no other\r\n// Python APIs) which does not require a Python thread state\r\n#[cfg(feature = \"nightly\")]\r\nunsafe impl<T: PyClass<Frozen = False>> crate::marker::Ungil for PyClassGuardMut<'_, T> {}\r\n// SAFETY: we provide access to\r\n// - `&T`, which requires `T: Sync` to be Send and `T: Sync` to be Sync\r\n// - `&mut T`, which requires `T: Send` to be Send and `T: Sync` to be Sync\r\nunsafe impl<T: PyClass<Frozen = False> + Send + Sync> Send for PyClassGuardMut<'_, T> {}\r\nunsafe impl<T: PyClass<Frozen = False> + Sync> Sync for PyClassGuardMut<'_, T> {}\r\n\r\n/// Custom error type for extracting a [PyClassGuardMut]\r\npub struct PyClassGuardMutError<'a, 'py>(pub(crate) Option<CastError<'a, 'py>>);\r\n\r\nimpl fmt::Debug for PyClassGuardMutError<'_, '_> {\r\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\r\n        if let Some(e) = &self.0 {\r\n            write!(f, \"{e:?}\")\r\n        } else {\r\n            write!(f, \"{:?}\", PyBorrowMutError::new())\r\n        }\r\n    }\r\n}\r\n\r\nimpl fmt::Display for PyClassGuardMutError<'_, '_> {\r\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\r\n        if let Some(e) = &self.0 {\r\n            write!(f, \"{e}\")\r\n        } else {\r\n            write!(f, \"{}\", PyBorrowMutError::new())\r\n        }\r\n    }\r\n}\r\n\r\nimpl From<PyClassGuardMutError<'_, '_>> for PyErr {\r\n    fn from(value: PyClassGuardMutError<'_, '_>) -> Self {\r\n        if let Some(e) = value.0 {\r\n            e.into()\r\n        } else {\r\n            PyBorrowMutError::new().into()\r\n        }\r\n    }\r\n}\r\n\r\n/// Wraps a borrowed reference `U` to a value stored inside of a pyclass `T`\r\n///\r\n/// See [`PyClassGuard::map`] and [`PyClassGuardMut::map`]\r\npub struct PyClassGuardMap<'a, U: ?Sized, const MUT: bool> {\r\n    ptr: NonNull<U>,\r\n    checker: &'a dyn PyClassBorrowChecker,\r\n}\r\n\r\nimpl<U: ?Sized, const MUT: bool> Deref for PyClassGuardMap<'_, U, MUT> {\r\n    type Target = U;\r\n\r\n    fn deref(&self) -> &U {\r\n        // SAFETY: `checker` guards our access to the `T` that `U` points into\r\n        unsafe { self.ptr.as_ref() }\r\n    }\r\n}\r\n\r\nimpl<U: ?Sized> DerefMut for PyClassGuardMap<'_, U, true> {\r\n    fn deref_mut(&mut self) -> &mut Self::Target {\r\n        // SAFETY: `checker` guards our access to the `T` that `U` points into\r\n        unsafe { self.ptr.as_mut() }\r\n    }\r\n}\r\n\r\nimpl<U: ?Sized, const MUT: bool> Drop for PyClassGuardMap<'_, U, MUT> {\r\n    fn drop(&mut self) {\r\n        if MUT {\r\n            self.checker.release_borrow_mut();\r\n        } else {\r\n            self.checker.release_borrow();\r\n        }\r\n    }\r\n}\r\n\r\n#[cfg(test)]\r\n#[cfg(feature = \"macros\")]\r\nmod tests {\r\n    use super::{PyClassGuard, PyClassGuardMut};\r\n    use crate::{types::PyAnyMethods as _, Bound, IntoPyObject as _, Py, PyErr, Python};\r\n\r\n    #[test]\r\n    fn test_into_frozen_super_released_borrow() {\r\n        #[crate::pyclass]\r\n        #[pyo3(crate = \"crate\", subclass, frozen)]\r\n        struct BaseClass {}\r\n\r\n        #[crate::pyclass]\r\n        #[pyo3(crate = \"crate\", extends=BaseClass, subclass)]\r\n        struct SubClass {}\r\n\r\n        #[crate::pymethods]\r\n        #[pyo3(crate = \"crate\")]\r\n        impl SubClass {\r\n            #[new]\r\n            fn new(py: Python<'_>) -> Py<SubClass> {\r\n                let init = crate::PyClassInitializer::from(BaseClass {}).add_subclass(SubClass {});\r\n                Py::new(py, init).expect(\"allocation error\")\r\n            }\r\n        }\r\n\r\n        Python::attach(|py| {\r\n            let obj = SubClass::new(py);\r\n            drop(PyClassGuard::try_borrow(&obj).unwrap().into_super());\r\n            assert!(PyClassGuardMut::try_borrow_mut(&obj).is_ok());\r\n        })\r\n    }\r\n\r\n    #[test]\r\n    fn test_into_frozen_super_mutable_base_holds_borrow() {\r\n        #[crate::pyclass]\r\n        #[pyo3(crate = \"crate\", subclass)]\r\n        struct BaseClass {}\r\n\r\n        #[crate::pyclass]\r\n        #[pyo3(crate = \"crate\", extends=BaseClass, subclass, frozen)]\r\n        struct SubClass {}\r\n\r\n        #[crate::pyclass]\r\n        #[pyo3(crate = \"crate\", extends=SubClass, subclass)]\r\n        struct SubSubClass {}\r\n\r\n        #[crate::pymethods]\r\n        #[pyo3(crate = \"crate\")]\r\n        impl SubSubClass {\r\n            #[new]\r\n            fn new(py: Python<'_>) -> Py<SubSubClass> {\r\n                let init = crate::PyClassInitializer::from(BaseClass {})\r\n                    .add_subclass(SubClass {})\r\n                    .add_subclass(SubSubClass {});\r\n                Py::new(py, init).expect(\"allocation error\")\r\n            }\r\n        }\r\n\r\n        Python::attach(|py| {\r\n            let obj = SubSubClass::new(py);\r\n            let _super_borrow = PyClassGuard::try_borrow(&obj).unwrap().into_super();\r\n            // the whole object still has an immutable borrow, so we cannot\r\n            // borrow any part mutably (the borrowflag is shared)\r\n            assert!(PyClassGuardMut::try_borrow_mut(&obj).is_err());\r\n        })\r\n    }\r\n\r\n    #[crate::pyclass]\r\n    #[pyo3(crate = \"crate\", subclass)]\r\n    struct BaseClass {\r\n        val1: usize,\r\n    }\r\n\r\n    #[crate::pyclass]\r\n    #[pyo3(crate = \"crate\", extends=BaseClass, subclass)]\r\n    struct SubClass {\r\n        val2: usize,\r\n    }\r\n\r\n    #[crate::pyclass]\r\n    #[pyo3(crate = \"crate\", extends=SubClass)]\r\n    struct SubSubClass {\r\n        #[pyo3(get)]\r\n        val3: usize,\r\n    }\r\n\r\n    #[crate::pymethods]\r\n    #[pyo3(crate = \"crate\")]\r\n    impl SubSubClass {\r\n        #[new]\r\n        fn new(py: Python<'_>) -> Py<SubSubClass> {\r\n            let init = crate::PyClassInitializer::from(BaseClass { val1: 10 })\r\n                .add_subclass(SubClass { val2: 15 })\r\n                .add_subclass(SubSubClass { val3: 20 });\r\n            Py::new(py, init).expect(\"allocation error\")\r\n        }\r\n\r\n        fn get_values(self_: PyClassGuard<'_, Self>) -> (usize, usize, usize) {\r\n            let val1 = self_.as_super().as_super().val1;\r\n            let val2 = self_.as_super().val2;\r\n            (val1, val2, self_.val3)\r\n        }\r\n\r\n        fn double_values(mut self_: PyClassGuardMut<'_, Self>) {\r\n            self_.as_super().as_super().val1 *= 2;\r\n            self_.as_super().val2 *= 2;\r\n            self_.val3 *= 2;\r\n        }\r\n\r\n        fn __add__<'a>(\r\n            mut slf: PyClassGuardMut<'a, Self>,\r\n            other: PyClassGuard<'a, Self>,\r\n        ) -> PyClassGuardMut<'a, Self> {\r\n            slf.val3 += other.val3;\r\n            slf\r\n        }\r\n\r\n        fn __rsub__<'a>(\r\n            slf: PyClassGuard<'a, Self>,\r\n            mut other: PyClassGuardMut<'a, Self>,\r\n        ) -> PyClassGuardMut<'a, Self> {\r\n            other.val3 -= slf.val3;\r\n            other\r\n        }\r\n    }\r\n\r\n    #[test]\r\n    fn test_pyclassguard_into_pyobject() {\r\n        Python::attach(|py| {\r\n            let class = Py::new(py, BaseClass { val1: 42 })?;\r\n            let guard = PyClassGuard::try_borrow(&class).unwrap();\r\n            let new_ref = (&guard).into_pyobject(py)?;\r\n            assert!(new_ref.is(&class));\r\n            let new = guard.into_pyobject(py)?;\r\n            assert!(new.is(&class));\r\n            Ok::<_, PyErr>(())\r\n        })\r\n        .unwrap();\r\n    }\r\n\r\n    #[test]\r\n    fn test_pyclassguardmut_into_pyobject() {\r\n        Python::attach(|py| {\r\n            let class = Py::new(py, BaseClass { val1: 42 })?;\r\n            let guard = PyClassGuardMut::try_borrow_mut(&class).unwrap();\r\n            let new_ref = (&guard).into_pyobject(py)?;\r\n            assert!(new_ref.is(&class));\r\n            let new = guard.into_pyobject(py)?;\r\n            assert!(new.is(&class));\r\n            Ok::<_, PyErr>(())\r\n        })\r\n        .unwrap();\r\n    }\r\n    #[test]\r\n    fn test_pyclassguard_as_super() {\r\n        Python::attach(|py| {\r\n            let obj = SubSubClass::new(py).into_bound(py);\r\n            let pyref = PyClassGuard::try_borrow(obj.as_unbound()).unwrap();\r\n            assert_eq!(pyref.as_super().as_super().val1, 10);\r\n            assert_eq!(pyref.as_super().val2, 15);\r\n            assert_eq!(pyref.val3, 20);\r\n            assert_eq!(SubSubClass::get_values(pyref), (10, 15, 20));\r\n        });\r\n    }\r\n\r\n    #[test]\r\n    fn test_pyclassguardmut_as_super() {\r\n        Python::attach(|py| {\r\n            let obj = SubSubClass::new(py).into_bound(py);\r\n            assert_eq!(\r\n                SubSubClass::get_values(PyClassGuard::try_borrow(obj.as_unbound()).unwrap()),\r\n                (10, 15, 20)\r\n            );\r\n            {\r\n                let mut pyrefmut = PyClassGuardMut::try_borrow_mut(obj.as_unbound()).unwrap();\r\n                assert_eq!(pyrefmut.as_super().as_super().val1, 10);\r\n                pyrefmut.as_super().as_super().val1 -= 5;\r\n                pyrefmut.as_super().val2 -= 5;\r\n                pyrefmut.val3 -= 5;\r\n            }\r\n            assert_eq!(\r\n                SubSubClass::get_values(PyClassGuard::try_borrow(obj.as_unbound()).unwrap()),\r\n                (5, 10, 15)\r\n            );\r\n            SubSubClass::double_values(PyClassGuardMut::try_borrow_mut(obj.as_unbound()).unwrap());\r\n            assert_eq!(\r\n                SubSubClass::get_values(PyClassGuard::try_borrow(obj.as_unbound()).unwrap()),\r\n                (10, 20, 30)\r\n            );\r\n        });\r\n    }\r\n\r\n    #[test]\r\n    fn test_extract_guard() {\r\n        Python::attach(|py| {\r\n            let obj1 = SubSubClass::new(py);\r\n            let obj2 = SubSubClass::new(py);\r\n            crate::py_run!(py, obj1 obj2, \"assert ((obj1 + obj2) - obj2).val3 == obj1.val3\");\r\n        });\r\n    }\r\n\r\n    #[test]\r\n    fn test_pyclassguards_in_python() {\r\n        Python::attach(|py| {\r\n            let obj = SubSubClass::new(py);\r\n            crate::py_run!(py, obj, \"assert obj.get_values() == (10, 15, 20)\");\r\n            crate::py_run!(py, obj, \"assert obj.double_values() is None\");\r\n            crate::py_run!(py, obj, \"assert obj.get_values() == (20, 30, 40)\");\r\n        });\r\n    }\r\n\r\n    #[crate::pyclass]\r\n    #[pyo3(crate = \"crate\")]\r\n    pub struct MyClass {\r\n        data: [i32; 100],\r\n    }\r\n\r\n    #[test]\r\n    fn test_pyclassguard_map() {\r\n        Python::attach(|py| {\r\n            let obj = Bound::new(py, MyClass { data: [0; 100] })?;\r\n            let data = PyClassGuard::try_borrow(obj.as_unbound())?.map(|c| &c.data);\r\n            assert_eq!(data[0], 0);\r\n            assert!(obj.try_borrow_mut().is_err()); // obj is still protected\r\n            drop(data);\r\n            assert!(obj.try_borrow_mut().is_ok()); // drop released shared borrow\r\n            Ok::<_, PyErr>(())\r\n        })\r\n        .unwrap()\r\n    }\r\n\r\n    #[test]\r\n    fn test_pyclassguardmut_map() {\r\n        Python::attach(|py| {\r\n            let obj = Bound::new(py, MyClass { data: [0; 100] })?;\r\n            let mut data =\r\n                PyClassGuardMut::try_borrow_mut(obj.as_unbound())?.map(|c| c.data.as_mut_slice());\r\n            assert_eq!(data[0], 0);\r\n            data[0] = 5;\r\n            assert_eq!(data[0], 5);\r\n            assert!(obj.try_borrow_mut().is_err()); // obj is still protected\r\n            drop(data);\r\n            assert!(obj.try_borrow_mut().is_ok()); // drop released mutable borrow\r\n            Ok::<_, PyErr>(())\r\n        })\r\n        .unwrap()\r\n    }\r\n\r\n    #[test]\r\n    fn test_pyclassguard_map_unrelated() {\r\n        use crate::types::{PyString, PyStringMethods};\r\n        Python::attach(|py| {\r\n            let obj = Bound::new(py, MyClass { data: [0; 100] })?;\r\n            let string = PyString::new(py, \"pyo3\");\r\n            // It is possible to return something not borrowing from the guard, but that shouldn't\r\n            // matter. `RefCell` has the same behaviour\r\n            let refmap = PyClassGuard::try_borrow(obj.as_unbound())?.map(|_| &string);\r\n            assert_eq!(refmap.to_cow()?, \"pyo3\");\r\n            Ok::<_, PyErr>(())\r\n        })\r\n        .unwrap()\r\n    }\r\n}\r\n"
  },
  {
    "path": "src/pyclass.rs",
    "content": "//! `PyClass` and related traits.\nuse crate::{ffi, impl_::pyclass::PyClassImpl, PyTypeInfo};\nuse std::{cmp::Ordering, os::raw::c_int};\n\nmod create_type_object;\nmod gc;\nmod guard;\n\npub(crate) use self::create_type_object::{create_type_object, PyClassTypeObject};\n\npub use self::gc::{PyTraverseError, PyVisit};\npub use self::guard::{\n    PyClassGuard, PyClassGuardError, PyClassGuardMap, PyClassGuardMut, PyClassGuardMutError,\n};\n\n/// Types that can be used as Python classes.\n///\n/// The `#[pyclass]` attribute implements this trait for your Rust struct -\n/// you shouldn't implement this trait directly.\npub trait PyClass: PyTypeInfo + PyClassImpl {\n    /// Name of the class.\n    ///\n    /// This can be set via `#[pyclass(name = \"...\")]`, otherwise it defaults to the Rust type name.\n    const NAME: &'static str;\n\n    /// Whether the pyclass is frozen.\n    ///\n    /// This can be enabled via `#[pyclass(frozen)]`.\n    type Frozen: Frozen;\n}\n\n/// Operators for the `__richcmp__` method\n#[derive(Debug, Clone, Copy)]\npub enum CompareOp {\n    /// The *less than* operator.\n    Lt = ffi::Py_LT as isize,\n    /// The *less than or equal to* operator.\n    Le = ffi::Py_LE as isize,\n    /// The equality operator.\n    Eq = ffi::Py_EQ as isize,\n    /// The *not equal to* operator.\n    Ne = ffi::Py_NE as isize,\n    /// The *greater than* operator.\n    Gt = ffi::Py_GT as isize,\n    /// The *greater than or equal to* operator.\n    Ge = ffi::Py_GE as isize,\n}\n\nimpl CompareOp {\n    /// Conversion from the C enum.\n    pub fn from_raw(op: c_int) -> Option<Self> {\n        match op {\n            ffi::Py_LT => Some(CompareOp::Lt),\n            ffi::Py_LE => Some(CompareOp::Le),\n            ffi::Py_EQ => Some(CompareOp::Eq),\n            ffi::Py_NE => Some(CompareOp::Ne),\n            ffi::Py_GT => Some(CompareOp::Gt),\n            ffi::Py_GE => Some(CompareOp::Ge),\n            _ => None,\n        }\n    }\n\n    /// Returns if a Rust [`std::cmp::Ordering`] matches this ordering query.\n    ///\n    /// Usage example:\n    ///\n    /// ```rust,no_run\n    /// # use pyo3::prelude::*;\n    /// # use pyo3::class::basic::CompareOp;\n    ///\n    /// #[pyclass]\n    /// struct Size {\n    ///     size: usize,\n    /// }\n    ///\n    /// #[pymethods]\n    /// impl Size {\n    ///     fn __richcmp__(&self, other: &Size, op: CompareOp) -> bool {\n    ///         op.matches(self.size.cmp(&other.size))\n    ///     }\n    /// }\n    /// ```\n    pub fn matches(&self, result: Ordering) -> bool {\n        match self {\n            CompareOp::Eq => result == Ordering::Equal,\n            CompareOp::Ne => result != Ordering::Equal,\n            CompareOp::Lt => result == Ordering::Less,\n            CompareOp::Le => result != Ordering::Greater,\n            CompareOp::Gt => result == Ordering::Greater,\n            CompareOp::Ge => result != Ordering::Less,\n        }\n    }\n}\n\n/// A workaround for [associated const equality](https://github.com/rust-lang/rust/issues/92827).\n///\n/// This serves to have True / False values in the [`PyClass`] trait's `Frozen` type.\n#[doc(hidden)]\npub mod boolean_struct {\n    pub(crate) mod private {\n        use super::*;\n\n        /// A way to \"seal\" the boolean traits.\n        pub trait Boolean {\n            const VALUE: bool;\n        }\n\n        impl Boolean for True {\n            const VALUE: bool = true;\n        }\n        impl Boolean for False {\n            const VALUE: bool = false;\n        }\n    }\n\n    pub struct True(());\n    pub struct False(());\n}\n\n/// A trait which is used to describe whether a `#[pyclass]` is frozen.\n#[doc(hidden)]\npub trait Frozen: boolean_struct::private::Boolean {}\n\nimpl Frozen for boolean_struct::True {}\nimpl Frozen for boolean_struct::False {}\n\nmod tests {\n    #[test]\n    fn test_compare_op_matches() {\n        use super::CompareOp;\n        use std::cmp::Ordering;\n\n        assert!(CompareOp::Eq.matches(Ordering::Equal));\n        assert!(CompareOp::Ne.matches(Ordering::Less));\n        assert!(CompareOp::Ge.matches(Ordering::Greater));\n        assert!(CompareOp::Gt.matches(Ordering::Greater));\n        assert!(CompareOp::Le.matches(Ordering::Equal));\n        assert!(CompareOp::Lt.matches(Ordering::Less));\n    }\n}\n"
  },
  {
    "path": "src/pyclass_init.rs",
    "content": "//! Contains initialization utilities for `#[pyclass]`.\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::impl_::pyclass::{PyClassBaseType, PyClassImpl};\nuse crate::impl_::pyclass_init::{PyNativeTypeInitializer, PyObjectInit};\nuse crate::pycell::impl_::PyClassObjectLayout;\nuse crate::{ffi, Bound, PyClass, PyResult, Python};\nuse crate::{ffi::PyTypeObject, pycell::impl_::PyClassObjectContents};\nuse std::marker::PhantomData;\n\n/// Initializer for our `#[pyclass]` system.\n///\n/// You can use this type to initialize complicatedly nested `#[pyclass]`.\n///\n/// # Examples\n///\n/// ```\n/// # use pyo3::prelude::*;\n/// # use pyo3::py_run;\n/// #[pyclass(subclass)]\n/// struct BaseClass {\n///     #[pyo3(get)]\n///     basename: &'static str,\n/// }\n/// #[pyclass(extends=BaseClass, subclass)]\n/// struct SubClass {\n///     #[pyo3(get)]\n///     subname: &'static str,\n/// }\n/// #[pyclass(extends=SubClass)]\n/// struct SubSubClass {\n///     #[pyo3(get)]\n///     subsubname: &'static str,\n/// }\n///\n/// #[pymethods]\n/// impl SubSubClass {\n///     #[new]\n///     fn new() -> PyClassInitializer<Self> {\n///         PyClassInitializer::from(BaseClass { basename: \"base\" })\n///             .add_subclass(SubClass { subname: \"sub\" })\n///             .add_subclass(SubSubClass {\n///                 subsubname: \"subsub\",\n///             })\n///     }\n/// }\n/// Python::attach(|py| {\n///     let typeobj = py.get_type::<SubSubClass>();\n///     let sub_sub_class = typeobj.call((), None).unwrap();\n///     py_run!(\n///         py,\n///         sub_sub_class,\n///         r#\"\n///  assert sub_sub_class.basename == 'base'\n///  assert sub_sub_class.subname == 'sub'\n///  assert sub_sub_class.subsubname == 'subsub'\"#\n///     );\n/// });\n/// ```\npub struct PyClassInitializer<T: PyClass> {\n    init: T,\n    super_init: <T::BaseType as PyClassBaseType>::Initializer,\n}\n\nimpl<T: PyClass> PyClassInitializer<T> {\n    /// Constructs a new initializer from value `T` and base class' initializer.\n    ///\n    /// It is recommended to use `add_subclass` instead of this method for most usage.\n    #[track_caller]\n    #[inline]\n    pub fn new(init: T, super_init: <T::BaseType as PyClassBaseType>::Initializer) -> Self {\n        Self { init, super_init }\n    }\n\n    /// Constructs a new initializer from an initializer for the base class.\n    ///\n    /// # Examples\n    /// ```\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyclass(subclass)]\n    /// struct BaseClass {\n    ///     #[pyo3(get)]\n    ///     value: i32,\n    /// }\n    ///\n    /// impl BaseClass {\n    ///     fn new(value: i32) -> PyResult<Self> {\n    ///         Ok(Self { value })\n    ///     }\n    /// }\n    ///\n    /// #[pyclass(extends=BaseClass)]\n    /// struct SubClass {}\n    ///\n    /// #[pymethods]\n    /// impl SubClass {\n    ///     #[new]\n    ///     fn new(value: i32) -> PyResult<PyClassInitializer<Self>> {\n    ///         let base_init = PyClassInitializer::from(BaseClass::new(value)?);\n    ///         Ok(base_init.add_subclass(SubClass {}))\n    ///     }\n    /// }\n    ///\n    /// fn main() -> PyResult<()> {\n    ///     Python::attach(|py| {\n    ///         let m = PyModule::new(py, \"example\")?;\n    ///         m.add_class::<SubClass>()?;\n    ///         m.add_class::<BaseClass>()?;\n    ///\n    ///         let instance = m.getattr(\"SubClass\")?.call1((92,))?;\n    ///\n    ///         // `SubClass` does not have a `value` attribute, but `BaseClass` does.\n    ///         let n = instance.getattr(\"value\")?.extract::<i32>()?;\n    ///         assert_eq!(n, 92);\n    ///\n    ///         Ok(())\n    ///     })\n    /// }\n    /// ```\n    #[track_caller]\n    #[inline]\n    pub fn add_subclass<S>(self, subclass_value: S) -> PyClassInitializer<S>\n    where\n        T: PyClassBaseType<Initializer = Self>,\n        S: PyClass<BaseType = T>,\n    {\n        PyClassInitializer::new(subclass_value, self)\n    }\n\n    /// Creates a new class object and initializes it.\n    pub(crate) fn create_class_object(self, py: Python<'_>) -> PyResult<Bound<'_, T>>\n    where\n        T: PyClass,\n    {\n        unsafe { self.create_class_object_of_type(py, T::type_object_raw(py)) }\n    }\n\n    /// Creates a new class object and initializes it given a typeobject `subtype`.\n    ///\n    /// # Safety\n    /// `subtype` must be a valid pointer to the type object of T or a subclass.\n    pub(crate) unsafe fn create_class_object_of_type(\n        self,\n        py: Python<'_>,\n        target_type: *mut crate::ffi::PyTypeObject,\n    ) -> PyResult<Bound<'_, T>>\n    where\n        T: PyClass,\n    {\n        let obj = unsafe { self.super_init.into_new_object(py, target_type)? };\n\n        // SAFETY: `obj` is constructed using `T::Layout` but has not been initialized yet\n        let contents = unsafe { <T as PyClassImpl>::Layout::contents_uninit(obj) };\n        // SAFETY: `contents` is a non-null pointer to the space allocated for our\n        // `PyClassObjectContents` (either statically in Rust or dynamically by Python)\n        unsafe { (*contents).write(PyClassObjectContents::new(self.init)) };\n\n        // Safety: obj is a valid pointer to an object of type `target_type`, which` is a known\n        // subclass of `T`\n        Ok(unsafe { obj.assume_owned(py).cast_into_unchecked() })\n    }\n}\n\nimpl<T: PyClass> PyObjectInit<T> for PyClassInitializer<T> {\n    unsafe fn into_new_object(\n        self,\n        py: Python<'_>,\n        subtype: *mut PyTypeObject,\n    ) -> PyResult<*mut ffi::PyObject> {\n        unsafe {\n            self.create_class_object_of_type(py, subtype)\n                .map(Bound::into_ptr)\n        }\n    }\n}\n\nimpl<T> From<T> for PyClassInitializer<T>\nwhere\n    T: PyClass,\n    T::BaseType: PyClassBaseType<Initializer = PyNativeTypeInitializer<T::BaseType>>,\n{\n    #[inline]\n    fn from(value: T) -> PyClassInitializer<T> {\n        Self::new(value, PyNativeTypeInitializer(PhantomData))\n    }\n}\n\nimpl<S, B> From<(S, B)> for PyClassInitializer<S>\nwhere\n    S: PyClass<BaseType = B>,\n    B: PyClass + PyClassBaseType<Initializer = PyClassInitializer<B>>,\n    B::BaseType: PyClassBaseType<Initializer = PyNativeTypeInitializer<B::BaseType>>,\n{\n    #[track_caller]\n    #[inline]\n    fn from(sub_and_base: (S, B)) -> PyClassInitializer<S> {\n        let (sub, base) = sub_and_base;\n        PyClassInitializer::from(base).add_subclass(sub)\n    }\n}\n"
  },
  {
    "path": "src/sealed.rs",
    "content": "use crate::impl_::pyfunction::PyFunctionDef;\n#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]\nuse crate::types::PyFrame;\nuse crate::types::{\n    PyBool, PyByteArray, PyBytes, PyCapsule, PyComplex, PyDict, PyFloat, PyFrozenSet, PyList,\n    PyMapping, PyMappingProxy, PyModule, PyRange, PySequence, PySet, PySlice, PyString,\n    PyTraceback, PyTuple, PyType, PyWeakref, PyWeakrefProxy, PyWeakrefReference,\n};\nuse crate::{ffi, Bound, PyAny, PyResult};\n\nuse crate::pyclass_init::PyClassInitializer;\n\nuse crate::impl_::{\n    pyclass_init::PyNativeTypeInitializer,\n    pymethods::PyMethodDef,\n    pymodule::{AddClassToModule, AddTypeToModule, ModuleDef},\n};\n\npub trait Sealed {}\n\n// for FfiPtrExt\nimpl Sealed for *mut ffi::PyObject {}\n\n// for PyResultExt\nimpl Sealed for PyResult<Bound<'_, PyAny>> {}\n\n// for Py(...)Methods\nimpl Sealed for Bound<'_, PyAny> {}\nimpl Sealed for Bound<'_, PyBool> {}\nimpl Sealed for Bound<'_, PyByteArray> {}\nimpl Sealed for Bound<'_, PyBytes> {}\nimpl Sealed for Bound<'_, PyCapsule> {}\nimpl Sealed for Bound<'_, PyComplex> {}\nimpl Sealed for Bound<'_, PyDict> {}\nimpl Sealed for Bound<'_, PyFloat> {}\nimpl Sealed for Bound<'_, PyFrozenSet> {}\nimpl Sealed for Bound<'_, PyList> {}\nimpl Sealed for Bound<'_, PyMapping> {}\nimpl Sealed for Bound<'_, PyMappingProxy> {}\nimpl Sealed for Bound<'_, PyModule> {}\nimpl Sealed for Bound<'_, PyRange> {}\nimpl Sealed for Bound<'_, PySequence> {}\nimpl Sealed for Bound<'_, PySet> {}\nimpl Sealed for Bound<'_, PySlice> {}\nimpl Sealed for Bound<'_, PyString> {}\nimpl Sealed for Bound<'_, PyTraceback> {}\n#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]\nimpl Sealed for Bound<'_, PyFrame> {}\nimpl Sealed for Bound<'_, PyTuple> {}\nimpl Sealed for Bound<'_, PyType> {}\nimpl Sealed for Bound<'_, PyWeakref> {}\nimpl Sealed for Bound<'_, PyWeakrefProxy> {}\nimpl Sealed for Bound<'_, PyWeakrefReference> {}\n\nimpl<T> Sealed for AddTypeToModule<T> {}\nimpl<T> Sealed for AddClassToModule<T> {}\nimpl Sealed for PyMethodDef {}\nimpl Sealed for PyFunctionDef {}\nimpl Sealed for ModuleDef {}\n\nimpl<T: crate::type_object::PyTypeInfo> Sealed for PyNativeTypeInitializer<T> {}\nimpl<T: crate::pyclass::PyClass> Sealed for PyClassInitializer<T> {}\n\nimpl Sealed for std::sync::Once {}\nimpl<T> Sealed for std::sync::Mutex<T> {}\n#[cfg(feature = \"lock_api\")]\nimpl<R, T> Sealed for lock_api::Mutex<R, T> {}\n#[cfg(feature = \"parking_lot\")]\nimpl Sealed for parking_lot::Once {}\n#[cfg(feature = \"arc_lock\")]\nimpl<R, T> Sealed for std::sync::Arc<lock_api::Mutex<R, T>> {}\n#[cfg(feature = \"lock_api\")]\nimpl<R, G, T> Sealed for lock_api::ReentrantMutex<R, G, T> {}\n#[cfg(feature = \"arc_lock\")]\nimpl<R, G, T> Sealed for std::sync::Arc<lock_api::ReentrantMutex<R, G, T>> {}\n"
  },
  {
    "path": "src/sync/critical_section.rs",
    "content": "//! Wrappers for the Python critical section API\n//!\n//! [Critical Sections](https://docs.python.org/3/c-api/init.html#python-critical-section-api) allow\n//! access to the [`PyMutex`](https://docs.python.org/3/c-api/init.html#c.PyMutex) lock attached to\n//! each Python object in the free-threaded build. They are no-ops on the GIL-enabled build.\n//!\n//! Provides weaker locking guarantees than traditional locks, but can in some cases be used to\n//! provide guarantees similar to the GIL without the risk of deadlocks associated with traditional\n//! locks.\n//!\n//! # Usage Notes\n//!\n//! The calling thread locks the per-object mutex when it enters the critical section and holds it\n//! until exiting the critical section unless the critical section is suspended. Any call into the\n//! CPython C API may cause the critical section to be suspended. Creating an inner critical\n//! section, for example by accessing an item in a Python list or dict, will cause the outer\n//! critical section to be relased while the inner critical section is active.\n//!\n//! As a consequence, it is only possible to lock one or two objects at a time. If you need two lock\n//! two objects, you should use the variants that accept two arguments. The outer critical section\n//! is suspended if you create an outer an inner critical section on two objects using the\n//! single-argument variants.\n//!\n//! It is not currently possible to lock more than two objects simultaneously using this mechanism.\n//! Taking a critical section on a container object does not lock the objects stored in the\n//! container.\n//!\n//! Many CPython C API functions do not lock the per-object mutex on objects passed to Python. You\n//! should not expect critical sections applied to built-in types to prevent concurrent\n//! modification. This API is most useful for user-defined types with full control over how the\n//! internal state for the type is managed.\n//!\n//! The caller must ensure the closure cannot implicitly release the critical section. If a\n//! multithreaded program calls back into the Python interpreter in a manner that would cause the\n//! critical section to be released, the per-object mutex will be unlocked and the state of the\n//! object may be read from or modified by another thread. Concurrent modifications are impossible,\n//! but races are possible and the state of an object may change \"underneath\" a suspended thread in\n//! possibly surprising ways.\n\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\nuse crate::types::PyMutex;\n\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\nuse crate::Python;\nuse crate::{types::PyAny, Bound};\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\nuse std::cell::UnsafeCell;\n\n#[cfg(Py_GIL_DISABLED)]\nstruct CSGuard(crate::ffi::PyCriticalSection);\n\n#[cfg(Py_GIL_DISABLED)]\nimpl Drop for CSGuard {\n    fn drop(&mut self) {\n        unsafe {\n            crate::ffi::PyCriticalSection_End(&mut self.0);\n        }\n    }\n}\n\n#[cfg(Py_GIL_DISABLED)]\nstruct CS2Guard(crate::ffi::PyCriticalSection2);\n\n#[cfg(Py_GIL_DISABLED)]\nimpl Drop for CS2Guard {\n    fn drop(&mut self) {\n        unsafe {\n            crate::ffi::PyCriticalSection2_End(&mut self.0);\n        }\n    }\n}\n\n/// Allows access to data protected by a PyMutex in a critical section\n///\n/// Used with the `with_critical_section_mutex` and\n/// `with_critical_section_mutex2` functions. See the documentation of those\n/// functions for more details.\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\npub struct EnteredCriticalSection<'a, T>(&'a UnsafeCell<T>);\n\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\nimpl<T> EnteredCriticalSection<'_, T> {\n    /// Get a mutable reference to the data wrapped by a PyMutex\n    ///\n    /// # Safety\n    ///\n    /// The caller must ensure the closure cannot implicitly release the critical section.\n    ///\n    /// If a multithreaded program calls back into the Python interpreter in a manner that would cause\n    /// the critical section to be released, the `PyMutex` will be unlocked and the resource protected\n    /// by the `PyMutex` may be read from or modified by another thread while the critical section is\n    /// suspended. Concurrent modifications are impossible, but races are possible and the state of the\n    /// protected resource may change in possibly surprising ways after calls into the interpreter.\n    pub unsafe fn get_mut(&mut self) -> &mut T {\n        unsafe { &mut *(self.0.get()) }\n    }\n\n    /// Get a immutable reference to the value wrapped by a PyMutex\n    ///\n    /// # Safety\n    ///\n    /// The caller must ensure the critical section is not released while the\n    /// reference is alive. If a multithreaded program calls back into the\n    /// Python interpreter in a manner that would cause the critical section to\n    /// be released, the `PyMutex` will be unlocked and the resource protected\n    /// by the `PyMutex` may be read from or modified by another thread while\n    /// the critical section is suspended and the thread that owns the reference\n    /// is blocked. Concurrent modifications are impossible, but races are\n    /// possible and the state of an object may change \"underneath\" a suspended\n    /// thread in possibly surprising ways. Note that many operations on Python\n    /// objects may call back into the interpreter in a blocking manner because\n    /// many C API calls can trigger the execution of arbitrary Python code.\n    pub unsafe fn get(&self) -> &T {\n        unsafe { &*(self.0.get()) }\n    }\n}\n\n/// Executes a closure with a Python critical section held on an object.\n///\n/// Locks the per-object mutex for the object `op` that is held while the closure `f` is\n/// executing. The critical section may be temporarily released and re-acquired if the closure calls\n/// back into the interpreter. See the notes in the\n/// [`pyo3::sync::critical_section`][crate::sync::critical_section] module documentation for more\n/// details.\n///\n/// This is structurally equivalent to the use of the paired Py_BEGIN_CRITICAL_SECTION and\n/// Py_END_CRITICAL_SECTION C-API macros.\n#[cfg_attr(not(Py_GIL_DISABLED), allow(unused_variables))]\npub fn with_critical_section<F, R>(object: &Bound<'_, PyAny>, f: F) -> R\nwhere\n    F: FnOnce() -> R,\n{\n    #[cfg(Py_GIL_DISABLED)]\n    {\n        let mut guard = CSGuard(unsafe { std::mem::zeroed() });\n        unsafe { crate::ffi::PyCriticalSection_Begin(&mut guard.0, object.as_ptr()) };\n        f()\n    }\n    #[cfg(not(Py_GIL_DISABLED))]\n    {\n        f()\n    }\n}\n\n/// Executes a closure with a Python critical section held on two objects.\n///\n/// Locks the per-object mutex for the objects `a` and `b` that are held while the closure `f` is\n/// executing. The critical section may be temporarily released and re-acquired if the closure calls\n/// back into the interpreter. See the notes in the\n/// [`pyo3::sync::critical_section`][crate::sync::critical_section] module documentation for more\n/// details.\n///\n/// This is structurally equivalent to the use of the paired\n/// Py_BEGIN_CRITICAL_SECTION2 and Py_END_CRITICAL_SECTION2 C-API macros.\n#[cfg_attr(not(Py_GIL_DISABLED), allow(unused_variables))]\npub fn with_critical_section2<F, R>(a: &Bound<'_, PyAny>, b: &Bound<'_, PyAny>, f: F) -> R\nwhere\n    F: FnOnce() -> R,\n{\n    #[cfg(Py_GIL_DISABLED)]\n    {\n        let mut guard = CS2Guard(unsafe { std::mem::zeroed() });\n        unsafe { crate::ffi::PyCriticalSection2_Begin(&mut guard.0, a.as_ptr(), b.as_ptr()) };\n        f()\n    }\n    #[cfg(not(Py_GIL_DISABLED))]\n    {\n        f()\n    }\n}\n\n/// Executes a closure with a Python critical section held on a `PyMutex`.\n///\n/// Locks the mutex `mutex` until the closure `f` finishes. The mutex may be temporarily unlocked\n/// and re-acquired if the closure calls back into the interpreter. See the notes in the\n/// [`pyo3::sync::critical_section`][crate::sync::critical_section] module documentation for more\n/// details.\n///\n/// This variant is particularly useful when paired with a global `PyMutex` to create a \"local GIL\"\n/// to protect global state in an extension in an analogous manner to the GIL without introducing\n/// any deadlock risks or affecting runtime behavior on the GIL-enabled build.\n///\n/// This is structurally equivalent to the use of the paired Py_BEGIN_CRITICAL_SECTION_MUTEX and\n/// Py_END_CRITICAL_SECTION C-API macros.\n///\n/// # Safety\n///\n/// The caller must ensure the closure cannot implicitly release the critical section. See the\n/// safety notes in the documentation for\n/// [`pyo3::sync::critical_section::EnteredCriticalSection`](crate::sync::critical_section::EnteredCriticalSection)\n/// for more details.\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\n#[cfg_attr(not(Py_GIL_DISABLED), allow(unused_variables))]\npub fn with_critical_section_mutex<F, R, T>(_py: Python<'_>, mutex: &PyMutex<T>, f: F) -> R\nwhere\n    F: for<'s> FnOnce(EnteredCriticalSection<'s, T>) -> R,\n{\n    #[cfg(Py_GIL_DISABLED)]\n    {\n        let mut guard = CSGuard(unsafe { std::mem::zeroed() });\n        unsafe { crate::ffi::PyCriticalSection_BeginMutex(&mut guard.0, &mut *mutex.mutex.get()) };\n        f(EnteredCriticalSection(&mutex.data))\n    }\n    #[cfg(not(Py_GIL_DISABLED))]\n    {\n        f(EnteredCriticalSection(&mutex.data))\n    }\n}\n\n/// Executes a closure with a Python critical section held on two `PyMutex` instances.\n///\n/// Simultaneously locks the mutexes `m1` and `m2` and holds them until the closure `f` is\n/// finished. The mutexes may be temporarily unlock and re-acquired if the closure calls back into\n/// the interpreter. See the notes in the\n/// [`pyo3::sync::critical_section`][crate::sync::critical_section] module documentation for more\n/// details.\n///\n/// This is structurally equivalent to the use of the paired\n/// Py_BEGIN_CRITICAL_SECTION2_MUTEX and Py_END_CRITICAL_SECTION2 C-API macros.\n///\n/// A no-op on GIL-enabled builds, where the critical section API is exposed as\n/// a no-op by the Python C API.\n///\n/// # Safety\n///\n/// The caller must ensure the closure cannot implicitly release the critical section. See the\n/// safety notes in the documentation for\n/// [`pyo3::sync::critical_section::EnteredCriticalSection`](crate::sync::critical_section::EnteredCriticalSection)\n/// for more details.\n#[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\n#[cfg_attr(not(Py_GIL_DISABLED), allow(unused_variables))]\npub fn with_critical_section_mutex2<F, R, T1, T2>(\n    _py: Python<'_>,\n    m1: &PyMutex<T1>,\n    m2: &PyMutex<T2>,\n    f: F,\n) -> R\nwhere\n    F: for<'s> FnOnce(EnteredCriticalSection<'s, T1>, EnteredCriticalSection<'s, T2>) -> R,\n{\n    #[cfg(Py_GIL_DISABLED)]\n    {\n        let mut guard = CS2Guard(unsafe { std::mem::zeroed() });\n        unsafe {\n            crate::ffi::PyCriticalSection2_BeginMutex(\n                &mut guard.0,\n                &mut *m1.mutex.get(),\n                &mut *m2.mutex.get(),\n            )\n        };\n        f(\n            EnteredCriticalSection(&m1.data),\n            EnteredCriticalSection(&m2.data),\n        )\n    }\n    #[cfg(not(Py_GIL_DISABLED))]\n    {\n        f(\n            EnteredCriticalSection(&m1.data),\n            EnteredCriticalSection(&m2.data),\n        )\n    }\n}\n\n// We are building wasm Python with pthreads disabled and all these\n// tests use threads\n#[cfg(not(target_arch = \"wasm32\"))]\n#[cfg(test)]\nmod tests {\n    #[cfg(feature = \"macros\")]\n    use super::{with_critical_section, with_critical_section2};\n    #[cfg(all(not(Py_LIMITED_API), Py_3_14))]\n    use super::{with_critical_section_mutex, with_critical_section_mutex2};\n    #[cfg(all(not(Py_LIMITED_API), Py_3_14))]\n    use crate::types::PyMutex;\n    #[cfg(feature = \"macros\")]\n    use std::sync::atomic::{AtomicBool, Ordering};\n    #[cfg(any(feature = \"macros\", all(not(Py_LIMITED_API), Py_3_14)))]\n    use std::sync::Barrier;\n\n    #[cfg(feature = \"macros\")]\n    use crate::Py;\n    #[cfg(any(feature = \"macros\", all(not(Py_LIMITED_API), Py_3_14)))]\n    use crate::Python;\n\n    #[cfg(feature = \"macros\")]\n    #[crate::pyclass(crate = \"crate\")]\n    struct VecWrapper(Vec<isize>);\n\n    #[cfg(feature = \"macros\")]\n    #[crate::pyclass(crate = \"crate\")]\n    struct BoolWrapper(AtomicBool);\n\n    #[cfg(feature = \"macros\")]\n    #[test]\n    fn test_critical_section() {\n        let barrier = Barrier::new(2);\n\n        let bool_wrapper = Python::attach(|py| -> Py<BoolWrapper> {\n            Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap()\n        });\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                Python::attach(|py| {\n                    let b = bool_wrapper.bind(py);\n                    with_critical_section(b, || {\n                        barrier.wait();\n                        std::thread::sleep(std::time::Duration::from_millis(10));\n                        b.borrow().0.store(true, Ordering::Release);\n                    })\n                });\n            });\n            s.spawn(|| {\n                barrier.wait();\n                Python::attach(|py| {\n                    let b = bool_wrapper.bind(py);\n                    // this blocks until the other thread's critical section finishes\n                    with_critical_section(b, || {\n                        assert!(b.borrow().0.load(Ordering::Acquire));\n                    });\n                });\n            });\n        });\n    }\n\n    #[cfg(all(not(Py_LIMITED_API), Py_3_14))]\n    #[test]\n    fn test_critical_section_mutex() {\n        let barrier = Barrier::new(2);\n\n        let mutex = PyMutex::new(false);\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                Python::attach(|py| {\n                    with_critical_section_mutex(py, &mutex, |mut b| {\n                        barrier.wait();\n                        std::thread::sleep(std::time::Duration::from_millis(10));\n                        // SAFETY: we never call back into the python interpreter inside this critical section\n                        *(unsafe { b.get_mut() }) = true;\n                    });\n                });\n            });\n            s.spawn(|| {\n                barrier.wait();\n                Python::attach(|py| {\n                    // blocks until the other thread enters a critical section\n                    with_critical_section_mutex(py, &mutex, |b| {\n                        // SAFETY: we never call back into the python interpreter inside this critical section\n                        assert!(unsafe { *b.get() });\n                    });\n                });\n            });\n        });\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[test]\n    fn test_critical_section2() {\n        let barrier = Barrier::new(3);\n\n        let (bool_wrapper1, bool_wrapper2) = Python::attach(|py| {\n            (\n                Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap(),\n                Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap(),\n            )\n        });\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                Python::attach(|py| {\n                    let b1 = bool_wrapper1.bind(py);\n                    let b2 = bool_wrapper2.bind(py);\n                    with_critical_section2(b1, b2, || {\n                        barrier.wait();\n                        std::thread::sleep(std::time::Duration::from_millis(10));\n                        b1.borrow().0.store(true, Ordering::Release);\n                        b2.borrow().0.store(true, Ordering::Release);\n                    })\n                });\n            });\n            s.spawn(|| {\n                barrier.wait();\n                Python::attach(|py| {\n                    let b1 = bool_wrapper1.bind(py);\n                    // this blocks until the other thread's critical section finishes\n                    with_critical_section(b1, || {\n                        assert!(b1.borrow().0.load(Ordering::Acquire));\n                    });\n                });\n            });\n            s.spawn(|| {\n                barrier.wait();\n                Python::attach(|py| {\n                    let b2 = bool_wrapper2.bind(py);\n                    // this blocks until the other thread's critical section finishes\n                    with_critical_section(b2, || {\n                        assert!(b2.borrow().0.load(Ordering::Acquire));\n                    });\n                });\n            });\n        });\n    }\n\n    #[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\n    #[test]\n    fn test_critical_section_mutex2() {\n        let barrier = Barrier::new(2);\n\n        let m1 = PyMutex::new(false);\n        let m2 = PyMutex::new(false);\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                Python::attach(|py| {\n                    with_critical_section_mutex2(py, &m1, &m2, |mut b1, mut b2| {\n                        barrier.wait();\n                        std::thread::sleep(std::time::Duration::from_millis(10));\n                        // SAFETY: we never call back into the python interpreter inside this critical section\n                        unsafe { (*b1.get_mut()) = true };\n                        unsafe { (*b2.get_mut()) = true };\n                    });\n                });\n            });\n            s.spawn(|| {\n                barrier.wait();\n                Python::attach(|py| {\n                    // blocks until the other thread enters a critical section\n                    with_critical_section_mutex2(py, &m1, &m2, |b1, b2| {\n                        // SAFETY: we never call back into the python interpreter inside this critical section\n                        assert!(unsafe { *b1.get() });\n                        assert!(unsafe { *b2.get() });\n                    });\n                });\n            });\n        });\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[test]\n    fn test_critical_section2_same_object_no_deadlock() {\n        let barrier = Barrier::new(2);\n\n        let bool_wrapper = Python::attach(|py| -> Py<BoolWrapper> {\n            Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap()\n        });\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                Python::attach(|py| {\n                    let b = bool_wrapper.bind(py);\n                    with_critical_section2(b, b, || {\n                        barrier.wait();\n                        std::thread::sleep(std::time::Duration::from_millis(10));\n                        b.borrow().0.store(true, Ordering::Release);\n                    })\n                });\n            });\n            s.spawn(|| {\n                barrier.wait();\n                Python::attach(|py| {\n                    let b = bool_wrapper.bind(py);\n                    // this blocks until the other thread's critical section finishes\n                    with_critical_section(b, || {\n                        assert!(b.borrow().0.load(Ordering::Acquire));\n                    });\n                });\n            });\n        });\n    }\n\n    #[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\n    #[test]\n    fn test_critical_section_mutex2_same_object_no_deadlock() {\n        let barrier = Barrier::new(2);\n\n        let m = PyMutex::new(false);\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                Python::attach(|py| {\n                    with_critical_section_mutex2(py, &m, &m, |mut b1, b2| {\n                        barrier.wait();\n                        std::thread::sleep(std::time::Duration::from_millis(10));\n                        // SAFETY: we never call back into the python interpreter inside this critical section\n                        unsafe { (*b1.get_mut()) = true };\n                        assert!(unsafe { *b2.get() });\n                    });\n                });\n            });\n            s.spawn(|| {\n                barrier.wait();\n                Python::attach(|py| {\n                    // this blocks until the other thread's critical section finishes\n                    with_critical_section_mutex(py, &m, |b| {\n                        // SAFETY: we never call back into the python interpreter inside this critical section\n                        assert!(unsafe { *b.get() });\n                    });\n                });\n            });\n        });\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[test]\n    fn test_critical_section2_two_containers() {\n        let (vec1, vec2) = Python::attach(|py| {\n            (\n                Py::new(py, VecWrapper(vec![1, 2, 3])).unwrap(),\n                Py::new(py, VecWrapper(vec![4, 5])).unwrap(),\n            )\n        });\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                Python::attach(|py| {\n                    let v1 = vec1.bind(py);\n                    let v2 = vec2.bind(py);\n                    with_critical_section2(v1, v2, || {\n                        // v2.extend(v1)\n                        v2.borrow_mut().0.extend(v1.borrow().0.iter());\n                    })\n                });\n            });\n            s.spawn(|| {\n                Python::attach(|py| {\n                    let v1 = vec1.bind(py);\n                    let v2 = vec2.bind(py);\n                    with_critical_section2(v1, v2, || {\n                        // v1.extend(v2)\n                        v1.borrow_mut().0.extend(v2.borrow().0.iter());\n                    })\n                });\n            });\n        });\n\n        Python::attach(|py| {\n            let v1 = vec1.bind(py);\n            let v2 = vec2.bind(py);\n            // execution order is not guaranteed, so we need to check both\n            // NB: extend should be atomic, items must not be interleaved\n            // v1.extend(v2)\n            // v2.extend(v1)\n            let expected1_vec1 = vec![1, 2, 3, 4, 5];\n            let expected1_vec2 = vec![4, 5, 1, 2, 3, 4, 5];\n            // v2.extend(v1)\n            // v1.extend(v2)\n            let expected2_vec1 = vec![1, 2, 3, 4, 5, 1, 2, 3];\n            let expected2_vec2 = vec![4, 5, 1, 2, 3];\n\n            assert!(\n                (v1.borrow().0.eq(&expected1_vec1) && v2.borrow().0.eq(&expected1_vec2))\n                    || (v1.borrow().0.eq(&expected2_vec1) && v2.borrow().0.eq(&expected2_vec2))\n            );\n        });\n    }\n\n    #[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\n    #[test]\n    fn test_critical_section_mutex2_two_containers() {\n        let (m1, m2) = (PyMutex::new(vec![1, 2, 3]), PyMutex::new(vec![4, 5]));\n\n        let (m1_guard, m2_guard) = (m1.lock().unwrap(), m2.lock().unwrap());\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                Python::attach(|py| {\n                    with_critical_section_mutex2(py, &m1, &m2, |mut v1, v2| {\n                        // v1.extend(v1)\n                        // SAFETY: we never call back into the python interpreter inside this critical section\n                        let vec1 = unsafe { v1.get_mut() };\n                        let vec2 = unsafe { v2.get() };\n                        vec1.extend(vec2.iter());\n                    })\n                });\n            });\n            s.spawn(|| {\n                Python::attach(|py| {\n                    with_critical_section_mutex2(py, &m1, &m2, |v1, mut v2| {\n                        // v2.extend(v1)\n                        // SAFETY: we never call back into the python interpreter inside this critical section\n                        let vec1 = unsafe { v1.get() };\n                        let vec2 = unsafe { v2.get_mut() };\n                        vec2.extend(vec1.iter());\n                    })\n                });\n            });\n            // the other threads waiting for locks should not block this attach\n            Python::attach(|_| {\n                // On the free-threaded build, the critical sections should have blocked\n                // the other threads from modification.\n                #[cfg(Py_GIL_DISABLED)]\n                {\n                    assert_eq!(&*m1_guard, &[1, 2, 3]);\n                    assert_eq!(&*m2_guard, &[4, 5]);\n                }\n            });\n            drop(m1_guard);\n            drop(m2_guard);\n        });\n\n        // execution order is not guaranteed, so we need to check both\n        // NB: extend should be atomic, items must not be interleaved\n        // v1.extend(v2)\n        // v2.extend(v1)\n        let expected1_vec1 = vec![1, 2, 3, 4, 5];\n        let expected1_vec2 = vec![4, 5, 1, 2, 3, 4, 5];\n        // v2.extend(v1)\n        // v1.extend(v2)\n        let expected2_vec1 = vec![1, 2, 3, 4, 5, 1, 2, 3];\n        let expected2_vec2 = vec![4, 5, 1, 2, 3];\n\n        let v1 = m1.lock().unwrap();\n        let v2 = m2.lock().unwrap();\n        assert!(\n            (&*v1, &*v2) == (&expected1_vec1, &expected1_vec2)\n                || (&*v1, &*v2) == (&expected2_vec1, &expected2_vec2)\n        );\n    }\n}\n"
  },
  {
    "path": "src/sync/once_lock.rs",
    "content": "use crate::{\n    internal::state::SuspendAttach, types::any::PyAnyMethods, Bound, Py, PyResult, PyTypeCheck,\n    Python,\n};\n\n/// An equivalent to [`std::sync::OnceLock`] for initializing objects while attached to\n/// the Python interpreter.\n///\n/// Unlike `OnceLock<T>`, this type will not deadlock with the interpreter.\n/// Before blocking calls the cell will detach from the runtime and then\n/// re-attach once the cell is unblocked.\n///\n/// # Re-entrant initialization\n///\n/// Like `OnceLock<T>`, it is an error to re-entrantly initialize a `PyOnceLock<T>`. The exact\n/// behavior in this case is not guaranteed, it may either deadlock or panic.\n///\n/// # Examples\n///\n/// The following example shows how to use `PyOnceLock` to share a reference to a Python list\n/// between threads:\n///\n/// ```\n/// use pyo3::sync::PyOnceLock;\n/// use pyo3::prelude::*;\n/// use pyo3::types::PyList;\n///\n/// static LIST_CELL: PyOnceLock<Py<PyList>> = PyOnceLock::new();\n///\n/// pub fn get_shared_list(py: Python<'_>) -> &Bound<'_, PyList> {\n///     LIST_CELL\n///         .get_or_init(py, || PyList::empty(py).unbind())\n///         .bind(py)\n/// }\n/// # Python::attach(|py| assert_eq!(get_shared_list(py).len(), 0));\n/// ```\n#[derive(Default)]\npub struct PyOnceLock<T> {\n    inner: once_cell::sync::OnceCell<T>,\n}\n\nimpl<T> PyOnceLock<T> {\n    /// Create a `PyOnceLock` which does not yet contain a value.\n    pub const fn new() -> Self {\n        Self {\n            inner: once_cell::sync::OnceCell::new(),\n        }\n    }\n\n    /// Get a reference to the contained value, or `None` if the cell has not yet been written.\n    #[inline]\n    pub fn get(&self, _py: Python<'_>) -> Option<&T> {\n        self.inner.get()\n    }\n\n    /// Get a reference to the contained value, initializing it if needed using the provided\n    /// closure.\n    ///\n    /// See the type-level documentation for detail on re-entrancy and concurrent initialization.\n    #[inline]\n    pub fn get_or_init<F>(&self, py: Python<'_>, f: F) -> &T\n    where\n        F: FnOnce() -> T,\n    {\n        self.inner\n            .get()\n            .unwrap_or_else(|| init_once_cell_py_attached(&self.inner, py, f))\n    }\n\n    /// Like `get_or_init`, but accepts a fallible initialization function. If it fails, the cell\n    /// is left uninitialized.\n    ///\n    /// See the type-level documentation for detail on re-entrancy and concurrent initialization.\n    pub fn get_or_try_init<F, E>(&self, py: Python<'_>, f: F) -> Result<&T, E>\n    where\n        F: FnOnce() -> Result<T, E>,\n    {\n        self.inner\n            .get()\n            .map_or_else(|| try_init_once_cell_py_attached(&self.inner, py, f), Ok)\n    }\n\n    /// Get the contents of the cell mutably. This is only possible if the reference to the cell is\n    /// unique.\n    pub fn get_mut(&mut self) -> Option<&mut T> {\n        self.inner.get_mut()\n    }\n\n    /// Set the value in the cell.\n    ///\n    /// If the cell has already been written, `Err(value)` will be returned containing the new\n    /// value which was not written.\n    pub fn set(&self, _py: Python<'_>, value: T) -> Result<(), T> {\n        self.inner.set(value)\n    }\n\n    /// Takes the value out of the cell, moving it back to an uninitialized state.\n    ///\n    /// Has no effect and returns None if the cell has not yet been written.\n    pub fn take(&mut self) -> Option<T> {\n        self.inner.take()\n    }\n\n    /// Consumes the cell, returning the wrapped value.\n    ///\n    /// Returns None if the cell has not yet been written.\n    pub fn into_inner(self) -> Option<T> {\n        self.inner.into_inner()\n    }\n}\n\nimpl<T> PyOnceLock<Py<T>> {\n    /// Creates a new cell that contains a new Python reference to the same contained object.\n    ///\n    /// Returns an uninitialized cell if `self` has not yet been initialized.\n    pub fn clone_ref(&self, py: Python<'_>) -> Self {\n        let cloned = PyOnceLock::new();\n        if let Some(value) = self.get(py) {\n            let _ = cloned.set(py, value.clone_ref(py));\n        }\n        cloned\n    }\n}\n\nimpl<T> PyOnceLock<Py<T>>\nwhere\n    T: PyTypeCheck,\n{\n    /// This is a shorthand method for `get_or_init` which imports the type from Python on init.\n    ///\n    /// # Example: Using `PyOnceLock` to store a class in a static variable.\n    ///\n    /// `PyOnceLock` can be used to avoid importing a class multiple times:\n    /// ```\n    /// # use pyo3::prelude::*;\n    /// # use pyo3::sync::PyOnceLock;\n    /// # use pyo3::types::{PyDict, PyType};\n    /// # use pyo3::intern;\n    /// #\n    /// #[pyfunction]\n    /// fn create_ordered_dict<'py>(py: Python<'py>, dict: Bound<'py, PyDict>) -> PyResult<Bound<'py, PyAny>> {\n    ///     // Even if this function is called multiple times,\n    ///     // the `OrderedDict` class will be imported only once.\n    ///     static ORDERED_DICT: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n    ///     ORDERED_DICT\n    ///         .import(py, \"collections\", \"OrderedDict\")?\n    ///         .call1((dict,))\n    /// }\n    ///\n    /// # Python::attach(|py| {\n    /// #     let dict = PyDict::new(py);\n    /// #     dict.set_item(intern!(py, \"foo\"), 42).unwrap();\n    /// #     let fun = wrap_pyfunction!(create_ordered_dict, py).unwrap();\n    /// #     let ordered_dict = fun.call1((&dict,)).unwrap();\n    /// #     assert!(dict.eq(ordered_dict).unwrap());\n    /// # });\n    /// ```\n    pub fn import<'py>(\n        &self,\n        py: Python<'py>,\n        module_name: &str,\n        attr_name: &str,\n    ) -> PyResult<&Bound<'py, T>> {\n        self.get_or_try_init(py, || {\n            let type_object = py.import(module_name)?.getattr(attr_name)?.cast_into()?;\n            Ok(type_object.unbind())\n        })\n        .map(|ty| ty.bind(py))\n    }\n}\n\n#[cold]\nfn init_once_cell_py_attached<'a, F, T>(\n    cell: &'a once_cell::sync::OnceCell<T>,\n    _py: Python<'_>,\n    f: F,\n) -> &'a T\nwhere\n    F: FnOnce() -> T,\n{\n    // SAFETY: detach from the runtime right before a possibly blocking call\n    // then reattach when the blocking call completes and before calling\n    // into the C API.\n    let ts_guard = unsafe { SuspendAttach::new() };\n\n    // By having detached here, we guarantee that `.get_or_init` cannot deadlock with\n    // the Python interpreter\n    cell.get_or_init(move || {\n        drop(ts_guard);\n        f()\n    })\n}\n\n#[cold]\nfn try_init_once_cell_py_attached<'a, F, T, E>(\n    cell: &'a once_cell::sync::OnceCell<T>,\n    _py: Python<'_>,\n    f: F,\n) -> Result<&'a T, E>\nwhere\n    F: FnOnce() -> Result<T, E>,\n{\n    // SAFETY: detach from the runtime right before a possibly blocking call\n    // then reattach when the blocking call completes and before calling\n    // into the C API.\n    let ts_guard = unsafe { SuspendAttach::new() };\n\n    // By having detached here, we guarantee that `.get_or_init` cannot deadlock with\n    // the Python interpreter\n    cell.get_or_try_init(move || {\n        drop(ts_guard);\n        f()\n    })\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_once_cell() {\n        Python::attach(|py| {\n            let mut cell = PyOnceLock::new();\n\n            assert!(cell.get(py).is_none());\n\n            assert_eq!(cell.get_or_try_init(py, || Err(5)), Err(5));\n            assert!(cell.get(py).is_none());\n\n            assert_eq!(cell.get_or_try_init(py, || Ok::<_, ()>(2)), Ok(&2));\n            assert_eq!(cell.get(py), Some(&2));\n\n            assert_eq!(cell.get_or_try_init(py, || Err(5)), Ok(&2));\n\n            assert_eq!(cell.take(), Some(2));\n            assert_eq!(cell.into_inner(), None);\n\n            let cell_py = PyOnceLock::new();\n            assert!(cell_py.clone_ref(py).get(py).is_none());\n            cell_py.get_or_init(py, || py.None());\n            assert!(cell_py.clone_ref(py).get(py).unwrap().is_none(py));\n        })\n    }\n\n    #[test]\n    fn test_once_cell_drop() {\n        #[derive(Debug)]\n        struct RecordDrop<'a>(&'a mut bool);\n\n        impl Drop for RecordDrop<'_> {\n            fn drop(&mut self) {\n                *self.0 = true;\n            }\n        }\n\n        Python::attach(|py| {\n            let mut dropped = false;\n            let cell = PyOnceLock::new();\n            cell.set(py, RecordDrop(&mut dropped)).unwrap();\n            let drop_container = cell.get(py).unwrap();\n\n            assert!(!*drop_container.0);\n            drop(cell);\n            assert!(dropped);\n        });\n    }\n}\n"
  },
  {
    "path": "src/sync.rs",
    "content": "//! Synchronization mechanisms which are aware of the existence of the Python interpreter.\n//!\n//! The Python interpreter has multiple \"stop the world\" situations which may block threads, such as\n//! - The Python global interpreter lock (GIL), on GIL-enabled builds of Python, or\n//! - The Python garbage collector (GC), which pauses attached threads during collection.\n//!\n//! To avoid deadlocks in these cases, threads should take care to be detached from the Python interpreter\n//! before performing operations which might block waiting for other threads attached to the Python\n//! interpreter.\n//!\n//! This module provides synchronization primitives which are able to synchronize under these conditions.\nuse crate::{\n    internal::state::SuspendAttach,\n    sealed::Sealed,\n    types::{PyAny, PyString},\n    Bound, Py, Python,\n};\nuse std::{\n    cell::UnsafeCell,\n    marker::PhantomData,\n    mem::MaybeUninit,\n    sync::{Once, OnceState},\n};\n\npub mod critical_section;\npub(crate) mod once_lock;\n\n/// Deprecated alias for [`pyo3::sync::critical_section::with_critical_section`][crate::sync::critical_section::with_critical_section]\n#[deprecated(\n    since = \"0.28.0\",\n    note = \"use pyo3::sync::critical_section::with_critical_section instead\"\n)]\npub fn with_critical_section<F, R>(object: &Bound<'_, PyAny>, f: F) -> R\nwhere\n    F: FnOnce() -> R,\n{\n    crate::sync::critical_section::with_critical_section(object, f)\n}\n\n/// Deprecated alias for [`pyo3::sync::critical_section::with_critical_section2`][crate::sync::critical_section::with_critical_section2]\n#[deprecated(\n    since = \"0.28.0\",\n    note = \"use pyo3::sync::critical_section::with_critical_section2 instead\"\n)]\npub fn with_critical_section2<F, R>(a: &Bound<'_, PyAny>, b: &Bound<'_, PyAny>, f: F) -> R\nwhere\n    F: FnOnce() -> R,\n{\n    crate::sync::critical_section::with_critical_section2(a, b, f)\n}\npub use self::once_lock::PyOnceLock;\n\n#[deprecated(\n    since = \"0.26.0\",\n    note = \"Now internal only, to be removed after https://github.com/PyO3/pyo3/pull/5341\"\n)]\npub(crate) struct GILOnceCell<T> {\n    once: Once,\n    data: UnsafeCell<MaybeUninit<T>>,\n\n    /// (Copied from std::sync::OnceLock)\n    ///\n    /// `PhantomData` to make sure dropck understands we're dropping T in our Drop impl.\n    ///\n    /// ```compile_error,E0597\n    /// #![allow(deprecated)]\n    /// use pyo3::Python;\n    /// use pyo3::sync::GILOnceCell;\n    ///\n    /// struct A<'a>(#[allow(dead_code)] &'a str);\n    ///\n    /// impl<'a> Drop for A<'a> {\n    ///     fn drop(&mut self) {}\n    /// }\n    ///\n    /// let cell = GILOnceCell::new();\n    /// {\n    ///     let s = String::new();\n    ///     let _ = Python::attach(|py| cell.set(py,A(&s)));\n    /// }\n    /// ```\n    _marker: PhantomData<T>,\n}\n\n#[allow(deprecated)]\nimpl<T> Default for GILOnceCell<T> {\n    fn default() -> Self {\n        Self::new()\n    }\n}\n\n// T: Send is needed for Sync because the thread which drops the GILOnceCell can be different\n// to the thread which fills it. (e.g. think scoped thread which fills the cell and then exits,\n// leaving the cell to be dropped by the main thread).\n#[allow(deprecated)]\nunsafe impl<T: Send + Sync> Sync for GILOnceCell<T> {}\n#[allow(deprecated)]\nunsafe impl<T: Send> Send for GILOnceCell<T> {}\n\n#[allow(deprecated)]\nimpl<T> GILOnceCell<T> {\n    /// Create a `GILOnceCell` which does not yet contain a value.\n    pub const fn new() -> Self {\n        Self {\n            once: Once::new(),\n            data: UnsafeCell::new(MaybeUninit::uninit()),\n            _marker: PhantomData,\n        }\n    }\n\n    /// Get a reference to the contained value, or `None` if the cell has not yet been written.\n    #[inline]\n    pub fn get(&self, _py: Python<'_>) -> Option<&T> {\n        if self.once.is_completed() {\n            // SAFETY: the cell has been written.\n            Some(unsafe { (*self.data.get()).assume_init_ref() })\n        } else {\n            None\n        }\n    }\n\n    /// Like `get_or_init`, but accepts a fallible initialization function. If it fails, the cell\n    /// is left uninitialized.\n    ///\n    /// See the type-level documentation for detail on re-entrancy and concurrent initialization.\n    #[inline]\n    pub fn get_or_try_init<F, E>(&self, py: Python<'_>, f: F) -> Result<&T, E>\n    where\n        F: FnOnce() -> Result<T, E>,\n    {\n        if let Some(value) = self.get(py) {\n            return Ok(value);\n        }\n\n        self.init(py, f)\n    }\n\n    #[cold]\n    fn init<F, E>(&self, py: Python<'_>, f: F) -> Result<&T, E>\n    where\n        F: FnOnce() -> Result<T, E>,\n    {\n        // Note that f() could temporarily release the GIL, so it's possible that another thread\n        // writes to this GILOnceCell before f() finishes. That's fine; we'll just have to discard\n        // the value computed here and accept a bit of wasted computation.\n\n        // TODO: on the freethreaded build, consider wrapping this pair of operations in a\n        // critical section (requires a critical section API which can use a PyMutex without\n        // an object.)\n        let value = f()?;\n        let _ = self.set(py, value);\n\n        Ok(self.get(py).unwrap())\n    }\n\n    /// Set the value in the cell.\n    ///\n    /// If the cell has already been written, `Err(value)` will be returned containing the new\n    /// value which was not written.\n    pub fn set(&self, _py: Python<'_>, value: T) -> Result<(), T> {\n        let mut value = Some(value);\n        // NB this can block, but since this is only writing a single value and\n        // does not call arbitrary python code, we don't need to worry about\n        // deadlocks with the GIL.\n        self.once.call_once_force(|_| {\n            // SAFETY: no other threads can be writing this value, because we are\n            // inside the `call_once_force` closure.\n            unsafe {\n                // `.take().unwrap()` will never panic\n                (*self.data.get()).write(value.take().unwrap());\n            }\n        });\n\n        match value {\n            // Some other thread wrote to the cell first\n            Some(value) => Err(value),\n            None => Ok(()),\n        }\n    }\n}\n\n#[allow(deprecated)]\nimpl<T> Drop for GILOnceCell<T> {\n    fn drop(&mut self) {\n        if self.once.is_completed() {\n            // SAFETY: the cell has been written.\n            unsafe { MaybeUninit::assume_init_drop(self.data.get_mut()) }\n        }\n    }\n}\n\n/// Interns `text` as a Python string and stores a reference to it in static storage.\n///\n/// A reference to the same Python string is returned on each invocation.\n///\n/// # Example: Using `intern!` to avoid needlessly recreating the same Python string\n///\n/// ```\n/// use pyo3::intern;\n/// # use pyo3::{prelude::*, types::PyDict};\n///\n/// #[pyfunction]\n/// fn create_dict(py: Python<'_>) -> PyResult<Bound<'_, PyDict>> {\n///     let dict = PyDict::new(py);\n///     //             👇 A new `PyString` is created\n///     //                for every call of this function.\n///     dict.set_item(\"foo\", 42)?;\n///     Ok(dict)\n/// }\n///\n/// #[pyfunction]\n/// fn create_dict_faster(py: Python<'_>) -> PyResult<Bound<'_, PyDict>> {\n///     let dict = PyDict::new(py);\n///     //               👇 A `PyString` is created once and reused\n///     //                  for the lifetime of the program.\n///     dict.set_item(intern!(py, \"foo\"), 42)?;\n///     Ok(dict)\n/// }\n/// #\n/// # Python::attach(|py| {\n/// #     let fun_slow = wrap_pyfunction!(create_dict, py).unwrap();\n/// #     let dict = fun_slow.call0().unwrap();\n/// #     assert!(dict.contains(\"foo\").unwrap());\n/// #     let fun = wrap_pyfunction!(create_dict_faster, py).unwrap();\n/// #     let dict = fun.call0().unwrap();\n/// #     assert!(dict.contains(\"foo\").unwrap());\n/// # });\n/// ```\n#[macro_export]\nmacro_rules! intern {\n    ($py: expr, $text: expr) => {{\n        static INTERNED: $crate::sync::Interned = $crate::sync::Interned::new($text);\n        INTERNED.get($py)\n    }};\n}\n\n/// Implementation detail for `intern!` macro.\n#[doc(hidden)]\npub struct Interned(&'static str, PyOnceLock<Py<PyString>>);\n\nimpl Interned {\n    /// Creates an empty holder for an interned `str`.\n    pub const fn new(value: &'static str) -> Self {\n        Interned(value, PyOnceLock::new())\n    }\n\n    /// Gets or creates the interned `str` value.\n    #[inline]\n    pub fn get<'py>(&self, py: Python<'py>) -> &Bound<'py, PyString> {\n        self.1\n            .get_or_init(py, || PyString::intern(py, self.0).into())\n            .bind(py)\n    }\n}\n\n/// Extension trait for [`Once`] to help avoid deadlocking when using a [`Once`] when attached to a\n/// Python thread.\npub trait OnceExt: Sealed {\n    ///The state of `Once`\n    type OnceState;\n\n    /// Similar to [`call_once`][Once::call_once], but releases the Python GIL temporarily\n    /// if blocking on another thread currently calling this `Once`.\n    fn call_once_py_attached(&self, py: Python<'_>, f: impl FnOnce());\n\n    /// Similar to [`call_once_force`][Once::call_once_force], but releases the Python GIL\n    /// temporarily if blocking on another thread currently calling this `Once`.\n    fn call_once_force_py_attached(&self, py: Python<'_>, f: impl FnOnce(&Self::OnceState));\n}\n\n/// Extension trait for [`std::sync::OnceLock`] which helps avoid deadlocks between the Python\n/// interpreter and initialization with the `OnceLock`.\npub trait OnceLockExt<T>: once_lock_ext_sealed::Sealed {\n    /// Initializes this `OnceLock` with the given closure if it has not been initialized yet.\n    ///\n    /// If this function would block, this function detaches from the Python interpreter and\n    /// reattaches before calling `f`. This avoids deadlocks between the Python interpreter and\n    /// the `OnceLock` in cases where `f` can call arbitrary Python code, as calling arbitrary\n    /// Python code can lead to `f` itself blocking on the Python interpreter.\n    ///\n    /// By detaching from the Python interpreter before blocking, this ensures that if `f` blocks\n    /// then the Python interpreter cannot be blocked by `f` itself.\n    fn get_or_init_py_attached<F>(&self, py: Python<'_>, f: F) -> &T\n    where\n        F: FnOnce() -> T;\n}\n\n/// Extension trait for [`std::sync::Mutex`] which helps avoid deadlocks between\n/// the Python interpreter and acquiring the `Mutex`.\npub trait MutexExt<T>: Sealed {\n    /// The result type returned by the `lock_py_attached` method.\n    type LockResult<'a>\n    where\n        Self: 'a;\n\n    /// Lock this `Mutex` in a manner that cannot deadlock with the Python interpreter.\n    ///\n    /// Before attempting to lock the mutex, this function detaches from the\n    /// Python runtime. When the lock is acquired, it re-attaches to the Python\n    /// runtime before returning the `LockResult`. This avoids deadlocks between\n    /// the GIL and other global synchronization events triggered by the Python\n    /// interpreter.\n    fn lock_py_attached(&self, py: Python<'_>) -> Self::LockResult<'_>;\n}\n\n/// Extension trait for [`std::sync::RwLock`] which helps avoid deadlocks between\n/// the Python interpreter and acquiring the `RwLock`.\npub trait RwLockExt<T>: rwlock_ext_sealed::Sealed {\n    /// The result type returned by the `read_py_attached` method.\n    type ReadLockResult<'a>\n    where\n        Self: 'a;\n\n    /// The result type returned by the `write_py_attached` method.\n    type WriteLockResult<'a>\n    where\n        Self: 'a;\n\n    /// Lock this `RwLock` for reading in a manner that cannot deadlock with\n    /// the Python interpreter.\n    ///\n    /// Before attempting to lock the rwlock, this function detaches from the\n    /// Python runtime. When the lock is acquired, it re-attaches to the Python\n    /// runtime before returning the `ReadLockResult`. This avoids deadlocks between\n    /// the GIL and other global synchronization events triggered by the Python\n    /// interpreter.\n    fn read_py_attached(&self, py: Python<'_>) -> Self::ReadLockResult<'_>;\n\n    /// Lock this `RwLock` for writing in a manner that cannot deadlock with\n    /// the Python interpreter.\n    ///\n    /// Before attempting to lock the rwlock, this function detaches from the\n    /// Python runtime. When the lock is acquired, it re-attaches to the Python\n    /// runtime before returning the `WriteLockResult`. This avoids deadlocks between\n    /// the GIL and other global synchronization events triggered by the Python\n    /// interpreter.\n    fn write_py_attached(&self, py: Python<'_>) -> Self::WriteLockResult<'_>;\n}\n\nimpl OnceExt for Once {\n    type OnceState = OnceState;\n\n    fn call_once_py_attached(&self, py: Python<'_>, f: impl FnOnce()) {\n        if self.is_completed() {\n            return;\n        }\n\n        init_once_py_attached(self, py, f)\n    }\n\n    fn call_once_force_py_attached(&self, py: Python<'_>, f: impl FnOnce(&OnceState)) {\n        if self.is_completed() {\n            return;\n        }\n\n        init_once_force_py_attached(self, py, f);\n    }\n}\n\n#[cfg(feature = \"parking_lot\")]\nimpl OnceExt for parking_lot::Once {\n    type OnceState = parking_lot::OnceState;\n\n    fn call_once_py_attached(&self, _py: Python<'_>, f: impl FnOnce()) {\n        if self.state().done() {\n            return;\n        }\n\n        let ts_guard = unsafe { SuspendAttach::new() };\n\n        self.call_once(move || {\n            drop(ts_guard);\n            f();\n        });\n    }\n\n    fn call_once_force_py_attached(\n        &self,\n        _py: Python<'_>,\n        f: impl FnOnce(&parking_lot::OnceState),\n    ) {\n        if self.state().done() {\n            return;\n        }\n\n        let ts_guard = unsafe { SuspendAttach::new() };\n\n        self.call_once_force(move |state| {\n            drop(ts_guard);\n            f(&state);\n        });\n    }\n}\n\nimpl<T> OnceLockExt<T> for std::sync::OnceLock<T> {\n    fn get_or_init_py_attached<F>(&self, py: Python<'_>, f: F) -> &T\n    where\n        F: FnOnce() -> T,\n    {\n        // Use self.get() first to create a fast path when initialized\n        self.get()\n            .unwrap_or_else(|| init_once_lock_py_attached(self, py, f))\n    }\n}\n\nimpl<T> MutexExt<T> for std::sync::Mutex<T> {\n    type LockResult<'a>\n        = std::sync::LockResult<std::sync::MutexGuard<'a, T>>\n    where\n        Self: 'a;\n\n    fn lock_py_attached(\n        &self,\n        _py: Python<'_>,\n    ) -> std::sync::LockResult<std::sync::MutexGuard<'_, T>> {\n        // If try_lock is successful or returns a poisoned mutex, return them so\n        // the caller can deal with them. Otherwise we need to use blocking\n        // lock, which requires detaching from the Python runtime to avoid\n        // possible deadlocks.\n        match self.try_lock() {\n            Ok(inner) => return Ok(inner),\n            Err(std::sync::TryLockError::Poisoned(inner)) => {\n                return std::sync::LockResult::Err(inner)\n            }\n            Err(std::sync::TryLockError::WouldBlock) => {}\n        }\n        // SAFETY: detach from the runtime right before a possibly blocking call\n        // then reattach when the blocking call completes and before calling\n        // into the C API.\n        let ts_guard = unsafe { SuspendAttach::new() };\n        let res = self.lock();\n        drop(ts_guard);\n        res\n    }\n}\n\n#[cfg(feature = \"lock_api\")]\nimpl<R: lock_api::RawMutex, T> MutexExt<T> for lock_api::Mutex<R, T> {\n    type LockResult<'a>\n        = lock_api::MutexGuard<'a, R, T>\n    where\n        Self: 'a;\n\n    fn lock_py_attached(&self, _py: Python<'_>) -> lock_api::MutexGuard<'_, R, T> {\n        if let Some(guard) = self.try_lock() {\n            return guard;\n        }\n\n        let ts_guard = unsafe { SuspendAttach::new() };\n        let res = self.lock();\n        drop(ts_guard);\n        res\n    }\n}\n\n#[cfg(feature = \"arc_lock\")]\nimpl<R, T> MutexExt<T> for std::sync::Arc<lock_api::Mutex<R, T>>\nwhere\n    R: lock_api::RawMutex,\n{\n    type LockResult<'a>\n        = lock_api::ArcMutexGuard<R, T>\n    where\n        Self: 'a;\n\n    fn lock_py_attached(&self, _py: Python<'_>) -> lock_api::ArcMutexGuard<R, T> {\n        if let Some(guard) = self.try_lock_arc() {\n            return guard;\n        }\n\n        let ts_guard = unsafe { SuspendAttach::new() };\n        let res = self.lock_arc();\n        drop(ts_guard);\n        res\n    }\n}\n\n#[cfg(feature = \"lock_api\")]\nimpl<R, G, T> MutexExt<T> for lock_api::ReentrantMutex<R, G, T>\nwhere\n    R: lock_api::RawMutex,\n    G: lock_api::GetThreadId,\n{\n    type LockResult<'a>\n        = lock_api::ReentrantMutexGuard<'a, R, G, T>\n    where\n        Self: 'a;\n\n    fn lock_py_attached(&self, _py: Python<'_>) -> lock_api::ReentrantMutexGuard<'_, R, G, T> {\n        if let Some(guard) = self.try_lock() {\n            return guard;\n        }\n\n        let ts_guard = unsafe { SuspendAttach::new() };\n        let res = self.lock();\n        drop(ts_guard);\n        res\n    }\n}\n\n#[cfg(feature = \"arc_lock\")]\nimpl<R, G, T> MutexExt<T> for std::sync::Arc<lock_api::ReentrantMutex<R, G, T>>\nwhere\n    R: lock_api::RawMutex,\n    G: lock_api::GetThreadId,\n{\n    type LockResult<'a>\n        = lock_api::ArcReentrantMutexGuard<R, G, T>\n    where\n        Self: 'a;\n\n    fn lock_py_attached(&self, _py: Python<'_>) -> lock_api::ArcReentrantMutexGuard<R, G, T> {\n        if let Some(guard) = self.try_lock_arc() {\n            return guard;\n        }\n\n        let ts_guard = unsafe { SuspendAttach::new() };\n        let res = self.lock_arc();\n        drop(ts_guard);\n        res\n    }\n}\n\nimpl<T> RwLockExt<T> for std::sync::RwLock<T> {\n    type ReadLockResult<'a>\n        = std::sync::LockResult<std::sync::RwLockReadGuard<'a, T>>\n    where\n        Self: 'a;\n\n    type WriteLockResult<'a>\n        = std::sync::LockResult<std::sync::RwLockWriteGuard<'a, T>>\n    where\n        Self: 'a;\n\n    fn read_py_attached(&self, _py: Python<'_>) -> Self::ReadLockResult<'_> {\n        // If try_read is successful or returns a poisoned rwlock, return them so\n        // the caller can deal with them. Otherwise we need to use blocking\n        // read lock, which requires detaching from the Python runtime to avoid\n        // possible deadlocks.\n        match self.try_read() {\n            Ok(inner) => return Ok(inner),\n            Err(std::sync::TryLockError::Poisoned(inner)) => {\n                return std::sync::LockResult::Err(inner)\n            }\n            Err(std::sync::TryLockError::WouldBlock) => {}\n        }\n\n        // SAFETY: detach from the runtime right before a possibly blocking call\n        // then reattach when the blocking call completes and before calling\n        // into the C API.\n        let ts_guard = unsafe { SuspendAttach::new() };\n\n        let res = self.read();\n        drop(ts_guard);\n        res\n    }\n\n    fn write_py_attached(&self, _py: Python<'_>) -> Self::WriteLockResult<'_> {\n        // If try_write is successful or returns a poisoned rwlock, return them so\n        // the caller can deal with them. Otherwise we need to use blocking\n        // write lock, which requires detaching from the Python runtime to avoid\n        // possible deadlocks.\n        match self.try_write() {\n            Ok(inner) => return Ok(inner),\n            Err(std::sync::TryLockError::Poisoned(inner)) => {\n                return std::sync::LockResult::Err(inner)\n            }\n            Err(std::sync::TryLockError::WouldBlock) => {}\n        }\n\n        // SAFETY: detach from the runtime right before a possibly blocking call\n        // then reattach when the blocking call completes and before calling\n        // into the C API.\n        let ts_guard = unsafe { SuspendAttach::new() };\n\n        let res = self.write();\n        drop(ts_guard);\n        res\n    }\n}\n\n#[cfg(feature = \"lock_api\")]\nimpl<R: lock_api::RawRwLock, T> RwLockExt<T> for lock_api::RwLock<R, T> {\n    type ReadLockResult<'a>\n        = lock_api::RwLockReadGuard<'a, R, T>\n    where\n        Self: 'a;\n\n    type WriteLockResult<'a>\n        = lock_api::RwLockWriteGuard<'a, R, T>\n    where\n        Self: 'a;\n\n    fn read_py_attached(&self, _py: Python<'_>) -> Self::ReadLockResult<'_> {\n        if let Some(guard) = self.try_read() {\n            return guard;\n        }\n\n        let ts_guard = unsafe { SuspendAttach::new() };\n        let res = self.read();\n        drop(ts_guard);\n        res\n    }\n\n    fn write_py_attached(&self, _py: Python<'_>) -> Self::WriteLockResult<'_> {\n        if let Some(guard) = self.try_write() {\n            return guard;\n        }\n\n        let ts_guard = unsafe { SuspendAttach::new() };\n        let res = self.write();\n        drop(ts_guard);\n        res\n    }\n}\n\n#[cfg(feature = \"arc_lock\")]\nimpl<R, T> RwLockExt<T> for std::sync::Arc<lock_api::RwLock<R, T>>\nwhere\n    R: lock_api::RawRwLock,\n{\n    type ReadLockResult<'a>\n        = lock_api::ArcRwLockReadGuard<R, T>\n    where\n        Self: 'a;\n\n    type WriteLockResult<'a>\n        = lock_api::ArcRwLockWriteGuard<R, T>\n    where\n        Self: 'a;\n\n    fn read_py_attached(&self, _py: Python<'_>) -> Self::ReadLockResult<'_> {\n        if let Some(guard) = self.try_read_arc() {\n            return guard;\n        }\n\n        let ts_guard = unsafe { SuspendAttach::new() };\n        let res = self.read_arc();\n        drop(ts_guard);\n        res\n    }\n\n    fn write_py_attached(&self, _py: Python<'_>) -> Self::WriteLockResult<'_> {\n        if let Some(guard) = self.try_write_arc() {\n            return guard;\n        }\n\n        let ts_guard = unsafe { SuspendAttach::new() };\n        let res = self.write_arc();\n        drop(ts_guard);\n        res\n    }\n}\n\n#[cold]\nfn init_once_py_attached<F, T>(once: &Once, _py: Python<'_>, f: F)\nwhere\n    F: FnOnce() -> T,\n{\n    // SAFETY: detach from the runtime right before a possibly blocking call\n    // then reattach when the blocking call completes and before calling\n    // into the C API.\n    let ts_guard = unsafe { SuspendAttach::new() };\n\n    once.call_once(move || {\n        drop(ts_guard);\n        f();\n    });\n}\n\n#[cold]\nfn init_once_force_py_attached<F, T>(once: &Once, _py: Python<'_>, f: F)\nwhere\n    F: FnOnce(&OnceState) -> T,\n{\n    // SAFETY: detach from the runtime right before a possibly blocking call\n    // then reattach when the blocking call completes and before calling\n    // into the C API.\n    let ts_guard = unsafe { SuspendAttach::new() };\n\n    once.call_once_force(move |state| {\n        drop(ts_guard);\n        f(state);\n    });\n}\n\n#[cold]\nfn init_once_lock_py_attached<'a, F, T>(\n    lock: &'a std::sync::OnceLock<T>,\n    _py: Python<'_>,\n    f: F,\n) -> &'a T\nwhere\n    F: FnOnce() -> T,\n{\n    // SAFETY: detach from the runtime right before a possibly blocking call\n    // then reattach when the blocking call completes and before calling\n    // into the C API.\n    let ts_guard = unsafe { SuspendAttach::new() };\n\n    // By having detached here, we guarantee that `.get_or_init` cannot deadlock with\n    // the Python interpreter\n    let value = lock.get_or_init(move || {\n        drop(ts_guard);\n        f()\n    });\n\n    value\n}\n\nmod once_lock_ext_sealed {\n    pub trait Sealed {}\n    impl<T> Sealed for std::sync::OnceLock<T> {}\n}\n\nmod rwlock_ext_sealed {\n    pub trait Sealed {}\n    impl<T> Sealed for std::sync::RwLock<T> {}\n    #[cfg(feature = \"lock_api\")]\n    impl<R, T> Sealed for lock_api::RwLock<R, T> {}\n    #[cfg(feature = \"arc_lock\")]\n    impl<R, T> Sealed for std::sync::Arc<lock_api::RwLock<R, T>> {}\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    use crate::types::{PyAnyMethods, PyDict, PyDictMethods};\n    #[cfg(not(target_arch = \"wasm32\"))]\n    #[cfg(feature = \"macros\")]\n    use std::sync::atomic::{AtomicBool, Ordering};\n    #[cfg(not(target_arch = \"wasm32\"))]\n    #[cfg(feature = \"macros\")]\n    use std::sync::Barrier;\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use std::sync::Mutex;\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    #[cfg(feature = \"macros\")]\n    #[crate::pyclass(crate = \"crate\")]\n    struct BoolWrapper(AtomicBool);\n\n    #[test]\n    fn test_intern() {\n        Python::attach(|py| {\n            let foo1 = \"foo\";\n            let foo2 = intern!(py, \"foo\");\n            let foo3 = intern!(py, stringify!(foo));\n\n            let dict = PyDict::new(py);\n            dict.set_item(foo1, 42_usize).unwrap();\n            assert!(dict.contains(foo2).unwrap());\n            assert_eq!(\n                dict.get_item(foo3)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<usize>()\n                    .unwrap(),\n                42\n            );\n        });\n    }\n\n    #[test]\n    #[allow(deprecated)]\n    fn test_once_cell() {\n        Python::attach(|py| {\n            let cell = GILOnceCell::new();\n\n            assert!(cell.get(py).is_none());\n\n            assert_eq!(cell.get_or_try_init(py, || Err(5)), Err(5));\n            assert!(cell.get(py).is_none());\n\n            assert_eq!(cell.get_or_try_init(py, || Ok::<_, ()>(2)), Ok(&2));\n            assert_eq!(cell.get(py), Some(&2));\n\n            assert_eq!(cell.get_or_try_init(py, || Err(5)), Ok(&2));\n        })\n    }\n\n    #[test]\n    #[allow(deprecated)]\n    fn test_once_cell_drop() {\n        #[derive(Debug)]\n        struct RecordDrop<'a>(&'a mut bool);\n\n        impl Drop for RecordDrop<'_> {\n            fn drop(&mut self) {\n                *self.0 = true;\n            }\n        }\n\n        Python::attach(|py| {\n            let mut dropped = false;\n            let cell = GILOnceCell::new();\n            cell.set(py, RecordDrop(&mut dropped)).unwrap();\n            let drop_container = cell.get(py).unwrap();\n\n            assert!(!*drop_container.0);\n            drop(cell);\n            assert!(dropped);\n        });\n    }\n\n    #[test]\n    #[cfg(not(target_arch = \"wasm32\"))] // We are building wasm Python with pthreads disabled\n    fn test_once_ext() {\n        macro_rules! test_once {\n            ($once:expr, $is_poisoned:expr) => {{\n                // adapted from the example in the docs for Once::try_once_force\n                let init = $once;\n                std::thread::scope(|s| {\n                    // poison the once\n                    let handle = s.spawn(|| {\n                        Python::attach(|py| {\n                            init.call_once_py_attached(py, || panic!());\n                        })\n                    });\n                    assert!(handle.join().is_err());\n\n                    // poisoning propagates\n                    let handle = s.spawn(|| {\n                        Python::attach(|py| {\n                            init.call_once_py_attached(py, || {});\n                        });\n                    });\n\n                    assert!(handle.join().is_err());\n\n                    // call_once_force will still run and reset the poisoned state\n                    Python::attach(|py| {\n                        init.call_once_force_py_attached(py, |state| {\n                            assert!($is_poisoned(state.clone()));\n                        });\n\n                        // once any success happens, we stop propagating the poison\n                        init.call_once_py_attached(py, || {});\n                    });\n\n                    // calling call_once_force should return immediately without calling the closure\n                    Python::attach(|py| init.call_once_force_py_attached(py, |_| panic!()));\n                });\n            }};\n        }\n\n        test_once!(Once::new(), OnceState::is_poisoned);\n        #[cfg(feature = \"parking_lot\")]\n        test_once!(parking_lot::Once::new(), parking_lot::OnceState::poisoned);\n    }\n\n    #[cfg(not(target_arch = \"wasm32\"))] // We are building wasm Python with pthreads disabled\n    #[test]\n    fn test_once_lock_ext() {\n        let cell = std::sync::OnceLock::new();\n        std::thread::scope(|s| {\n            assert!(cell.get().is_none());\n\n            s.spawn(|| {\n                Python::attach(|py| {\n                    assert_eq!(*cell.get_or_init_py_attached(py, || 12345), 12345);\n                });\n            });\n        });\n        assert_eq!(cell.get(), Some(&12345));\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[cfg(not(target_arch = \"wasm32\"))] // We are building wasm Python with pthreads disabled\n    #[test]\n    fn test_mutex_ext() {\n        let barrier = Barrier::new(2);\n\n        let mutex = Python::attach(|py| -> Mutex<Py<BoolWrapper>> {\n            Mutex::new(Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap())\n        });\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                Python::attach(|py| {\n                    let b = mutex.lock_py_attached(py).unwrap();\n                    barrier.wait();\n                    // sleep to ensure the other thread actually blocks\n                    std::thread::sleep(std::time::Duration::from_millis(10));\n                    (*b).bind(py).borrow().0.store(true, Ordering::Release);\n                    drop(b);\n                });\n            });\n            s.spawn(|| {\n                barrier.wait();\n                Python::attach(|py| {\n                    // blocks until the other thread releases the lock\n                    let b = mutex.lock_py_attached(py).unwrap();\n                    assert!((*b).bind(py).borrow().0.load(Ordering::Acquire));\n                });\n            });\n        });\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[cfg(all(\n        any(feature = \"parking_lot\", feature = \"lock_api\"),\n        not(target_arch = \"wasm32\") // We are building wasm Python with pthreads disabled\n    ))]\n    #[test]\n    fn test_parking_lot_mutex_ext() {\n        macro_rules! test_mutex {\n            ($guard:ty ,$mutex:stmt) => {{\n                let barrier = Barrier::new(2);\n\n                let mutex = Python::attach({ $mutex });\n\n                std::thread::scope(|s| {\n                    s.spawn(|| {\n                        Python::attach(|py| {\n                            let b: $guard = mutex.lock_py_attached(py);\n                            barrier.wait();\n                            // sleep to ensure the other thread actually blocks\n                            std::thread::sleep(std::time::Duration::from_millis(10));\n                            (*b).bind(py).borrow().0.store(true, Ordering::Release);\n                            drop(b);\n                        });\n                    });\n                    s.spawn(|| {\n                        barrier.wait();\n                        Python::attach(|py| {\n                            // blocks until the other thread releases the lock\n                            let b: $guard = mutex.lock_py_attached(py);\n                            assert!((*b).bind(py).borrow().0.load(Ordering::Acquire));\n                        });\n                    });\n                });\n            }};\n        }\n\n        test_mutex!(parking_lot::MutexGuard<'_, _>, |py| {\n            parking_lot::Mutex::new(Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap())\n        });\n\n        test_mutex!(parking_lot::ReentrantMutexGuard<'_, _>, |py| {\n            parking_lot::ReentrantMutex::new(\n                Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap(),\n            )\n        });\n\n        #[cfg(feature = \"arc_lock\")]\n        test_mutex!(parking_lot::ArcMutexGuard<_, _>, |py| {\n            let mutex =\n                parking_lot::Mutex::new(Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap());\n            std::sync::Arc::new(mutex)\n        });\n\n        #[cfg(feature = \"arc_lock\")]\n        test_mutex!(parking_lot::ArcReentrantMutexGuard<_, _, _>, |py| {\n            let mutex =\n                parking_lot::ReentrantMutex::new(Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap());\n            std::sync::Arc::new(mutex)\n        });\n    }\n\n    #[cfg(not(target_arch = \"wasm32\"))] // We are building wasm Python with pthreads disabled\n    #[test]\n    fn test_mutex_ext_poison() {\n        let mutex = Mutex::new(42);\n\n        std::thread::scope(|s| {\n            let lock_result = s.spawn(|| {\n                Python::attach(|py| {\n                    let _unused = mutex.lock_py_attached(py);\n                    panic!();\n                });\n            });\n            assert!(lock_result.join().is_err());\n            assert!(mutex.is_poisoned());\n        });\n        let guard = Python::attach(|py| {\n            // recover from the poisoning\n            match mutex.lock_py_attached(py) {\n                Ok(guard) => guard,\n                Err(poisoned) => poisoned.into_inner(),\n            }\n        });\n        assert_eq!(*guard, 42);\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[cfg(not(target_arch = \"wasm32\"))] // We are building wasm Python with pthreads disabled\n    #[test]\n    fn test_rwlock_ext_writer_blocks_reader() {\n        use std::sync::RwLock;\n\n        let barrier = Barrier::new(2);\n\n        let rwlock = Python::attach(|py| -> RwLock<Py<BoolWrapper>> {\n            RwLock::new(Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap())\n        });\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                Python::attach(|py| {\n                    let b = rwlock.write_py_attached(py).unwrap();\n                    barrier.wait();\n                    // sleep to ensure the other thread actually blocks\n                    std::thread::sleep(std::time::Duration::from_millis(10));\n                    (*b).bind(py).borrow().0.store(true, Ordering::Release);\n                    drop(b);\n                });\n            });\n            s.spawn(|| {\n                barrier.wait();\n                Python::attach(|py| {\n                    // blocks until the other thread releases the lock\n                    let b = rwlock.read_py_attached(py).unwrap();\n                    assert!((*b).bind(py).borrow().0.load(Ordering::Acquire));\n                });\n            });\n        });\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[cfg(not(target_arch = \"wasm32\"))] // We are building wasm Python with pthreads disabled\n    #[test]\n    fn test_rwlock_ext_reader_blocks_writer() {\n        use std::sync::RwLock;\n\n        let barrier = Barrier::new(2);\n\n        let rwlock = Python::attach(|py| -> RwLock<Py<BoolWrapper>> {\n            RwLock::new(Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap())\n        });\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                Python::attach(|py| {\n                    let b = rwlock.read_py_attached(py).unwrap();\n                    barrier.wait();\n\n                    // sleep to ensure the other thread actually blocks\n                    std::thread::sleep(std::time::Duration::from_millis(10));\n\n                    // The bool must still be false (i.e., the writer did not actually write the\n                    // value yet).\n                    assert!(!(*b).bind(py).borrow().0.load(Ordering::Acquire));\n                });\n            });\n            s.spawn(|| {\n                barrier.wait();\n                Python::attach(|py| {\n                    // blocks until the other thread releases the lock\n                    let b = rwlock.write_py_attached(py).unwrap();\n                    (*b).bind(py).borrow().0.store(true, Ordering::Release);\n                    drop(b);\n                });\n            });\n        });\n\n        // Confirm that the writer did in fact run and write the expected `true` value.\n        Python::attach(|py| {\n            let b = rwlock.read_py_attached(py).unwrap();\n            assert!((*b).bind(py).borrow().0.load(Ordering::Acquire));\n            drop(b);\n        });\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[cfg(all(\n        any(feature = \"parking_lot\", feature = \"lock_api\"),\n        not(target_arch = \"wasm32\") // We are building wasm Python with pthreads disabled\n    ))]\n    #[test]\n    fn test_parking_lot_rwlock_ext_writer_blocks_reader() {\n        macro_rules! test_rwlock {\n            ($write_guard:ty, $read_guard:ty, $rwlock:stmt) => {{\n                let barrier = Barrier::new(2);\n\n                let rwlock = Python::attach({ $rwlock });\n\n                std::thread::scope(|s| {\n                    s.spawn(|| {\n                        Python::attach(|py| {\n                            let b: $write_guard = rwlock.write_py_attached(py);\n                            barrier.wait();\n                            // sleep to ensure the other thread actually blocks\n                            std::thread::sleep(std::time::Duration::from_millis(10));\n                            (*b).bind(py).borrow().0.store(true, Ordering::Release);\n                            drop(b);\n                        });\n                    });\n                    s.spawn(|| {\n                        barrier.wait();\n                        Python::attach(|py| {\n                            // blocks until the other thread releases the lock\n                            let b: $read_guard = rwlock.read_py_attached(py);\n                            assert!((*b).bind(py).borrow().0.load(Ordering::Acquire));\n                        });\n                    });\n                });\n            }};\n        }\n\n        test_rwlock!(\n            parking_lot::RwLockWriteGuard<'_, _>,\n            parking_lot::RwLockReadGuard<'_, _>,\n            |py| {\n                parking_lot::RwLock::new(Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap())\n            }\n        );\n\n        #[cfg(feature = \"arc_lock\")]\n        test_rwlock!(\n            parking_lot::ArcRwLockWriteGuard<_, _>,\n            parking_lot::ArcRwLockReadGuard<_, _>,\n            |py| {\n                let rwlock = parking_lot::RwLock::new(\n                    Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap(),\n                );\n                std::sync::Arc::new(rwlock)\n            }\n        );\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[cfg(all(\n        any(feature = \"parking_lot\", feature = \"lock_api\"),\n        not(target_arch = \"wasm32\") // We are building wasm Python with pthreads disabled\n    ))]\n    #[test]\n    fn test_parking_lot_rwlock_ext_reader_blocks_writer() {\n        macro_rules! test_rwlock {\n            ($write_guard:ty, $read_guard:ty, $rwlock:stmt) => {{\n                let barrier = Barrier::new(2);\n\n                let rwlock = Python::attach({ $rwlock });\n\n                std::thread::scope(|s| {\n                    s.spawn(|| {\n                        Python::attach(|py| {\n                            let b: $read_guard = rwlock.read_py_attached(py);\n                            barrier.wait();\n\n                            // sleep to ensure the other thread actually blocks\n                            std::thread::sleep(std::time::Duration::from_millis(10));\n\n                            // The bool must still be false (i.e., the writer did not actually write the\n                            // value yet).\n                            assert!(!(*b).bind(py).borrow().0.load(Ordering::Acquire));                            (*b).bind(py).borrow().0.store(true, Ordering::Release);\n\n                            drop(b);\n                        });\n                    });\n                    s.spawn(|| {\n                        barrier.wait();\n                        Python::attach(|py| {\n                            // blocks until the other thread releases the lock\n                            let b: $write_guard = rwlock.write_py_attached(py);\n                            (*b).bind(py).borrow().0.store(true, Ordering::Release);\n                        });\n                    });\n                });\n\n                // Confirm that the writer did in fact run and write the expected `true` value.\n                Python::attach(|py| {\n                    let b: $read_guard = rwlock.read_py_attached(py);\n                    assert!((*b).bind(py).borrow().0.load(Ordering::Acquire));\n                    drop(b);\n                });\n            }};\n        }\n\n        test_rwlock!(\n            parking_lot::RwLockWriteGuard<'_, _>,\n            parking_lot::RwLockReadGuard<'_, _>,\n            |py| {\n                parking_lot::RwLock::new(Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap())\n            }\n        );\n\n        #[cfg(feature = \"arc_lock\")]\n        test_rwlock!(\n            parking_lot::ArcRwLockWriteGuard<_, _>,\n            parking_lot::ArcRwLockReadGuard<_, _>,\n            |py| {\n                let rwlock = parking_lot::RwLock::new(\n                    Py::new(py, BoolWrapper(AtomicBool::new(false))).unwrap(),\n                );\n                std::sync::Arc::new(rwlock)\n            }\n        );\n    }\n\n    #[cfg(not(target_arch = \"wasm32\"))] // We are building wasm Python with pthreads disabled\n    #[test]\n    fn test_rwlock_ext_poison() {\n        use std::sync::RwLock;\n\n        let rwlock = RwLock::new(42);\n\n        std::thread::scope(|s| {\n            let lock_result = s.spawn(|| {\n                Python::attach(|py| {\n                    let _unused = rwlock.write_py_attached(py);\n                    panic!();\n                });\n            });\n            assert!(lock_result.join().is_err());\n            assert!(rwlock.is_poisoned());\n            Python::attach(|py| {\n                assert!(rwlock.read_py_attached(py).is_err());\n                assert!(rwlock.write_py_attached(py).is_err());\n            });\n        });\n        Python::attach(|py| {\n            // recover from the poisoning\n            let guard = rwlock.write_py_attached(py).unwrap_err().into_inner();\n            assert_eq!(*guard, 42);\n        });\n    }\n}\n"
  },
  {
    "path": "src/test_utils.rs",
    "content": "// Brings in `test_utils` from the `tests` directory\n//\n// to make that file function (lots of references to `pyo3` within it) need\n// re-bind `crate` as pyo3\nuse crate as pyo3;\ninclude!(\"../tests/test_utils/mod.rs\");\n"
  },
  {
    "path": "src/tests/hygiene/misc.rs",
    "content": "#[derive(crate::FromPyObject)]\n#[pyo3(crate = \"crate\")]\nstruct Derive1(i32); // newtype case\n\n#[derive(crate::FromPyObject)]\n#[pyo3(crate = \"crate\")]\nstruct Derive2(i32, i32); // tuple case\n\n#[derive(crate::FromPyObject)]\n#[pyo3(crate = \"crate\")]\nstruct Derive3 {\n    f: i32,\n    #[pyo3(item(42))]\n    g: i32,\n    #[pyo3(default)]\n    h: i32,\n} // struct case\n\n#[derive(crate::FromPyObject)]\n#[pyo3(crate = \"crate\")]\nenum Derive4 {\n    A(i32),\n    B { f: i32 },\n} // enum case\n\ncrate::create_exception!(mymodule, CustomError, crate::exceptions::PyException);\ncrate::import_exception!(socket, gaierror);\n\nfn intern(py: crate::Python<'_>) {\n    let _foo = crate::intern!(py, \"foo\");\n    let _bar = crate::intern!(py, stringify!(bar));\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\nfn append_to_inittab() {\n    #[crate::pymodule]\n    #[pyo3(crate = \"crate\")]\n    mod module_for_inittab {}\n\n    crate::append_to_inittab!(module_for_inittab);\n}\n\nmacro_rules! macro_rules_hygiene {\n    ($name_a:ident, $name_b:ident) => {\n        #[crate::pyclass(crate = \"crate\")]\n        struct $name_a {}\n\n        #[crate::pymethods(crate = \"crate\")]\n        impl $name_a {\n            fn finalize(&mut self) -> $name_b {\n                $name_b {}\n            }\n        }\n\n        #[crate::pyclass(crate = \"crate\")]\n        struct $name_b {}\n    };\n}\n\nmacro_rules_hygiene!(MyClass1, MyClass2);\n\n#[derive(crate::IntoPyObject, crate::IntoPyObjectRef)]\n#[pyo3(crate = \"crate\")]\nstruct IntoPyObject1(i32); // transparent newtype case\n\n#[derive(crate::IntoPyObject, crate::IntoPyObjectRef)]\n#[pyo3(crate = \"crate\", transparent)]\nstruct IntoPyObject2<'a> {\n    inner: &'a str, // transparent newtype case\n}\n\n#[derive(crate::IntoPyObject, crate::IntoPyObjectRef)]\n#[pyo3(crate = \"crate\")]\nstruct IntoPyObject3<'py>(i32, crate::Bound<'py, crate::PyAny>); // tuple case\n\n#[derive(crate::IntoPyObject, crate::IntoPyObjectRef)]\n#[pyo3(crate = \"crate\")]\nstruct IntoPyObject4<'a, 'py> {\n    callable: &'a crate::Bound<'py, crate::PyAny>, // struct case\n    num: usize,\n}\n\n#[derive(crate::IntoPyObject, crate::IntoPyObjectRef)]\n#[pyo3(crate = \"crate\")]\nenum IntoPyObject5<'a, 'py> {\n    TransparentTuple(i32),\n    #[pyo3(transparent)]\n    TransparentStruct {\n        f: crate::Py<crate::PyAny>,\n    },\n    Tuple(crate::Bound<'py, crate::types::PyString>, usize),\n    Struct {\n        f: i32,\n        g: &'a str,\n    },\n} // enum case\n"
  },
  {
    "path": "src/tests/hygiene/mod.rs",
    "content": "#![no_implicit_prelude]\n#![allow(dead_code, unused_variables, clippy::unnecessary_wraps)]\n\n// The modules in this test are used to check PyO3 macro expansion is hygienic. By locating the test\n// inside the crate the global `::pyo3` namespace is not available, so in combination with\n// #[pyo3(crate = \"crate\")] this validates that all macro expansion respects the setting.\n\nmod misc;\nmod pyclass;\nmod pyfunction;\nmod pymethods;\nmod pymodule;\n"
  },
  {
    "path": "src/tests/hygiene/pyclass.rs",
    "content": "#[crate::pyclass(from_py_object)]\n#[pyo3(crate = \"crate\")]\n#[derive(::std::clone::Clone)]\npub struct Foo;\n\n#[crate::pyclass]\n#[pyo3(crate = \"crate\")]\npub struct Foo2;\n\n#[cfg_attr(any(Py_3_9, not(Py_LIMITED_API)), crate::pyclass(\n    name = \"ActuallyBar\",\n    freelist = 8,\n    unsendable,\n    subclass,\n    extends = crate::types::PyAny,\n    module = \"Spam\",\n    weakref,\n    dict\n))]\n#[cfg_attr(not(any(Py_3_9, not(Py_LIMITED_API))), crate::pyclass(\n    name = \"ActuallyBar\",\n    freelist = 8,\n    unsendable,\n    subclass,\n    extends = crate::types::PyAny,\n    module = \"Spam\"\n))]\n#[pyo3(crate = \"crate\")]\npub struct Bar {\n    #[pyo3(get, set)]\n    a: u8,\n    #[pyo3(get, set)]\n    b: Foo,\n    #[pyo3(set)]\n    c: ::std::option::Option<crate::Py<Foo2>>,\n}\n\n#[crate::pyclass(eq, eq_int)]\n#[pyo3(crate = \"crate\")]\n#[derive(PartialEq)]\npub enum Enum {\n    Var0,\n}\n\n#[crate::pyclass]\n#[pyo3(crate = \"crate\")]\npub struct Foo3 {\n    #[pyo3(get, set)]\n    #[cfg(any())]\n    field: i32,\n\n    #[pyo3(get, set)]\n    #[cfg(not(any()))]\n    field: u32,\n}\n\n#[crate::pyclass]\n#[pyo3(crate = \"crate\")]\npub struct Foo4 {\n    #[pyo3(get, set)]\n    #[cfg(any())]\n    #[cfg(not(any()))]\n    field: i32,\n\n    #[pyo3(get, set)]\n    #[cfg(not(any()))]\n    field: u32,\n}\n\n#[crate::pyclass(eq, ord)]\n#[pyo3(crate = \"crate\")]\n#[derive(PartialEq, PartialOrd)]\npub struct PointEqOrd {\n    x: u32,\n    y: u32,\n    z: u32,\n}\n\n#[crate::pyclass(eq, ord)]\n#[pyo3(crate = \"crate\")]\n#[derive(PartialEq, PartialOrd)]\npub enum ComplexEnumEqOrd {\n    Variant1 { a: u32, b: u32 },\n    Variant2 { c: u32 },\n}\n\n#[crate::pyclass(eq, ord)]\n#[pyo3(crate = \"crate\")]\n#[derive(PartialEq, PartialOrd)]\npub enum TupleEnumEqOrd {\n    Variant1(u32, u32),\n    Variant2(u32),\n}\n\n#[crate::pyclass(crate = \"crate\")]\npub enum ComplexEnumManyVariantFields {\n    ManyStructFields {\n        field_1: u16,\n        field_2: u32,\n        field_3: u32,\n        field_4: i32,\n        field_5: u32,\n        field_6: u32,\n        field_7: u8,\n        field_8: u32,\n        field_9: i32,\n        field_10: u32,\n        field_11: u32,\n        field_12: u32,\n        field_13: u32,\n        field_14: i16,\n        field_15: u32,\n    },\n    ManyTupleFields(\n        u16,\n        u32,\n        u32,\n        i32,\n        u32,\n        u32,\n        u8,\n        u32,\n        i32,\n        u32,\n        u32,\n        u32,\n        u32,\n        i16,\n        u32,\n    ),\n}\n\n#[crate::pyclass(str = \"{x}, {y}, {z}\")]\n#[pyo3(crate = \"crate\")]\npub struct PointFmt {\n    x: u32,\n    y: u32,\n    z: u32,\n}\n\n#[crate::pyclass(str)]\n#[pyo3(crate = \"crate\")]\npub struct Point {\n    x: i32,\n    y: i32,\n    z: i32,\n}\n\nimpl ::std::fmt::Display for Point {\n    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {\n        ::std::write!(f, \"({}, {}, {})\", self.x, self.y, self.z)\n    }\n}\n\n#[crate::pyclass(crate = \"crate\", from_py_object)]\n#[derive(Clone)]\npub struct Foo5 {\n    a: i32,\n}\n"
  },
  {
    "path": "src/tests/hygiene/pyfunction.rs",
    "content": "#[crate::pyfunction]\n#[pyo3(crate = \"crate\")]\nfn do_something(x: i32) -> crate::PyResult<i32> {\n    ::std::result::Result::Ok(x)\n}\n\n#[crate::pyfunction]\n#[pyo3(crate = \"crate\", name = \"check5012\")]\nfn check_5012(x: i32) -> crate::PyResult<i32> {\n    ::std::result::Result::Ok(x)\n}\n\n#[crate::pyfunction]\n#[pyo3(crate = \"crate\")]\n#[pyo3(warn(message = \"This is a warning message\"))]\nfn function_with_warning() {}\n\n#[crate::pyfunction(crate = \"crate\")]\n#[pyo3(warn(message = \"This is a warning message with custom category\", category = crate::exceptions::PyFutureWarning))]\nfn function_with_warning_and_category() {}\n\n#[crate::pyfunction(crate = \"crate\")]\n#[pyo3(warn(message = \"This is a warning message\"))]\n#[pyo3(warn(message = \"This is another warning message\", category = crate::exceptions::PyFutureWarning))]\nfn multiple_warning_function() {}\n\n#[test]\nfn invoke_wrap_pyfunction() {\n    crate::Python::attach(|py| {\n        let func = crate::wrap_pyfunction!(do_something, py).unwrap();\n        crate::py_run!(py, func, r#\"func(5)\"#);\n    });\n}\n"
  },
  {
    "path": "src/tests/hygiene/pymethods.rs",
    "content": "#[crate::pyclass]\n#[pyo3(crate = \"crate\")]\npub struct Dummy;\n\n#[crate::pyclass]\n#[pyo3(crate = \"crate\")]\npub struct DummyIter;\n\n#[crate::pymethods]\n#[pyo3(crate = \"crate\")]\nimpl Dummy {\n    //////////////////////\n    // Basic customization\n    //////////////////////\n    fn __repr__(&self) -> &'static str {\n        \"Dummy\"\n    }\n\n    fn __str__(&self) -> &'static str {\n        \"Dummy\"\n    }\n\n    fn __bytes__<'py>(&self, py: crate::Python<'py>) -> crate::Bound<'py, crate::types::PyBytes> {\n        crate::types::PyBytes::new(py, &[0])\n    }\n\n    fn __format__(&self, format_spec: ::std::string::String) -> ::std::string::String {\n        ::std::unimplemented!()\n    }\n\n    fn __lt__(&self, other: &Self) -> bool {\n        false\n    }\n\n    fn __le__(&self, other: &Self) -> bool {\n        false\n    }\n    fn __eq__(&self, other: &Self) -> bool {\n        false\n    }\n    fn __ne__(&self, other: &Self) -> bool {\n        false\n    }\n    fn __gt__(&self, other: &Self) -> bool {\n        false\n    }\n    fn __ge__(&self, other: &Self) -> bool {\n        false\n    }\n\n    fn __hash__(&self) -> u64 {\n        42\n    }\n\n    fn __bool__(&self) -> bool {\n        true\n    }\n\n    //////////////////////\n    // Customizing attribute access\n    //////////////////////\n\n    fn __getattr__(&self, name: ::std::string::String) -> &crate::Bound<'_, crate::PyAny> {\n        ::std::unimplemented!()\n    }\n\n    fn __getattribute__(&self, name: ::std::string::String) -> &crate::Bound<'_, crate::PyAny> {\n        ::std::unimplemented!()\n    }\n\n    fn __setattr__(&mut self, name: ::std::string::String, value: ::std::string::String) {}\n\n    fn __delattr__(&mut self, name: ::std::string::String) {}\n\n    fn __dir__<'py>(\n        &self,\n        py: crate::Python<'py>,\n    ) -> crate::PyResult<crate::Bound<'py, crate::types::PyList>> {\n        crate::types::PyList::new(py, ::std::vec![0_u8])\n    }\n\n    //////////////////////\n    // Implementing Descriptors\n    //////////////////////\n\n    fn __get__(\n        &self,\n        instance: &crate::Bound<'_, crate::PyAny>,\n        owner: &crate::Bound<'_, crate::PyAny>,\n    ) -> crate::PyResult<&crate::Bound<'_, crate::PyAny>> {\n        ::std::unimplemented!()\n    }\n\n    fn __set__(\n        &self,\n        instance: &crate::Bound<'_, crate::PyAny>,\n        owner: &crate::Bound<'_, crate::PyAny>,\n    ) {\n    }\n\n    fn __delete__(&self, instance: &crate::Bound<'_, crate::PyAny>) {}\n\n    fn __set_name__(\n        &self,\n        owner: &crate::Bound<'_, crate::PyAny>,\n        name: &crate::Bound<'_, crate::PyAny>,\n    ) {\n    }\n\n    //////////////////////\n    // Implementing Descriptors\n    //////////////////////\n\n    fn __len__(&self) -> usize {\n        0\n    }\n\n    fn __getitem__(&self, key: u32) -> crate::PyResult<u32> {\n        ::std::result::Result::Err(crate::exceptions::PyKeyError::new_err(\"boo\"))\n    }\n\n    fn __setitem__(&self, key: u32, value: u32) {}\n\n    fn __delitem__(&self, key: u32) {}\n\n    fn __iter__(_: crate::pycell::PyRef<'_, Self>, py: crate::Python<'_>) -> crate::Py<DummyIter> {\n        crate::Py::new(py, DummyIter {}).unwrap()\n    }\n\n    fn __next__(&mut self) -> ::std::option::Option<()> {\n        ::std::option::Option::None\n    }\n\n    fn __reversed__(\n        slf: crate::pycell::PyRef<'_, Self>,\n        py: crate::Python<'_>,\n    ) -> crate::Py<DummyIter> {\n        crate::Py::new(py, DummyIter {}).unwrap()\n    }\n\n    fn __contains__(&self, item: u32) -> bool {\n        false\n    }\n\n    //////////////////////\n    // Emulating numeric types\n    //////////////////////\n\n    fn __add__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __sub__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __mul__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __truediv__(&self, _other: &Self) -> crate::PyResult<()> {\n        ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err(\"boo\"))\n    }\n\n    fn __floordiv__(&self, _other: &Self) -> crate::PyResult<()> {\n        ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err(\"boo\"))\n    }\n\n    fn __mod__(&self, _other: &Self) -> u32 {\n        0\n    }\n\n    fn __divmod__(&self, _other: &Self) -> (u32, u32) {\n        (0, 0)\n    }\n\n    fn __pow__(&self, _other: &Self, modulo: ::std::option::Option<i32>) -> Dummy {\n        Dummy {}\n    }\n\n    fn __lshift__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __rshift__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __and__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __xor__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __or__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __radd__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __rrsub__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __rmul__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __rtruediv__(&self, _other: &Self) -> crate::PyResult<()> {\n        ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err(\"boo\"))\n    }\n\n    fn __rfloordiv__(&self, _other: &Self) -> crate::PyResult<()> {\n        ::std::result::Result::Err(crate::exceptions::PyZeroDivisionError::new_err(\"boo\"))\n    }\n\n    fn __rmod__(&self, _other: &Self) -> u32 {\n        0\n    }\n\n    fn __rdivmod__(&self, _other: &Self) -> (u32, u32) {\n        (0, 0)\n    }\n\n    fn __rpow__(&self, _other: &Self, modulo: ::std::option::Option<i32>) -> Dummy {\n        Dummy {}\n    }\n\n    fn __rlshift__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __rrshift__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __rand__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __rxor__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __ror__(&self, other: &Self) -> Dummy {\n        Dummy {}\n    }\n\n    fn __iadd__(&mut self, other: &Self) {}\n\n    fn __irsub__(&mut self, other: &Self) {}\n\n    fn __imul__(&mut self, other: &Self) {}\n\n    fn __itruediv__(&mut self, _other: &Self) {}\n\n    fn __ifloordiv__(&mut self, _other: &Self) {}\n\n    fn __imod__(&mut self, _other: &Self) {}\n\n    fn __ipow__(&mut self, _other: &Self, modulo: ::std::option::Option<i32>) {}\n\n    fn __ilshift__(&mut self, other: &Self) {}\n\n    fn __irshift__(&mut self, other: &Self) {}\n\n    fn __iand__(&mut self, other: &Self) {}\n\n    fn __ixor__(&mut self, other: &Self) {}\n\n    fn __ior__(&mut self, other: &Self) {}\n\n    fn __neg__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> {\n        slf\n    }\n\n    fn __pos__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> {\n        slf\n    }\n\n    fn __abs__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> {\n        slf\n    }\n\n    fn __invert__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> {\n        slf\n    }\n\n    fn __complex__<'py>(\n        &self,\n        py: crate::Python<'py>,\n    ) -> crate::Bound<'py, crate::types::PyComplex> {\n        crate::types::PyComplex::from_doubles(py, 0.0, 0.0)\n    }\n\n    fn __int__(&self) -> u32 {\n        0\n    }\n\n    fn __float__(&self) -> f64 {\n        0.0\n    }\n\n    fn __index__(&self) -> u32 {\n        0\n    }\n\n    #[pyo3(signature=(ndigits=::std::option::Option::None))]\n    fn __round__(&self, ndigits: ::std::option::Option<u32>) -> u32 {\n        0\n    }\n\n    fn __trunc__(&self) -> u32 {\n        0\n    }\n\n    fn __floor__(&self) -> u32 {\n        0\n    }\n\n    fn __ceil__(&self) -> u32 {\n        0\n    }\n\n    //////////////////////\n    // With Statement Context Managers\n    //////////////////////\n\n    fn __enter__(&mut self) {}\n\n    fn __exit__(\n        &mut self,\n        exc_type: &crate::Bound<'_, crate::PyAny>,\n        exc_value: &crate::Bound<'_, crate::PyAny>,\n        traceback: &crate::Bound<'_, crate::PyAny>,\n    ) {\n    }\n\n    //////////////////////\n    // Awaitable Objects\n    //////////////////////\n\n    fn __await__(slf: crate::pycell::PyRef<'_, Self>) -> crate::pycell::PyRef<'_, Self> {\n        slf\n    }\n\n    //////////////////////\n\n    // Asynchronous Iterators\n    //////////////////////\n\n    fn __aiter__(\n        slf: crate::pycell::PyRef<'_, Self>,\n        py: crate::Python<'_>,\n    ) -> crate::Py<DummyIter> {\n        crate::Py::new(py, DummyIter {}).unwrap()\n    }\n\n    fn __anext__(&mut self) -> ::std::option::Option<()> {\n        ::std::option::Option::None\n    }\n\n    //////////////////////\n    // Asynchronous Context Managers\n    //////////////////////\n\n    fn __aenter__(&mut self) {}\n\n    fn __aexit__(\n        &mut self,\n        exc_type: &crate::Bound<'_, crate::PyAny>,\n        exc_value: &crate::Bound<'_, crate::PyAny>,\n        traceback: &crate::Bound<'_, crate::PyAny>,\n    ) {\n    }\n\n    // Things with attributes\n\n    #[pyo3(signature = (_y, *, _z=2))]\n    fn test(&self, _y: &Dummy, _z: i32) {}\n    #[staticmethod]\n    fn staticmethod() {}\n    #[classmethod]\n    fn clsmethod(_: &crate::Bound<'_, crate::types::PyType>) {}\n    #[pyo3(signature = (*_args, **_kwds))]\n    fn __call__(\n        &self,\n        _args: &crate::Bound<'_, crate::types::PyTuple>,\n        _kwds: ::std::option::Option<&crate::Bound<'_, crate::types::PyDict>>,\n    ) -> crate::PyResult<i32> {\n        ::std::unimplemented!()\n    }\n    #[new]\n    fn new(a: u8) -> Self {\n        Dummy {}\n    }\n    #[getter]\n    fn get(&self) -> i32 {\n        0\n    }\n    #[setter]\n    fn set(&mut self, _v: i32) {}\n    #[deleter]\n    fn delete(&mut self) {}\n    #[classattr]\n    fn class_attr() -> i32 {\n        0\n    }\n\n    // Dunder methods invented for protocols\n\n    // PyGcProtocol\n    // Buffer protocol?\n}\n\n#[crate::pyclass(crate = \"crate\")]\nstruct Clear;\n\n#[crate::pymethods(crate = \"crate\")]\nimpl Clear {\n    pub fn __traverse__(\n        &self,\n        visit: crate::PyVisit<'_>,\n    ) -> ::std::result::Result<(), crate::PyTraverseError> {\n        ::std::result::Result::Ok(())\n    }\n\n    pub fn __clear__(&self) {}\n\n    #[pyo3(signature=(*, reuse=false))]\n    pub fn clear(&self, reuse: bool) {}\n}\n\n// Ensure that crate argument is also accepted inline\n\n#[crate::pyclass(crate = \"crate\")]\nstruct Dummy2;\n\n#[crate::pymethods(crate = \"crate\")]\nimpl Dummy2 {\n    #[classmethod]\n    fn __len__(cls: &crate::Bound<'_, crate::types::PyType>) -> crate::PyResult<usize> {\n        ::std::result::Result::Ok(0)\n    }\n\n    #[staticmethod]\n    fn __repr__() -> &'static str {\n        \"Dummy\"\n    }\n}\n\n#[crate::pyclass(crate = \"crate\")]\nstruct WarningDummy {\n    value: i32,\n}\n\n#[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n#[crate::pyclass(crate = \"crate\", extends=crate::exceptions::PyWarning)]\npub struct UserDefinedWarning {}\n\n#[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n#[crate::pymethods(crate = \"crate\")]\nimpl UserDefinedWarning {\n    #[new]\n    #[pyo3(signature = (*_args, **_kwargs))]\n    fn new(\n        _args: crate::Bound<'_, crate::PyAny>,\n        _kwargs: ::std::option::Option<crate::Bound<'_, crate::PyAny>>,\n    ) -> Self {\n        Self {}\n    }\n}\n\n#[crate::pymethods(crate = \"crate\")]\nimpl WarningDummy {\n    #[new]\n    #[pyo3(warn(message = \"this __new__ method raises warning\"))]\n    fn new() -> Self {\n        Self { value: 0 }\n    }\n\n    #[pyo3(warn(message = \"this method raises warning\"))]\n    fn method_with_warning(_slf: crate::PyRef<'_, Self>) {}\n\n    #[pyo3(warn(message = \"this method raises warning\", category = crate::exceptions::PyFutureWarning))]\n    fn method_with_warning_and_custom_category(_slf: crate::PyRef<'_, Self>) {}\n\n    #[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n    #[pyo3(warn(message = \"this method raises user-defined warning\", category = UserDefinedWarning))]\n    fn method_with_warning_and_user_defined_category(&self) {}\n\n    #[staticmethod]\n    #[pyo3(warn(message = \"this static method raises warning\"))]\n    fn static_method() {}\n\n    #[staticmethod]\n    #[pyo3(warn(message = \"this class method raises warning\"))]\n    fn class_method() {}\n\n    #[getter]\n    #[pyo3(warn(message = \"this getter raises warning\"))]\n    fn get_value(&self) -> i32 {\n        self.value\n    }\n\n    #[setter]\n    #[pyo3(warn(message = \"this setter raises warning\"))]\n    fn set_value(&mut self, value: i32) {\n        self.value = value;\n    }\n\n    #[deleter]\n    #[pyo3(warn(message = \"this deleter raises warning\"))]\n    fn deleter_value(&mut self) {\n        self.value = 0;\n    }\n\n    #[pyo3(warn(message = \"this subscript op method raises warning\"))]\n    fn __getitem__(&self, _key: i32) -> i32 {\n        0\n    }\n\n    #[pyo3(warn(message = \"the + op method raises warning\"))]\n    fn __add__(&self, other: crate::PyRef<'_, Self>) -> Self {\n        Self {\n            value: self.value + other.value,\n        }\n    }\n\n    #[pyo3(warn(message = \"this __call__ method raises warning\"))]\n    fn __call__(&self) -> i32 {\n        self.value\n    }\n\n    #[pyo3(warn(message = \"this method raises warning 1\"))]\n    #[pyo3(warn(message = \"this method raises warning 2\", category = crate::exceptions::PyFutureWarning))]\n    fn multiple_warn_method(&self) {}\n}\n\n#[crate::pyclass(crate = \"crate\")]\nstruct WarningDummy2;\n\n#[crate::pymethods(crate = \"crate\")]\nimpl WarningDummy2 {\n    #[new]\n    #[classmethod]\n    #[pyo3(warn(message = \"this class-method __new__ method raises warning\"))]\n    fn new(_cls: crate::Bound<'_, crate::types::PyType>) -> Self {\n        Self {}\n    }\n\n    #[pyo3(warn(message = \"this class-method raises warning 1\"))]\n    #[pyo3(warn(message = \"this class-method raises warning 2\"))]\n    fn multiple_default_warnings_fn(&self) {}\n\n    #[pyo3(warn(message = \"this class-method raises warning\"))]\n    #[pyo3(warn(message = \"this class-method raises future warning\", category = crate::exceptions::PyFutureWarning))]\n    fn multiple_warnings_fn(&self) {}\n\n    #[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n    #[pyo3(warn(message = \"this class-method raises future warning\", category = crate::exceptions::PyFutureWarning))]\n    #[pyo3(warn(message = \"this class-method raises user-defined warning\", category = UserDefinedWarning))]\n    fn multiple_warnings_fn_with_custom_category(&self) {}\n}\n"
  },
  {
    "path": "src/tests/hygiene/pymodule.rs",
    "content": "#[crate::pyfunction]\n#[pyo3(crate = \"crate\")]\nfn do_something(x: i32) -> crate::PyResult<i32> {\n    ::std::result::Result::Ok(x)\n}\n\n#[crate::pymodule]\n#[pyo3(crate = \"crate\")]\nfn foo(\n    _py: crate::Python<'_>,\n    _m: &crate::Bound<'_, crate::types::PyModule>,\n) -> crate::PyResult<()> {\n    ::std::result::Result::Ok(())\n}\n\n#[crate::pymodule]\n#[pyo3(crate = \"crate\")]\nfn my_module(m: &crate::Bound<'_, crate::types::PyModule>) -> crate::PyResult<()> {\n    <crate::Bound<'_, crate::types::PyModule> as crate::types::PyModuleMethods>::add_function(\n        m,\n        crate::wrap_pyfunction!(do_something, m)?,\n    )?;\n    <crate::Bound<'_, crate::types::PyModule> as crate::types::PyModuleMethods>::add_wrapped(\n        m,\n        crate::wrap_pymodule!(foo),\n    )?;\n\n    ::std::result::Result::Ok(())\n}\n\n#[crate::pymodule(submodule)]\n#[pyo3(crate = \"crate\")]\nmod my_module_declarative {\n    #[pymodule_export]\n    use super::{do_something, foo};\n\n    #[pymodule_export]\n    const BAR: u32 = 42;\n}\n"
  },
  {
    "path": "src/tests/mod.rs",
    "content": "/// Test macro hygiene - this is in the crate since we won't have\n/// `pyo3` available in the crate root.\n#[cfg(all(test, feature = \"macros\"))]\nmod hygiene;\n"
  },
  {
    "path": "src/type_object.rs",
    "content": "//! Python type object information\n\nuse crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_identifier, PyStaticExpr};\nuse crate::types::{PyAny, PyType};\nuse crate::{ffi, Bound, Python};\nuse std::ptr;\n\n/// `T: PyLayout<U>` represents that `T` is a concrete representation of `U` in the Python heap.\n/// E.g., `PyClassObject` is a concrete representation of all `pyclass`es, and `ffi::PyObject`\n/// is of `PyAny`.\n///\n/// This trait is intended to be used internally.\n///\n/// # Safety\n///\n/// This trait must only be implemented for types which represent valid layouts of Python objects.\npub unsafe trait PyLayout<T> {}\n\n/// `T: PySizedLayout<U>` represents that `T` is not a instance of\n/// [`PyVarObject`](https://docs.python.org/3/c-api/structures.html#c.PyVarObject).\n///\n/// In addition, that `T` is a concrete representation of `U`.\npub trait PySizedLayout<T>: PyLayout<T> + Sized {}\n\n/// Python type information.\n/// All Python native types (e.g., `PyDict`) and `#[pyclass]` structs implement this trait.\n///\n/// This trait is marked unsafe because:\n///  - specifying the incorrect layout can lead to memory errors\n///  - the return value of type_object must always point to the same PyTypeObject instance\n///\n/// It is safely implemented by the `pyclass` macro.\n///\n/// # Safety\n///\n/// Implementations must provide an implementation for `type_object_raw` which infallibly produces a\n/// non-null pointer to the corresponding Python type object.\n///\n/// `is_type_of` must only return true for objects which can safely be treated as instances of `Self`.\n///\n/// `is_exact_type_of` must only return true for objects whose type is exactly `Self`.\npub unsafe trait PyTypeInfo: Sized {\n    /// Class name.\n    #[deprecated(\n        since = \"0.28.0\",\n        note = \"prefer using `::type_object(py).name()` to get the correct runtime value\"\n    )]\n    const NAME: &'static str;\n\n    /// Module name, if any.\n    #[deprecated(\n        since = \"0.28.0\",\n        note = \"prefer using `::type_object(py).module()` to get the correct runtime value\"\n    )]\n    const MODULE: Option<&'static str>;\n\n    /// Provides the full python type as a type hint.\n    #[cfg(feature = \"experimental-inspect\")]\n    const TYPE_HINT: PyStaticExpr = type_hint_identifier!(\"_typeshed\", \"Incomplete\");\n\n    /// Returns the PyTypeObject instance for this type.\n    fn type_object_raw(py: Python<'_>) -> *mut ffi::PyTypeObject;\n\n    /// Returns the safe abstraction over the type object.\n    #[inline]\n    fn type_object(py: Python<'_>) -> Bound<'_, PyType> {\n        // Making the borrowed object `Bound` is necessary for soundness reasons. It's an extreme\n        // edge case, but arbitrary Python code _could_ change the __class__ of an object and cause\n        // the type object to be freed.\n        //\n        // By making `Bound` we assume ownership which is then safe against races.\n        unsafe {\n            Self::type_object_raw(py)\n                .cast::<ffi::PyObject>()\n                .assume_borrowed_unchecked(py)\n                .to_owned()\n                .cast_into_unchecked()\n        }\n    }\n\n    /// Checks if `object` is an instance of this type or a subclass of this type.\n    #[inline]\n    fn is_type_of(object: &Bound<'_, PyAny>) -> bool {\n        unsafe { ffi::PyObject_TypeCheck(object.as_ptr(), Self::type_object_raw(object.py())) != 0 }\n    }\n\n    /// Checks if `object` is an instance of this type.\n    #[inline]\n    fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool {\n        unsafe {\n            ptr::eq(\n                ffi::Py_TYPE(object.as_ptr()),\n                Self::type_object_raw(object.py()),\n            )\n        }\n    }\n}\n\n/// Implemented by types which can be used as a concrete Python type inside `Py<T>` smart pointers.\n///\n/// # Safety\n///\n/// This trait is used to determine whether [`Bound::cast`] and similar functions can safely cast\n/// to a concrete type. The implementor is responsible for ensuring that `type_check` only returns\n/// true for objects which can safely be treated as Python instances of `Self`.\npub unsafe trait PyTypeCheck {\n    /// Name of self. This is used in error messages, for example.\n    #[deprecated(\n        since = \"0.27.0\",\n        note = \"Use ::classinfo_object() instead and format the type name at runtime. Note that using built-in cast features is often better than manual PyTypeCheck usage.\"\n    )]\n    const NAME: &'static str;\n\n    /// Provides the full python type of the allowed values as a Python type hint.\n    #[cfg(feature = \"experimental-inspect\")]\n    const TYPE_HINT: PyStaticExpr;\n\n    /// Checks if `object` is an instance of `Self`, which may include a subtype.\n    ///\n    /// This should be equivalent to the Python expression `isinstance(object, Self)`.\n    fn type_check(object: &Bound<'_, PyAny>) -> bool;\n\n    /// Returns the expected type as a possible argument for the `isinstance` and `issubclass` function.\n    ///\n    /// It may be a single type or a tuple of types.\n    fn classinfo_object(py: Python<'_>) -> Bound<'_, PyAny>;\n}\n\nunsafe impl<T> PyTypeCheck for T\nwhere\n    T: PyTypeInfo,\n{\n    #[allow(deprecated)]\n    const NAME: &'static str = T::NAME;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const TYPE_HINT: PyStaticExpr = <T as PyTypeInfo>::TYPE_HINT;\n\n    #[inline]\n    fn type_check(object: &Bound<'_, PyAny>) -> bool {\n        T::is_type_of(object)\n    }\n\n    #[inline]\n    fn classinfo_object(py: Python<'_>) -> Bound<'_, PyAny> {\n        T::type_object(py).into_any()\n    }\n}\n"
  },
  {
    "path": "src/types/any.rs",
    "content": "use crate::call::PyCallArgs;\nuse crate::class::basic::CompareOp;\nuse crate::conversion::{FromPyObject, IntoPyObject};\nuse crate::err::{PyErr, PyResult};\nuse crate::exceptions::{PyAttributeError, PyTypeError};\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::impl_::pycell::PyStaticClassObject;\nuse crate::instance::Bound;\nuse crate::internal::get_slot::TP_DESCR_GET;\nuse crate::py_result_ext::PyResultExt;\nuse crate::type_object::{PyTypeCheck, PyTypeInfo};\nuse crate::types::PySuper;\nuse crate::types::{PyDict, PyIterator, PyList, PyString, PyType};\nuse crate::{err, ffi, Borrowed, BoundObject, IntoPyObjectExt, Py, Python};\n#[allow(deprecated)]\nuse crate::{DowncastError, DowncastIntoError};\nuse std::cell::UnsafeCell;\nuse std::cmp::Ordering;\nuse std::ffi::c_int;\nuse std::ptr;\n\n/// Represents any Python object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyAny>`][crate::Py] or [`Bound<'py, PyAny>`][Bound].\n///\n/// For APIs available on all Python objects, see the [`PyAnyMethods`] trait which is implemented for\n/// [`Bound<'py, PyAny>`][Bound].\n///\n/// See\n#[doc = concat!(\"[the guide](https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/types.html#concrete-python-types)\")]\n/// for an explanation of the different Python object types.\n#[repr(transparent)]\npub struct PyAny(UnsafeCell<ffi::PyObject>);\n\n#[allow(non_snake_case)]\n// Copied here as the macro does not accept deprecated functions.\n// Originally ffi::object::PyObject_Check, but this is not in the Python C API.\nfn PyObject_Check(_: *mut ffi::PyObject) -> c_int {\n    1\n}\n\n// We follow stub writing guidelines and use \"object\" instead of \"typing.Any\": https://typing.python.org/en/latest/guides/writing_stubs.html#using-any\npyobject_native_type_info!(\n    PyAny,\n    pyobject_native_static_type_object!(ffi::PyBaseObject_Type),\n    \"typing\",\n    \"Any\",\n    Some(\"builtins\"),\n    #checkfunction=PyObject_Check\n);\n\npyobject_native_type_sized!(PyAny, ffi::PyObject);\n// We cannot use `pyobject_subclassable_native_type!()` because it cfgs out on `Py_LIMITED_API`.\nimpl crate::impl_::pyclass::PyClassBaseType for PyAny {\n    type LayoutAsBase = crate::impl_::pycell::PyClassObjectBase<ffi::PyObject>;\n    type BaseNativeType = PyAny;\n    type Initializer = crate::impl_::pyclass_init::PyNativeTypeInitializer<Self>;\n    type PyClassMutability = crate::pycell::impl_::ImmutableClass;\n    type Layout<T: crate::impl_::pyclass::PyClassImpl> = PyStaticClassObject<T>;\n}\n\n/// This trait represents the Python APIs which are usable on all Python objects.\n///\n/// It is recommended you import this trait via `use pyo3::prelude::*` rather than\n/// by importing this trait directly.\n#[doc(alias = \"PyAny\")]\npub trait PyAnyMethods<'py>: crate::sealed::Sealed {\n    /// Returns whether `self` and `other` point to the same object. To compare\n    /// the equality of two objects (the `==` operator), use [`eq`](PyAnyMethods::eq).\n    ///\n    /// This is equivalent to the Python expression `self is other`.\n    fn is<T: AsRef<Py<PyAny>>>(&self, other: T) -> bool;\n\n    /// Determines whether this object has the given attribute.\n    ///\n    /// This is equivalent to the Python expression `hasattr(self, attr_name)`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used\n    /// to intern `attr_name`.\n    ///\n    /// # Example: `intern!`ing the attribute name\n    ///\n    /// ```\n    /// # use pyo3::{prelude::*, intern};\n    /// #\n    /// #[pyfunction]\n    /// fn has_version(sys: &Bound<'_, PyModule>) -> PyResult<bool> {\n    ///     sys.hasattr(intern!(sys.py(), \"version\"))\n    /// }\n    /// #\n    /// # Python::attach(|py| {\n    /// #    let sys = py.import(\"sys\").unwrap();\n    /// #    has_version(&sys).unwrap();\n    /// # });\n    /// ```\n    fn hasattr<N>(&self, attr_name: N) -> PyResult<bool>\n    where\n        N: IntoPyObject<'py, Target = PyString>;\n\n    /// Retrieves an attribute value.\n    ///\n    /// This is equivalent to the Python expression `self.attr_name`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used\n    /// to intern `attr_name`.\n    ///\n    /// # Example: `intern!`ing the attribute name\n    ///\n    /// ```\n    /// # use pyo3::{prelude::*, intern};\n    /// #\n    /// #[pyfunction]\n    /// fn version<'py>(sys: &Bound<'py, PyModule>) -> PyResult<Bound<'py, PyAny>> {\n    ///     sys.getattr(intern!(sys.py(), \"version\"))\n    /// }\n    /// #\n    /// # Python::attach(|py| {\n    /// #    let sys = py.import(\"sys\").unwrap();\n    /// #    version(&sys).unwrap();\n    /// # });\n    /// ```\n    fn getattr<N>(&self, attr_name: N) -> PyResult<Bound<'py, PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>;\n\n    /// Retrieves an attribute value optionally.\n    ///\n    /// This is equivalent to the Python expression `getattr(self, attr_name, None)`, which may\n    /// be more efficient in some cases by simply returning `None` if the attribute is not found\n    /// instead of raising `AttributeError`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used\n    /// to intern `attr_name`.\n    ///\n    /// # Errors\n    /// Returns `Err` if an exception other than `AttributeError` is raised during attribute lookup,\n    /// such as a `ValueError` from a property or descriptor.\n    ///\n    /// # Example: Retrieving an optional attribute\n    /// ```\n    /// # use pyo3::{prelude::*, intern};\n    /// #\n    /// #[pyfunction]\n    /// fn get_version_if_exists<'py>(sys: &Bound<'py, PyModule>) -> PyResult<Option<Bound<'py, PyAny>>> {\n    ///     sys.getattr_opt(intern!(sys.py(), \"version\"))\n    /// }\n    /// #\n    /// # Python::attach(|py| {\n    /// #    let sys = py.import(\"sys\").unwrap();\n    /// #    let version = get_version_if_exists(&sys).unwrap();\n    /// #    assert!(version.is_some());\n    /// # });\n    /// ```\n    fn getattr_opt<N>(&self, attr_name: N) -> PyResult<Option<Bound<'py, PyAny>>>\n    where\n        N: IntoPyObject<'py, Target = PyString>;\n\n    /// Sets an attribute value.\n    ///\n    /// This is equivalent to the Python expression `self.attr_name = value`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used\n    /// to intern `name`.\n    ///\n    /// # Example: `intern!`ing the attribute name\n    ///\n    /// ```\n    /// # use pyo3::{prelude::*, intern};\n    /// #\n    /// #[pyfunction]\n    /// fn set_answer(ob: &Bound<'_, PyAny>) -> PyResult<()> {\n    ///     ob.setattr(intern!(ob.py(), \"answer\"), 42)\n    /// }\n    /// #\n    /// # Python::attach(|py| {\n    /// #    let ob = PyModule::new(py, \"empty\").unwrap();\n    /// #    set_answer(&ob).unwrap();\n    /// # });\n    /// ```\n    fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n        V: IntoPyObject<'py>;\n\n    /// Deletes an attribute.\n    ///\n    /// This is equivalent to the Python statement `del self.attr_name`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used\n    /// to intern `attr_name`.\n    fn delattr<N>(&self, attr_name: N) -> PyResult<()>\n    where\n        N: IntoPyObject<'py, Target = PyString>;\n\n    /// Returns an [`Ordering`] between `self` and `other`.\n    ///\n    /// This is equivalent to the following Python code:\n    /// ```python\n    /// if self == other:\n    ///     return Equal\n    /// elif a < b:\n    ///     return Less\n    /// elif a > b:\n    ///     return Greater\n    /// else:\n    ///     raise TypeError(\"PyAny::compare(): All comparisons returned false\")\n    /// ```\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyFloat;\n    /// use std::cmp::Ordering;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let a = PyFloat::new(py, 0_f64);\n    ///     let b = PyFloat::new(py, 42_f64);\n    ///     assert_eq!(a.compare(b)?, Ordering::Less);\n    ///     Ok(())\n    /// })?;\n    /// # Ok(())}\n    /// ```\n    ///\n    /// It will return `PyErr` for values that cannot be compared:\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::{PyFloat, PyString};\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let a = PyFloat::new(py, 0_f64);\n    ///     let b = PyString::new(py, \"zero\");\n    ///     assert!(a.compare(b).is_err());\n    ///     Ok(())\n    /// })?;\n    /// # Ok(())}\n    /// ```\n    fn compare<O>(&self, other: O) -> PyResult<Ordering>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Tests whether two Python objects obey a given [`CompareOp`].\n    ///\n    /// [`lt`](Self::lt), [`le`](Self::le), [`eq`](Self::eq), [`ne`](Self::ne),\n    /// [`gt`](Self::gt) and [`ge`](Self::ge) are the specialized versions\n    /// of this function.\n    ///\n    /// Depending on the value of `compare_op`, this is equivalent to one of the\n    /// following Python expressions:\n    ///\n    /// | `compare_op` | Python expression |\n    /// | :---: | :----: |\n    /// | [`CompareOp::Eq`] | `self == other` |\n    /// | [`CompareOp::Ne`] | `self != other` |\n    /// | [`CompareOp::Lt`] | `self < other` |\n    /// | [`CompareOp::Le`] | `self <= other` |\n    /// | [`CompareOp::Gt`] | `self > other` |\n    /// | [`CompareOp::Ge`] | `self >= other` |\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::class::basic::CompareOp;\n    /// use pyo3::prelude::*;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let a = 0_u8.into_pyobject(py)?;\n    ///     let b = 42_u8.into_pyobject(py)?;\n    ///     assert!(a.rich_compare(b, CompareOp::Le)?.is_truthy()?);\n    ///     Ok(())\n    /// })?;\n    /// # Ok(())}\n    /// ```\n    fn rich_compare<O>(&self, other: O, compare_op: CompareOp) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes the negative of self.\n    ///\n    /// Equivalent to the Python expression `-self`.\n    fn neg(&self) -> PyResult<Bound<'py, PyAny>>;\n\n    /// Computes the positive of self.\n    ///\n    /// Equivalent to the Python expression `+self`.\n    fn pos(&self) -> PyResult<Bound<'py, PyAny>>;\n\n    /// Computes the absolute of self.\n    ///\n    /// Equivalent to the Python expression `abs(self)`.\n    fn abs(&self) -> PyResult<Bound<'py, PyAny>>;\n\n    /// Computes `~self`.\n    fn bitnot(&self) -> PyResult<Bound<'py, PyAny>>;\n\n    /// Tests whether this object is less than another.\n    ///\n    /// This is equivalent to the Python expression `self < other`.\n    fn lt<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Tests whether this object is less than or equal to another.\n    ///\n    /// This is equivalent to the Python expression `self <= other`.\n    fn le<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Tests whether this object is equal to another.\n    ///\n    /// This is equivalent to the Python expression `self == other`.\n    fn eq<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Tests whether this object is not equal to another.\n    ///\n    /// This is equivalent to the Python expression `self != other`.\n    fn ne<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Tests whether this object is greater than another.\n    ///\n    /// This is equivalent to the Python expression `self > other`.\n    fn gt<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Tests whether this object is greater than or equal to another.\n    ///\n    /// This is equivalent to the Python expression `self >= other`.\n    fn ge<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self + other`.\n    fn add<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self - other`.\n    fn sub<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self * other`.\n    fn mul<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self @ other`.\n    fn matmul<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self / other`.\n    fn div<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self // other`.\n    fn floor_div<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self % other`.\n    fn rem<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `divmod(self, other)`.\n    fn divmod<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self << other`.\n    fn lshift<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self >> other`.\n    fn rshift<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self ** other % modulus` (`pow(self, other, modulus)`).\n    /// `py.None()` may be passed for the `modulus`.\n    fn pow<O1, O2>(&self, other: O1, modulus: O2) -> PyResult<Bound<'py, PyAny>>\n    where\n        O1: IntoPyObject<'py>,\n        O2: IntoPyObject<'py>;\n\n    /// Computes `self & other`.\n    fn bitand<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self | other`.\n    fn bitor<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Computes `self ^ other`.\n    fn bitxor<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>;\n\n    /// Determines whether this object appears callable.\n    ///\n    /// This is equivalent to Python's [`callable()`][1] function.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let builtins = PyModule::import(py, \"builtins\")?;\n    ///     let print = builtins.getattr(\"print\")?;\n    ///     assert!(print.is_callable());\n    ///     Ok(())\n    /// })?;\n    /// # Ok(())}\n    /// ```\n    ///\n    /// This is equivalent to the Python statement `assert callable(print)`.\n    ///\n    /// Note that unless an API needs to distinguish between callable and\n    /// non-callable objects, there is no point in checking for callability.\n    /// Instead, it is better to just do the call and handle potential\n    /// exceptions.\n    ///\n    /// [1]: https://docs.python.org/3/library/functions.html#callable\n    fn is_callable(&self) -> bool;\n\n    /// Calls the object.\n    ///\n    /// This is equivalent to the Python expression `self(*args, **kwargs)`.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyDict;\n    /// use pyo3_ffi::c_str;\n    /// use std::ffi::CStr;\n    ///\n    /// const CODE: &CStr = cr#\"\n    /// def function(*args, **kwargs):\n    ///     assert args == (\"hello\",)\n    ///     assert kwargs == {\"cruel\": \"world\"}\n    ///     return \"called with args and kwargs\"\n    /// \"#;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let module = PyModule::from_code(py, CODE, c\"func.py\", c\"\")?;\n    ///     let fun = module.getattr(\"function\")?;\n    ///     let args = (\"hello\",);\n    ///     let kwargs = PyDict::new(py);\n    ///     kwargs.set_item(\"cruel\", \"world\")?;\n    ///     let result = fun.call(args, Some(&kwargs))?;\n    ///     assert_eq!(result.extract::<String>()?, \"called with args and kwargs\");\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    fn call<A>(&self, args: A, kwargs: Option<&Bound<'py, PyDict>>) -> PyResult<Bound<'py, PyAny>>\n    where\n        A: PyCallArgs<'py>;\n\n    /// Calls the object without arguments.\n    ///\n    /// This is equivalent to the Python expression `self()`.\n    ///\n    /// # Examples\n    ///\n    /// ```no_run\n    /// use pyo3::prelude::*;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let module = PyModule::import(py, \"builtins\")?;\n    ///     let help = module.getattr(\"help\")?;\n    ///     help.call0()?;\n    ///     Ok(())\n    /// })?;\n    /// # Ok(())}\n    /// ```\n    ///\n    /// This is equivalent to the Python expression `help()`.\n    fn call0(&self) -> PyResult<Bound<'py, PyAny>>;\n\n    /// Calls the object with only positional arguments.\n    ///\n    /// This is equivalent to the Python expression `self(*args)`.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3_ffi::c_str;\n    /// use std::ffi::CStr;\n    ///\n    /// const CODE: &CStr = cr#\"\n    /// def function(*args, **kwargs):\n    ///     assert args == (\"hello\",)\n    ///     assert kwargs == {}\n    ///     return \"called with args\"\n    /// \"#;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let module = PyModule::from_code(py, CODE, c\"func.py\", c\"\")?;\n    ///     let fun = module.getattr(\"function\")?;\n    ///     let args = (\"hello\",);\n    ///     let result = fun.call1(args)?;\n    ///     assert_eq!(result.extract::<String>()?, \"called with args\");\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    fn call1<A>(&self, args: A) -> PyResult<Bound<'py, PyAny>>\n    where\n        A: PyCallArgs<'py>;\n\n    /// Calls a method on the object.\n    ///\n    /// This is equivalent to the Python expression `self.name(*args, **kwargs)`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used\n    /// to intern `name`.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyDict;\n    /// use pyo3_ffi::c_str;\n    /// use std::ffi::CStr;\n    ///\n    /// const CODE: &CStr = cr#\"\n    /// class A:\n    ///     def method(self, *args, **kwargs):\n    ///         assert args == (\"hello\",)\n    ///         assert kwargs == {\"cruel\": \"world\"}\n    ///         return \"called with args and kwargs\"\n    /// a = A()\n    /// \"#;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let module = PyModule::from_code(py, CODE, c\"a.py\", c\"\")?;\n    ///     let instance = module.getattr(\"a\")?;\n    ///     let args = (\"hello\",);\n    ///     let kwargs = PyDict::new(py);\n    ///     kwargs.set_item(\"cruel\", \"world\")?;\n    ///     let result = instance.call_method(\"method\", args, Some(&kwargs))?;\n    ///     assert_eq!(result.extract::<String>()?, \"called with args and kwargs\");\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    fn call_method<N, A>(\n        &self,\n        name: N,\n        args: A,\n        kwargs: Option<&Bound<'py, PyDict>>,\n    ) -> PyResult<Bound<'py, PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n        A: PyCallArgs<'py>;\n\n    /// Calls a method on the object without arguments.\n    ///\n    /// This is equivalent to the Python expression `self.name()`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used\n    /// to intern `name`.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3_ffi::c_str;\n    /// use std::ffi::CStr;\n    ///\n    /// const CODE: &CStr = cr#\"\n    /// class A:\n    ///     def method(self, *args, **kwargs):\n    ///         assert args == ()\n    ///         assert kwargs == {}\n    ///         return \"called with no arguments\"\n    /// a = A()\n    /// \"#;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let module = PyModule::from_code(py, CODE, c\"a.py\", c\"\")?;\n    ///     let instance = module.getattr(\"a\")?;\n    ///     let result = instance.call_method0(\"method\")?;\n    ///     assert_eq!(result.extract::<String>()?, \"called with no arguments\");\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    fn call_method0<N>(&self, name: N) -> PyResult<Bound<'py, PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>;\n\n    /// Calls a method on the object with only positional arguments.\n    ///\n    /// This is equivalent to the Python expression `self.name(*args)`.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used\n    /// to intern `name`.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3_ffi::c_str;\n    /// use std::ffi::CStr;\n    ///\n    /// const CODE: &CStr = cr#\"\n    /// class A:\n    ///     def method(self, *args, **kwargs):\n    ///         assert args == (\"hello\",)\n    ///         assert kwargs == {}\n    ///         return \"called with args\"\n    /// a = A()\n    /// \"#;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let module = PyModule::from_code(py, CODE, c\"a.py\", c\"\")?;\n    ///     let instance = module.getattr(\"a\")?;\n    ///     let args = (\"hello\",);\n    ///     let result = instance.call_method1(\"method\", args)?;\n    ///     assert_eq!(result.extract::<String>()?, \"called with args\");\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    fn call_method1<N, A>(&self, name: N, args: A) -> PyResult<Bound<'py, PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n        A: PyCallArgs<'py>;\n\n    /// Returns whether the object is considered to be true.\n    ///\n    /// This is equivalent to the Python expression `bool(self)`.\n    fn is_truthy(&self) -> PyResult<bool>;\n\n    /// Returns whether the object is considered to be None.\n    ///\n    /// This is equivalent to the Python expression `self is None`.\n    fn is_none(&self) -> bool;\n\n    /// Returns true if the sequence or mapping has a length of 0.\n    ///\n    /// This is equivalent to the Python expression `len(self) == 0`.\n    fn is_empty(&self) -> PyResult<bool>;\n\n    /// Gets an item from the collection.\n    ///\n    /// This is equivalent to the Python expression `self[key]`.\n    fn get_item<K>(&self, key: K) -> PyResult<Bound<'py, PyAny>>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Sets a collection item value.\n    ///\n    /// This is equivalent to the Python expression `self[key] = value`.\n    fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>,\n        V: IntoPyObject<'py>;\n\n    /// Deletes an item from the collection.\n    ///\n    /// This is equivalent to the Python expression `del self[key]`.\n    fn del_item<K>(&self, key: K) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Takes an object and returns an iterator for it. Returns an error if the object is not\n    /// iterable.\n    ///\n    /// This is typically a new iterator but if the argument is an iterator,\n    /// this returns itself.\n    ///\n    /// # Example: Checking a Python object for iterability\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::{PyAny, PyNone};\n    ///\n    /// fn is_iterable(obj: &Bound<'_, PyAny>) -> bool {\n    ///     match obj.try_iter() {\n    ///         Ok(_) => true,\n    ///         Err(_) => false,\n    ///     }\n    /// }\n    ///\n    /// Python::attach(|py| {\n    ///     assert!(is_iterable(&vec![1, 2, 3].into_pyobject(py).unwrap()));\n    ///     assert!(!is_iterable(&PyNone::get(py)));\n    /// });\n    /// ```\n    fn try_iter(&self) -> PyResult<Bound<'py, PyIterator>>;\n\n    /// Returns the Python type object for this object's type.\n    fn get_type(&self) -> Bound<'py, PyType>;\n\n    /// Returns the Python type pointer for this object.\n    fn get_type_ptr(&self) -> *mut ffi::PyTypeObject;\n\n    /// Downcast this `PyAny` to a concrete Python type or pyclass.\n    ///\n    /// Note that you can often avoid downcasting yourself by just specifying\n    /// the desired type in function or method signatures.\n    /// However, manual downcasting is sometimes necessary.\n    ///\n    /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract).\n    ///\n    /// # Example: Downcasting to a specific Python object\n    ///\n    /// ```rust\n    /// # #![allow(deprecated)]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::{PyDict, PyList};\n    ///\n    /// Python::attach(|py| {\n    ///     let dict = PyDict::new(py);\n    ///     assert!(dict.is_instance_of::<PyAny>());\n    ///     let any = dict.as_any();\n    ///\n    ///     assert!(any.downcast::<PyDict>().is_ok());\n    ///     assert!(any.downcast::<PyList>().is_err());\n    /// });\n    /// ```\n    ///\n    /// # Example: Getting a reference to a pyclass\n    ///\n    /// This is useful if you want to mutate a `PyObject` that\n    /// might actually be a pyclass.\n    ///\n    /// ```rust\n    /// # #![allow(deprecated)]\n    /// # fn main() -> Result<(), pyo3::PyErr> {\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyclass]\n    /// struct Class {\n    ///     i: i32,\n    /// }\n    ///\n    /// Python::attach(|py| {\n    ///     let class = Py::new(py, Class { i: 0 }).unwrap().into_bound(py).into_any();\n    ///\n    ///     let class_bound: &Bound<'_, Class> = class.downcast()?;\n    ///\n    ///     class_bound.borrow_mut().i += 1;\n    ///\n    ///     // Alternatively you can get a `PyRefMut` directly\n    ///     let class_ref: PyRefMut<'_, Class> = class.extract()?;\n    ///     assert_eq!(class_ref.i, 1);\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    #[deprecated(since = \"0.27.0\", note = \"use `Bound::cast` instead\")]\n    #[allow(deprecated)]\n    fn downcast<T>(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>>\n    where\n        T: PyTypeCheck;\n\n    /// Like `downcast` but takes ownership of `self`.\n    ///\n    /// In case of an error, it is possible to retrieve `self` again via [`DowncastIntoError::into_inner`].\n    ///\n    /// # Example\n    ///\n    /// ```rust\n    /// # #![allow(deprecated)]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::{PyDict, PyList};\n    ///\n    /// Python::attach(|py| {\n    ///     let obj: Bound<'_, PyAny> = PyDict::new(py).into_any();\n    ///\n    ///     let obj: Bound<'_, PyAny> = match obj.downcast_into::<PyList>() {\n    ///         Ok(_) => panic!(\"obj should not be a list\"),\n    ///         Err(err) => err.into_inner(),\n    ///     };\n    ///\n    ///     // obj is a dictionary\n    ///     assert!(obj.downcast_into::<PyDict>().is_ok());\n    /// })\n    /// ```\n    #[deprecated(since = \"0.27.0\", note = \"use `Bound::cast_into` instead\")]\n    #[allow(deprecated)]\n    fn downcast_into<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>>\n    where\n        T: PyTypeCheck;\n\n    /// Downcast this `PyAny` to a concrete Python type or pyclass (but not a subclass of it).\n    ///\n    /// It is almost always better to use [`PyAnyMethods::downcast`] because it accounts for Python\n    /// subtyping. Use this method only when you do not want to allow subtypes.\n    ///\n    /// The advantage of this method over [`PyAnyMethods::downcast`] is that it is faster. The implementation\n    /// of `downcast_exact` uses the equivalent of the Python expression `type(self) is T`, whereas\n    /// `downcast` uses `isinstance(self, T)`.\n    ///\n    /// For extracting a Rust-only type, see [`PyAny::extract`](struct.PyAny.html#method.extract).\n    ///\n    /// # Example: Downcasting to a specific Python object but not a subtype\n    ///\n    /// ```rust\n    /// # #![allow(deprecated)]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::{PyBool, PyInt};\n    ///\n    /// Python::attach(|py| {\n    ///     let b = PyBool::new(py, true);\n    ///     assert!(b.is_instance_of::<PyBool>());\n    ///     let any: &Bound<'_, PyAny> = b.as_any();\n    ///\n    ///     // `bool` is a subtype of `int`, so `downcast` will accept a `bool` as an `int`\n    ///     // but `downcast_exact` will not.\n    ///     assert!(any.downcast::<PyInt>().is_ok());\n    ///     assert!(any.downcast_exact::<PyInt>().is_err());\n    ///\n    ///     assert!(any.downcast_exact::<PyBool>().is_ok());\n    /// });\n    /// ```\n    #[deprecated(since = \"0.27.0\", note = \"use `Bound::cast_exact` instead\")]\n    #[allow(deprecated)]\n    fn downcast_exact<T>(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>>\n    where\n        T: PyTypeInfo;\n\n    /// Like `downcast_exact` but takes ownership of `self`.\n    #[deprecated(since = \"0.27.0\", note = \"use `Bound::cast_into_exact` instead\")]\n    #[allow(deprecated)]\n    fn downcast_into_exact<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>>\n    where\n        T: PyTypeInfo;\n\n    /// Converts this `PyAny` to a concrete Python type without checking validity.\n    ///\n    /// # Safety\n    ///\n    /// Callers must ensure that the type is valid or risk type confusion.\n    #[deprecated(since = \"0.27.0\", note = \"use `Bound::cast_unchecked` instead\")]\n    unsafe fn downcast_unchecked<T>(&self) -> &Bound<'py, T>;\n\n    /// Like `downcast_unchecked` but takes ownership of `self`.\n    ///\n    /// # Safety\n    ///\n    /// Callers must ensure that the type is valid or risk type confusion.\n    #[deprecated(since = \"0.27.0\", note = \"use `Bound::cast_into_unchecked` instead\")]\n    unsafe fn downcast_into_unchecked<T>(self) -> Bound<'py, T>;\n\n    /// Extracts some type from the Python object.\n    ///\n    /// This is a wrapper function around [`FromPyObject::extract()`](crate::FromPyObject::extract).\n    fn extract<'a, T>(&'a self) -> Result<T, T::Error>\n    where\n        T: FromPyObject<'a, 'py>;\n\n    /// Returns the reference count for the Python object.\n    #[deprecated(\n        since = \"0.29.0\",\n        note = \"use `pyo3::ffi::Py_REFCNT(obj.as_ptr())` instead\"\n    )]\n    fn get_refcnt(&self) -> isize;\n\n    /// Computes the \"repr\" representation of self.\n    ///\n    /// This is equivalent to the Python expression `repr(self)`.\n    fn repr(&self) -> PyResult<Bound<'py, PyString>>;\n\n    /// Computes the \"str\" representation of self.\n    ///\n    /// This is equivalent to the Python expression `str(self)`.\n    fn str(&self) -> PyResult<Bound<'py, PyString>>;\n\n    /// Retrieves the hash code of self.\n    ///\n    /// This is equivalent to the Python expression `hash(self)`.\n    fn hash(&self) -> PyResult<isize>;\n\n    /// Returns the length of the sequence or mapping.\n    ///\n    /// This is equivalent to the Python expression `len(self)`.\n    fn len(&self) -> PyResult<usize>;\n\n    /// Returns the list of attributes of this object.\n    ///\n    /// This is equivalent to the Python expression `dir(self)`.\n    fn dir(&self) -> PyResult<Bound<'py, PyList>>;\n\n    /// Checks whether this object is an instance of type `ty`.\n    ///\n    /// This is equivalent to the Python expression `isinstance(self, ty)`.\n    fn is_instance(&self, ty: &Bound<'py, PyAny>) -> PyResult<bool>;\n\n    /// Checks whether this object is an instance of exactly type `ty` (not a subclass).\n    ///\n    /// This is equivalent to the Python expression `type(self) is ty`.\n    fn is_exact_instance(&self, ty: &Bound<'py, PyAny>) -> bool;\n\n    /// Checks whether this object is an instance of type `T`.\n    ///\n    /// This is equivalent to the Python expression `isinstance(self, T)`,\n    /// if the type `T` is known at compile time.\n    fn is_instance_of<T: PyTypeCheck>(&self) -> bool;\n\n    /// Checks whether this object is an instance of exactly type `T`.\n    ///\n    /// This is equivalent to the Python expression `type(self) is T`,\n    /// if the type `T` is known at compile time.\n    fn is_exact_instance_of<T: PyTypeInfo>(&self) -> bool;\n\n    /// Determines if self contains `value`.\n    ///\n    /// This is equivalent to the Python expression `value in self`.\n    fn contains<V>(&self, value: V) -> PyResult<bool>\n    where\n        V: IntoPyObject<'py>;\n\n    /// Return a proxy object that delegates method calls to a parent or sibling class of type.\n    ///\n    /// This is equivalent to the Python expression `super()`\n    fn py_super(&self) -> PyResult<Bound<'py, PySuper>>;\n}\n\nmacro_rules! implement_binop {\n    ($name:ident, $c_api:ident, $op:expr) => {\n        #[doc = concat!(\"Computes `self \", $op, \" other`.\")]\n        fn $name<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n        where\n            O: IntoPyObject<'py>,\n        {\n            fn inner<'py>(\n                any: &Bound<'py, PyAny>,\n                other: Borrowed<'_, 'py, PyAny>,\n            ) -> PyResult<Bound<'py, PyAny>> {\n                unsafe { ffi::$c_api(any.as_ptr(), other.as_ptr()).assume_owned_or_err(any.py()) }\n            }\n\n            let py = self.py();\n            inner(\n                self,\n                other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n            )\n        }\n    };\n}\n\nimpl<'py> PyAnyMethods<'py> for Bound<'py, PyAny> {\n    #[inline]\n    fn is<T: AsRef<Py<PyAny>>>(&self, other: T) -> bool {\n        ptr::eq(self.as_ptr(), other.as_ref().as_ptr())\n    }\n\n    fn hasattr<N>(&self, attr_name: N) -> PyResult<bool>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n    {\n        // PyObject_HasAttr suppresses all exceptions, which was the behaviour of `hasattr` in Python 2.\n        // Use an implementation which suppresses only AttributeError, which is consistent with `hasattr` in Python 3.\n        fn inner(py: Python<'_>, getattr_result: PyResult<Bound<'_, PyAny>>) -> PyResult<bool> {\n            match getattr_result {\n                Ok(_) => Ok(true),\n                Err(err) if err.is_instance_of::<PyAttributeError>(py) => Ok(false),\n                Err(e) => Err(e),\n            }\n        }\n\n        inner(self.py(), self.getattr(attr_name))\n    }\n\n    fn getattr<N>(&self, attr_name: N) -> PyResult<Bound<'py, PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n    {\n        fn inner<'py>(\n            any: &Bound<'py, PyAny>,\n            attr_name: Borrowed<'_, '_, PyString>,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            unsafe {\n                ffi::PyObject_GetAttr(any.as_ptr(), attr_name.as_ptr())\n                    .assume_owned_or_err(any.py())\n            }\n        }\n\n        inner(\n            self,\n            attr_name\n                .into_pyobject(self.py())\n                .map_err(Into::into)?\n                .as_borrowed(),\n        )\n    }\n\n    fn getattr_opt<N>(&self, attr_name: N) -> PyResult<Option<Bound<'py, PyAny>>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n    {\n        fn inner<'py>(\n            any: &Bound<'py, PyAny>,\n            attr_name: Borrowed<'_, 'py, PyString>,\n        ) -> PyResult<Option<Bound<'py, PyAny>>> {\n            #[cfg(Py_3_13)]\n            {\n                let mut resp_ptr: *mut ffi::PyObject = std::ptr::null_mut();\n                match unsafe {\n                    ffi::PyObject_GetOptionalAttr(any.as_ptr(), attr_name.as_ptr(), &mut resp_ptr)\n                } {\n                    // Attribute found, result is a new strong reference\n                    1 => {\n                        let bound = unsafe { Bound::from_owned_ptr(any.py(), resp_ptr) };\n                        Ok(Some(bound))\n                    }\n                    // Attribute not found, result is NULL\n                    0 => Ok(None),\n\n                    // An error occurred (other than AttributeError)\n                    _ => Err(PyErr::fetch(any.py())),\n                }\n            }\n\n            #[cfg(not(Py_3_13))]\n            {\n                match any.getattr(attr_name) {\n                    Ok(bound) => Ok(Some(bound)),\n                    Err(err) => {\n                        let err_type = err\n                            .get_type(any.py())\n                            .is(PyType::new::<PyAttributeError>(any.py()));\n                        match err_type {\n                            true => Ok(None),\n                            false => Err(err),\n                        }\n                    }\n                }\n            }\n        }\n\n        let py = self.py();\n        inner(self, attr_name.into_pyobject_or_pyerr(py)?.as_borrowed())\n    }\n\n    fn setattr<N, V>(&self, attr_name: N, value: V) -> PyResult<()>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n        V: IntoPyObject<'py>,\n    {\n        fn inner(\n            any: &Bound<'_, PyAny>,\n            attr_name: Borrowed<'_, '_, PyString>,\n            value: Borrowed<'_, '_, PyAny>,\n        ) -> PyResult<()> {\n            err::error_on_minusone(any.py(), unsafe {\n                ffi::PyObject_SetAttr(any.as_ptr(), attr_name.as_ptr(), value.as_ptr())\n            })\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            attr_name.into_pyobject_or_pyerr(py)?.as_borrowed(),\n            value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn delattr<N>(&self, attr_name: N) -> PyResult<()>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n    {\n        fn inner(any: &Bound<'_, PyAny>, attr_name: Borrowed<'_, '_, PyString>) -> PyResult<()> {\n            err::error_on_minusone(any.py(), unsafe {\n                ffi::PyObject_DelAttr(any.as_ptr(), attr_name.as_ptr())\n            })\n        }\n\n        let py = self.py();\n        inner(self, attr_name.into_pyobject_or_pyerr(py)?.as_borrowed())\n    }\n\n    fn compare<O>(&self, other: O) -> PyResult<Ordering>\n    where\n        O: IntoPyObject<'py>,\n    {\n        fn inner(any: &Bound<'_, PyAny>, other: Borrowed<'_, '_, PyAny>) -> PyResult<Ordering> {\n            let other = other.as_ptr();\n            // Almost the same as ffi::PyObject_RichCompareBool, but this one doesn't try self == other.\n            // See https://github.com/PyO3/pyo3/issues/985 for more.\n            let do_compare = |other, op| unsafe {\n                ffi::PyObject_RichCompare(any.as_ptr(), other, op)\n                    .assume_owned_or_err(any.py())\n                    .and_then(|obj| obj.is_truthy())\n            };\n            if do_compare(other, ffi::Py_EQ)? {\n                Ok(Ordering::Equal)\n            } else if do_compare(other, ffi::Py_LT)? {\n                Ok(Ordering::Less)\n            } else if do_compare(other, ffi::Py_GT)? {\n                Ok(Ordering::Greater)\n            } else {\n                Err(PyTypeError::new_err(\n                    \"PyAny::compare(): All comparisons returned false\",\n                ))\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn rich_compare<O>(&self, other: O, compare_op: CompareOp) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>,\n    {\n        fn inner<'py>(\n            any: &Bound<'py, PyAny>,\n            other: Borrowed<'_, 'py, PyAny>,\n            compare_op: CompareOp,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            unsafe {\n                ffi::PyObject_RichCompare(any.as_ptr(), other.as_ptr(), compare_op as c_int)\n                    .assume_owned_or_err(any.py())\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n            compare_op,\n        )\n    }\n\n    fn neg(&self) -> PyResult<Bound<'py, PyAny>> {\n        unsafe { ffi::PyNumber_Negative(self.as_ptr()).assume_owned_or_err(self.py()) }\n    }\n\n    fn pos(&self) -> PyResult<Bound<'py, PyAny>> {\n        fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> {\n            unsafe { ffi::PyNumber_Positive(any.as_ptr()).assume_owned_or_err(any.py()) }\n        }\n\n        inner(self)\n    }\n\n    fn abs(&self) -> PyResult<Bound<'py, PyAny>> {\n        fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> {\n            unsafe { ffi::PyNumber_Absolute(any.as_ptr()).assume_owned_or_err(any.py()) }\n        }\n\n        inner(self)\n    }\n\n    fn bitnot(&self) -> PyResult<Bound<'py, PyAny>> {\n        fn inner<'py>(any: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> {\n            unsafe { ffi::PyNumber_Invert(any.as_ptr()).assume_owned_or_err(any.py()) }\n        }\n\n        inner(self)\n    }\n\n    fn lt<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>,\n    {\n        self.rich_compare(other, CompareOp::Lt)\n            .and_then(|any| any.is_truthy())\n    }\n\n    fn le<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>,\n    {\n        self.rich_compare(other, CompareOp::Le)\n            .and_then(|any| any.is_truthy())\n    }\n\n    fn eq<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>,\n    {\n        self.rich_compare(other, CompareOp::Eq)\n            .and_then(|any| any.is_truthy())\n    }\n\n    fn ne<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>,\n    {\n        self.rich_compare(other, CompareOp::Ne)\n            .and_then(|any| any.is_truthy())\n    }\n\n    fn gt<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>,\n    {\n        self.rich_compare(other, CompareOp::Gt)\n            .and_then(|any| any.is_truthy())\n    }\n\n    fn ge<O>(&self, other: O) -> PyResult<bool>\n    where\n        O: IntoPyObject<'py>,\n    {\n        self.rich_compare(other, CompareOp::Ge)\n            .and_then(|any| any.is_truthy())\n    }\n\n    implement_binop!(add, PyNumber_Add, \"+\");\n    implement_binop!(sub, PyNumber_Subtract, \"-\");\n    implement_binop!(mul, PyNumber_Multiply, \"*\");\n    implement_binop!(matmul, PyNumber_MatrixMultiply, \"@\");\n    implement_binop!(div, PyNumber_TrueDivide, \"/\");\n    implement_binop!(floor_div, PyNumber_FloorDivide, \"//\");\n    implement_binop!(rem, PyNumber_Remainder, \"%\");\n    implement_binop!(lshift, PyNumber_Lshift, \"<<\");\n    implement_binop!(rshift, PyNumber_Rshift, \">>\");\n    implement_binop!(bitand, PyNumber_And, \"&\");\n    implement_binop!(bitor, PyNumber_Or, \"|\");\n    implement_binop!(bitxor, PyNumber_Xor, \"^\");\n\n    /// Computes `divmod(self, other)`.\n    fn divmod<O>(&self, other: O) -> PyResult<Bound<'py, PyAny>>\n    where\n        O: IntoPyObject<'py>,\n    {\n        fn inner<'py>(\n            any: &Bound<'py, PyAny>,\n            other: Borrowed<'_, 'py, PyAny>,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            unsafe {\n                ffi::PyNumber_Divmod(any.as_ptr(), other.as_ptr()).assume_owned_or_err(any.py())\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    /// Computes `self ** other % modulus` (`pow(self, other, modulus)`).\n    /// `py.None()` may be passed for the `modulus`.\n    fn pow<O1, O2>(&self, other: O1, modulus: O2) -> PyResult<Bound<'py, PyAny>>\n    where\n        O1: IntoPyObject<'py>,\n        O2: IntoPyObject<'py>,\n    {\n        fn inner<'py>(\n            any: &Bound<'py, PyAny>,\n            other: Borrowed<'_, 'py, PyAny>,\n            modulus: Borrowed<'_, 'py, PyAny>,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            unsafe {\n                ffi::PyNumber_Power(any.as_ptr(), other.as_ptr(), modulus.as_ptr())\n                    .assume_owned_or_err(any.py())\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            other.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n            modulus.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn is_callable(&self) -> bool {\n        unsafe { ffi::PyCallable_Check(self.as_ptr()) != 0 }\n    }\n\n    fn call<A>(&self, args: A, kwargs: Option<&Bound<'py, PyDict>>) -> PyResult<Bound<'py, PyAny>>\n    where\n        A: PyCallArgs<'py>,\n    {\n        if let Some(kwargs) = kwargs {\n            args.call(\n                self.as_borrowed(),\n                kwargs.as_borrowed(),\n                crate::call::private::Token,\n            )\n        } else {\n            args.call_positional(self.as_borrowed(), crate::call::private::Token)\n        }\n    }\n\n    #[inline]\n    fn call0(&self) -> PyResult<Bound<'py, PyAny>> {\n        unsafe { ffi::compat::PyObject_CallNoArgs(self.as_ptr()).assume_owned_or_err(self.py()) }\n    }\n\n    fn call1<A>(&self, args: A) -> PyResult<Bound<'py, PyAny>>\n    where\n        A: PyCallArgs<'py>,\n    {\n        args.call_positional(self.as_borrowed(), crate::call::private::Token)\n    }\n\n    #[inline]\n    fn call_method<N, A>(\n        &self,\n        name: N,\n        args: A,\n        kwargs: Option<&Bound<'py, PyDict>>,\n    ) -> PyResult<Bound<'py, PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n        A: PyCallArgs<'py>,\n    {\n        if kwargs.is_none() {\n            self.call_method1(name, args)\n        } else {\n            self.getattr(name)\n                .and_then(|method| method.call(args, kwargs))\n        }\n    }\n\n    #[inline]\n    fn call_method0<N>(&self, name: N) -> PyResult<Bound<'py, PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n    {\n        let py = self.py();\n        let name = name.into_pyobject_or_pyerr(py)?.into_bound();\n        unsafe {\n            ffi::compat::PyObject_CallMethodNoArgs(self.as_ptr(), name.as_ptr())\n                .assume_owned_or_err(py)\n        }\n    }\n\n    fn call_method1<N, A>(&self, name: N, args: A) -> PyResult<Bound<'py, PyAny>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n        A: PyCallArgs<'py>,\n    {\n        let name = name.into_pyobject_or_pyerr(self.py())?;\n        args.call_method_positional(\n            self.as_borrowed(),\n            name.as_borrowed(),\n            crate::call::private::Token,\n        )\n    }\n\n    fn is_truthy(&self) -> PyResult<bool> {\n        let v = unsafe { ffi::PyObject_IsTrue(self.as_ptr()) };\n        err::error_on_minusone(self.py(), v)?;\n        Ok(v != 0)\n    }\n\n    #[inline]\n    fn is_none(&self) -> bool {\n        unsafe { ptr::eq(ffi::Py_None(), self.as_ptr()) }\n    }\n\n    fn is_empty(&self) -> PyResult<bool> {\n        self.len().map(|l| l == 0)\n    }\n\n    fn get_item<K>(&self, key: K) -> PyResult<Bound<'py, PyAny>>\n    where\n        K: IntoPyObject<'py>,\n    {\n        fn inner<'py>(\n            any: &Bound<'py, PyAny>,\n            key: Borrowed<'_, 'py, PyAny>,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            unsafe {\n                ffi::PyObject_GetItem(any.as_ptr(), key.as_ptr()).assume_owned_or_err(any.py())\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>,\n        V: IntoPyObject<'py>,\n    {\n        fn inner(\n            any: &Bound<'_, PyAny>,\n            key: Borrowed<'_, '_, PyAny>,\n            value: Borrowed<'_, '_, PyAny>,\n        ) -> PyResult<()> {\n            err::error_on_minusone(any.py(), unsafe {\n                ffi::PyObject_SetItem(any.as_ptr(), key.as_ptr(), value.as_ptr())\n            })\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n            value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn del_item<K>(&self, key: K) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>,\n    {\n        fn inner(any: &Bound<'_, PyAny>, key: Borrowed<'_, '_, PyAny>) -> PyResult<()> {\n            err::error_on_minusone(any.py(), unsafe {\n                ffi::PyObject_DelItem(any.as_ptr(), key.as_ptr())\n            })\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn try_iter(&self) -> PyResult<Bound<'py, PyIterator>> {\n        PyIterator::from_object(self)\n    }\n\n    fn get_type(&self) -> Bound<'py, PyType> {\n        unsafe { PyType::from_borrowed_type_ptr(self.py(), ffi::Py_TYPE(self.as_ptr())) }\n    }\n\n    #[inline]\n    fn get_type_ptr(&self) -> *mut ffi::PyTypeObject {\n        unsafe { ffi::Py_TYPE(self.as_ptr()) }\n    }\n\n    #[inline]\n    #[allow(deprecated)]\n    fn downcast<T>(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>>\n    where\n        T: PyTypeCheck,\n    {\n        if T::type_check(self) {\n            // Safety: type_check is responsible for ensuring that the type is correct\n            Ok(unsafe { self.cast_unchecked() })\n        } else {\n            #[allow(deprecated)]\n            Err(DowncastError::new(self, T::NAME))\n        }\n    }\n\n    #[inline]\n    #[allow(deprecated)]\n    fn downcast_into<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>>\n    where\n        T: PyTypeCheck,\n    {\n        if T::type_check(&self) {\n            // Safety: type_check is responsible for ensuring that the type is correct\n            Ok(unsafe { self.cast_into_unchecked() })\n        } else {\n            #[allow(deprecated)]\n            Err(DowncastIntoError::new(self, T::NAME))\n        }\n    }\n\n    #[inline]\n    #[allow(deprecated)]\n    fn downcast_exact<T>(&self) -> Result<&Bound<'py, T>, DowncastError<'_, 'py>>\n    where\n        T: PyTypeInfo,\n    {\n        if T::is_exact_type_of(self) {\n            // Safety: is_exact_type_of is responsible for ensuring that the type is correct\n            Ok(unsafe { self.cast_unchecked() })\n        } else {\n            #[allow(deprecated)]\n            Err(DowncastError::new(self, T::NAME))\n        }\n    }\n\n    #[inline]\n    #[allow(deprecated)]\n    fn downcast_into_exact<T>(self) -> Result<Bound<'py, T>, DowncastIntoError<'py>>\n    where\n        T: PyTypeInfo,\n    {\n        if T::is_exact_type_of(&self) {\n            // Safety: is_exact_type_of is responsible for ensuring that the type is correct\n            Ok(unsafe { self.cast_into_unchecked() })\n        } else {\n            #[allow(deprecated)]\n            Err(DowncastIntoError::new(self, T::NAME))\n        }\n    }\n\n    #[inline]\n    unsafe fn downcast_unchecked<T>(&self) -> &Bound<'py, T> {\n        unsafe { self.cast_unchecked() }\n    }\n\n    #[inline]\n    unsafe fn downcast_into_unchecked<T>(self) -> Bound<'py, T> {\n        unsafe { self.cast_into_unchecked() }\n    }\n\n    fn extract<'a, T>(&'a self) -> Result<T, T::Error>\n    where\n        T: FromPyObject<'a, 'py>,\n    {\n        FromPyObject::extract(self.as_borrowed())\n    }\n\n    fn get_refcnt(&self) -> isize {\n        self._get_refcnt()\n    }\n\n    fn repr(&self) -> PyResult<Bound<'py, PyString>> {\n        unsafe {\n            ffi::PyObject_Repr(self.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    fn str(&self) -> PyResult<Bound<'py, PyString>> {\n        unsafe {\n            ffi::PyObject_Str(self.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    fn hash(&self) -> PyResult<isize> {\n        let v = unsafe { ffi::PyObject_Hash(self.as_ptr()) };\n        crate::err::error_on_minusone(self.py(), v)?;\n        Ok(v)\n    }\n\n    fn len(&self) -> PyResult<usize> {\n        let v = unsafe { ffi::PyObject_Size(self.as_ptr()) };\n        crate::err::error_on_minusone(self.py(), v)?;\n        Ok(v as usize)\n    }\n\n    fn dir(&self) -> PyResult<Bound<'py, PyList>> {\n        unsafe {\n            ffi::PyObject_Dir(self.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    #[inline]\n    fn is_instance(&self, ty: &Bound<'py, PyAny>) -> PyResult<bool> {\n        let result = unsafe { ffi::PyObject_IsInstance(self.as_ptr(), ty.as_ptr()) };\n        err::error_on_minusone(self.py(), result)?;\n        Ok(result == 1)\n    }\n\n    #[inline]\n    fn is_exact_instance(&self, ty: &Bound<'py, PyAny>) -> bool {\n        self.get_type().is(ty)\n    }\n\n    #[inline]\n    fn is_instance_of<T: PyTypeCheck>(&self) -> bool {\n        T::type_check(self)\n    }\n\n    #[inline]\n    fn is_exact_instance_of<T: PyTypeInfo>(&self) -> bool {\n        T::is_exact_type_of(self)\n    }\n\n    fn contains<V>(&self, value: V) -> PyResult<bool>\n    where\n        V: IntoPyObject<'py>,\n    {\n        fn inner(any: &Bound<'_, PyAny>, value: Borrowed<'_, '_, PyAny>) -> PyResult<bool> {\n            match unsafe { ffi::PySequence_Contains(any.as_ptr(), value.as_ptr()) } {\n                0 => Ok(false),\n                1 => Ok(true),\n                _ => Err(PyErr::fetch(any.py())),\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn py_super(&self) -> PyResult<Bound<'py, PySuper>> {\n        PySuper::new(&self.get_type(), self)\n    }\n}\n\nimpl<'py> Bound<'py, PyAny> {\n    /// Retrieve an attribute value, skipping the instance dictionary during the lookup but still\n    /// binding the object to the instance.\n    ///\n    /// This is useful when trying to resolve Python's \"magic\" methods like `__getitem__`, which\n    /// are looked up starting from the type object.  This returns an `Option` as it is not\n    /// typically a direct error for the special lookup to fail, as magic methods are optional in\n    /// many situations in which they might be called.\n    ///\n    /// To avoid repeated temporary allocations of Python strings, the [`intern!`] macro can be used\n    /// to intern `attr_name`.\n    #[allow(dead_code, reason = \"currently only used with num-complex + abi3\")]\n    pub(crate) fn lookup_special<N>(&self, attr_name: N) -> PyResult<Option<Bound<'py, PyAny>>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n    {\n        let py = self.py();\n        let self_type = self.get_type();\n        let attr = if let Ok(attr) = self_type.getattr(attr_name) {\n            attr\n        } else {\n            return Ok(None);\n        };\n\n        // Manually resolve descriptor protocol. (Faster than going through Python.)\n        if let Some(descr_get) = attr.get_type().get_slot(TP_DESCR_GET) {\n            // attribute is a descriptor, resolve it\n            unsafe {\n                descr_get(attr.as_ptr(), self.as_ptr(), self_type.as_ptr())\n                    .assume_owned_or_err(py)\n                    .map(Some)\n            }\n        } else {\n            Ok(Some(attr))\n        }\n    }\n\n    #[inline]\n    pub(crate) fn _get_refcnt(&self) -> isize {\n        unsafe { ffi::Py_REFCNT(self.as_ptr()) }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::{\n        basic::CompareOp,\n        test_utils::generate_unique_module_name,\n        types::{IntoPyDict, PyAny, PyAnyMethods, PyBool, PyInt, PyList, PyModule, PyTypeMethods},\n        Bound, BoundObject, IntoPyObject, PyTypeInfo, Python,\n    };\n    use pyo3_ffi::c_str;\n    use std::fmt::Debug;\n\n    #[test]\n    fn test_lookup_special() {\n        Python::attach(|py| {\n            let module = PyModule::from_code(\n                py,\n                cr#\"\nclass CustomCallable:\n    def __call__(self):\n        return 1\n\nclass SimpleInt:\n    def __int__(self):\n        return 1\n\nclass InheritedInt(SimpleInt): pass\n\nclass NoInt: pass\n\nclass NoDescriptorInt:\n    __int__ = CustomCallable()\n\nclass InstanceOverrideInt:\n    def __int__(self):\n        return 1\ninstance_override = InstanceOverrideInt()\ninstance_override.__int__ = lambda self: 2\n\nclass ErrorInDescriptorInt:\n    @property\n    def __int__(self):\n        raise ValueError(\"uh-oh!\")\n\nclass NonHeapNonDescriptorInt:\n    # A static-typed callable that doesn't implement `__get__`.  These are pretty hard to come by.\n    __int__ = int\n                \"#,\n                c\"test.py\",\n                &generate_unique_module_name(\"test\"),\n            )\n            .unwrap();\n\n            let int = crate::intern!(py, \"__int__\");\n            let eval_int =\n                |obj: Bound<'_, PyAny>| obj.lookup_special(int)?.unwrap().call0()?.extract::<u32>();\n\n            let simple = module.getattr(\"SimpleInt\").unwrap().call0().unwrap();\n            assert_eq!(eval_int(simple).unwrap(), 1);\n            let inherited = module.getattr(\"InheritedInt\").unwrap().call0().unwrap();\n            assert_eq!(eval_int(inherited).unwrap(), 1);\n            let no_descriptor = module.getattr(\"NoDescriptorInt\").unwrap().call0().unwrap();\n            assert_eq!(eval_int(no_descriptor).unwrap(), 1);\n            let missing = module.getattr(\"NoInt\").unwrap().call0().unwrap();\n            assert!(missing.lookup_special(int).unwrap().is_none());\n            // Note the instance override should _not_ call the instance method that returns 2,\n            // because that's not how special lookups are meant to work.\n            let instance_override = module.getattr(\"instance_override\").unwrap();\n            assert_eq!(eval_int(instance_override).unwrap(), 1);\n            let descriptor_error = module\n                .getattr(\"ErrorInDescriptorInt\")\n                .unwrap()\n                .call0()\n                .unwrap();\n            assert!(descriptor_error.lookup_special(int).is_err());\n            let nonheap_nondescriptor = module\n                .getattr(\"NonHeapNonDescriptorInt\")\n                .unwrap()\n                .call0()\n                .unwrap();\n            assert_eq!(eval_int(nonheap_nondescriptor).unwrap(), 0);\n        })\n    }\n\n    #[test]\n    fn test_getattr_opt() {\n        Python::attach(|py| {\n            let module = PyModule::from_code(\n                py,\n                cr#\"\nclass Test:\n    class_str_attribute = \"class_string\"\n\n    @property\n    def error(self):\n        raise ValueError(\"This is an intentional error\")\n                \"#,\n                c\"test.py\",\n                &generate_unique_module_name(\"test\"),\n            )\n            .unwrap();\n\n            // Get the class Test\n            let class_test = module.getattr_opt(\"Test\").unwrap().unwrap();\n\n            // Test attribute that exist\n            let cls_attr_str = class_test\n                .getattr_opt(\"class_str_attribute\")\n                .unwrap()\n                .unwrap();\n            assert_eq!(cls_attr_str.extract::<String>().unwrap(), \"class_string\");\n\n            // Test non-existent attribute\n            let do_not_exist = class_test.getattr_opt(\"doNotExist\").unwrap();\n            assert!(do_not_exist.is_none());\n\n            // Test error attribute\n            let instance = class_test.call0().unwrap();\n            let error = instance.getattr_opt(\"error\");\n            assert!(error.is_err());\n            assert!(error\n                .unwrap_err()\n                .to_string()\n                .contains(\"This is an intentional error\"));\n        });\n    }\n\n    #[test]\n    fn test_call_for_non_existing_method() {\n        Python::attach(|py| {\n            let a = py.eval(c\"42\", None, None).unwrap();\n            a.call_method0(\"__str__\").unwrap(); // ok\n            assert!(a.call_method(\"nonexistent_method\", (1,), None).is_err());\n            assert!(a.call_method0(\"nonexistent_method\").is_err());\n            assert!(a.call_method1(\"nonexistent_method\", (1,)).is_err());\n        });\n    }\n\n    #[test]\n    fn test_call_with_kwargs() {\n        Python::attach(|py| {\n            let list = vec![3, 6, 5, 4, 7].into_pyobject(py).unwrap();\n            let dict = vec![(\"reverse\", true)].into_py_dict(py).unwrap();\n            list.call_method(\"sort\", (), Some(&dict)).unwrap();\n            assert_eq!(list.extract::<Vec<i32>>().unwrap(), vec![7, 6, 5, 4, 3]);\n        });\n    }\n\n    #[test]\n    fn test_call_method0() {\n        Python::attach(|py| {\n            let module = PyModule::from_code(\n                py,\n                cr#\"\nclass SimpleClass:\n    def foo(self):\n        return 42\n\"#,\n                c_str!(file!()),\n                &generate_unique_module_name(\"test_module\"),\n            )\n            .expect(\"module creation failed\");\n\n            let simple_class = module.getattr(\"SimpleClass\").unwrap().call0().unwrap();\n            assert_eq!(\n                simple_class\n                    .call_method0(\"foo\")\n                    .unwrap()\n                    .extract::<u32>()\n                    .unwrap(),\n                42\n            );\n        })\n    }\n\n    #[test]\n    fn test_type() {\n        Python::attach(|py| {\n            let obj = py.eval(c\"42\", None, None).unwrap();\n            assert_eq!(obj.get_type().as_type_ptr(), obj.get_type_ptr());\n        });\n    }\n\n    #[test]\n    fn test_dir() {\n        Python::attach(|py| {\n            let obj = py.eval(c\"42\", None, None).unwrap();\n            let dir = py\n                .eval(c\"dir(42)\", None, None)\n                .unwrap()\n                .cast_into::<PyList>()\n                .unwrap();\n            let a = obj\n                .dir()\n                .unwrap()\n                .into_iter()\n                .map(|x| x.extract::<String>().unwrap());\n            let b = dir.into_iter().map(|x| x.extract::<String>().unwrap());\n            assert!(a.eq(b));\n        });\n    }\n\n    #[test]\n    fn test_hasattr() {\n        Python::attach(|py| {\n            let x = 5i32.into_pyobject(py).unwrap();\n            assert!(x.is_instance_of::<PyInt>());\n\n            assert!(x.hasattr(\"to_bytes\").unwrap());\n            assert!(!x.hasattr(\"bbbbbbytes\").unwrap());\n        })\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[test]\n    #[allow(unknown_lints, non_local_definitions)]\n    fn test_hasattr_error() {\n        use crate::exceptions::PyValueError;\n        use crate::prelude::*;\n\n        #[pyclass(crate = \"crate\")]\n        struct GetattrFail;\n\n        #[pymethods(crate = \"crate\")]\n        impl GetattrFail {\n            fn __getattr__(&self, attr: Py<PyAny>) -> PyResult<Py<PyAny>> {\n                Err(PyValueError::new_err(attr))\n            }\n        }\n\n        Python::attach(|py| {\n            let obj = Py::new(py, GetattrFail).unwrap();\n            let obj = obj.bind(py).as_any();\n\n            assert!(obj\n                .hasattr(\"foo\")\n                .unwrap_err()\n                .is_instance_of::<PyValueError>(py));\n        })\n    }\n\n    #[test]\n    fn test_nan_eq() {\n        Python::attach(|py| {\n            let nan = py.eval(c\"float('nan')\", None, None).unwrap();\n            assert!(nan.compare(&nan).is_err());\n        });\n    }\n\n    #[test]\n    fn test_any_is_instance_of() {\n        Python::attach(|py| {\n            let x = 5i32.into_pyobject(py).unwrap();\n            assert!(x.is_instance_of::<PyInt>());\n\n            let l = vec![&x, &x].into_pyobject(py).unwrap();\n            assert!(l.is_instance_of::<PyList>());\n        });\n    }\n\n    #[test]\n    fn test_any_is_instance() {\n        Python::attach(|py| {\n            let l = vec![1i8, 2].into_pyobject(py).unwrap();\n            assert!(l.is_instance(&py.get_type::<PyList>()).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_any_is_exact_instance_of() {\n        Python::attach(|py| {\n            let x = 5i32.into_pyobject(py).unwrap();\n            assert!(x.is_exact_instance_of::<PyInt>());\n\n            let t = PyBool::new(py, true);\n            assert!(t.is_instance_of::<PyInt>());\n            assert!(!t.is_exact_instance_of::<PyInt>());\n            assert!(t.is_exact_instance_of::<PyBool>());\n\n            let l = vec![&x, &x].into_pyobject(py).unwrap();\n            assert!(l.is_exact_instance_of::<PyList>());\n        });\n    }\n\n    #[test]\n    fn test_any_is_exact_instance() {\n        Python::attach(|py| {\n            let t = PyBool::new(py, true);\n            assert!(t.is_instance(&py.get_type::<PyInt>()).unwrap());\n            assert!(!t.is_exact_instance(&py.get_type::<PyInt>()));\n            assert!(t.is_exact_instance(&py.get_type::<PyBool>()));\n        });\n    }\n\n    #[test]\n    fn test_any_contains() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];\n            let ob = v.into_pyobject(py).unwrap();\n\n            let bad_needle = 7i32.into_pyobject(py).unwrap();\n            assert!(!ob.contains(&bad_needle).unwrap());\n\n            let good_needle = 8i32.into_pyobject(py).unwrap();\n            assert!(ob.contains(&good_needle).unwrap());\n\n            let type_coerced_needle = 8f32.into_pyobject(py).unwrap();\n            assert!(ob.contains(&type_coerced_needle).unwrap());\n\n            let n: u32 = 42;\n            let bad_haystack = n.into_pyobject(py).unwrap();\n            let irrelevant_needle = 0i32.into_pyobject(py).unwrap();\n            assert!(bad_haystack.contains(&irrelevant_needle).is_err());\n        });\n    }\n\n    // This is intentionally not a test, it's a generic function used by the tests below.\n    fn test_eq_methods_generic<'a, T>(list: &'a [T])\n    where\n        T: PartialEq + PartialOrd,\n        for<'py> &'a T: IntoPyObject<'py>,\n        for<'py> <&'a T as IntoPyObject<'py>>::Error: Debug,\n    {\n        Python::attach(|py| {\n            for a in list {\n                for b in list {\n                    let a_py = a.into_pyobject(py).unwrap().into_any().into_bound();\n                    let b_py = b.into_pyobject(py).unwrap().into_any().into_bound();\n\n                    assert_eq!(\n                        a.lt(b),\n                        a_py.lt(&b_py).unwrap(),\n                        \"{} < {} should be {}.\",\n                        a_py,\n                        b_py,\n                        a.lt(b)\n                    );\n                    assert_eq!(\n                        a.le(b),\n                        a_py.le(&b_py).unwrap(),\n                        \"{} <= {} should be {}.\",\n                        a_py,\n                        b_py,\n                        a.le(b)\n                    );\n                    assert_eq!(\n                        a.eq(b),\n                        a_py.eq(&b_py).unwrap(),\n                        \"{} == {} should be {}.\",\n                        a_py,\n                        b_py,\n                        a.eq(b)\n                    );\n                    assert_eq!(\n                        a.ne(b),\n                        a_py.ne(&b_py).unwrap(),\n                        \"{} != {} should be {}.\",\n                        a_py,\n                        b_py,\n                        a.ne(b)\n                    );\n                    assert_eq!(\n                        a.gt(b),\n                        a_py.gt(&b_py).unwrap(),\n                        \"{} > {} should be {}.\",\n                        a_py,\n                        b_py,\n                        a.gt(b)\n                    );\n                    assert_eq!(\n                        a.ge(b),\n                        a_py.ge(&b_py).unwrap(),\n                        \"{} >= {} should be {}.\",\n                        a_py,\n                        b_py,\n                        a.ge(b)\n                    );\n                }\n            }\n        });\n    }\n\n    #[test]\n    fn test_eq_methods_integers() {\n        let ints = [-4, -4, 1, 2, 0, -100, 1_000_000];\n        test_eq_methods_generic::<i32>(&ints);\n    }\n\n    #[test]\n    fn test_eq_methods_strings() {\n        let strings = [\"Let's\", \"test\", \"some\", \"eq\", \"methods\"];\n        test_eq_methods_generic::<&str>(&strings);\n    }\n\n    #[test]\n    fn test_eq_methods_floats() {\n        let floats = [\n            -1.0,\n            2.5,\n            0.0,\n            3.0,\n            std::f64::consts::PI,\n            10.0,\n            10.0 / 3.0,\n            -1_000_000.0,\n        ];\n        test_eq_methods_generic::<f64>(&floats);\n    }\n\n    #[test]\n    fn test_eq_methods_bools() {\n        let bools = [true, false];\n        test_eq_methods_generic::<bool>(&bools);\n    }\n\n    #[test]\n    fn test_rich_compare_type_error() {\n        Python::attach(|py| {\n            let py_int = 1i32.into_pyobject(py).unwrap();\n            let py_str = \"1\".into_pyobject(py).unwrap();\n\n            assert!(py_int.rich_compare(&py_str, CompareOp::Lt).is_err());\n            assert!(!py_int\n                .rich_compare(py_str, CompareOp::Eq)\n                .unwrap()\n                .is_truthy()\n                .unwrap());\n        })\n    }\n\n    #[test]\n    fn test_is_callable() {\n        Python::attach(|py| {\n            assert!(PyList::type_object(py).is_callable());\n\n            let not_callable = 5i32.into_pyobject(py).unwrap();\n            assert!(!not_callable.is_callable());\n        });\n    }\n\n    #[test]\n    fn test_is_empty() {\n        Python::attach(|py| {\n            let empty_list = PyList::empty(py).into_any();\n            assert!(empty_list.is_empty().unwrap());\n\n            let list = PyList::new(py, vec![1, 2, 3]).unwrap().into_any();\n            assert!(!list.is_empty().unwrap());\n\n            let not_container = 5i32.into_pyobject(py).unwrap();\n            assert!(not_container.is_empty().is_err());\n        });\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[test]\n    #[allow(unknown_lints, non_local_definitions)]\n    fn test_fallible_dir() {\n        use crate::exceptions::PyValueError;\n        use crate::prelude::*;\n\n        #[pyclass(crate = \"crate\")]\n        struct DirFail;\n\n        #[pymethods(crate = \"crate\")]\n        impl DirFail {\n            fn __dir__(&self) -> PyResult<Py<PyAny>> {\n                Err(PyValueError::new_err(\"uh-oh!\"))\n            }\n        }\n\n        Python::attach(|py| {\n            let obj = Bound::new(py, DirFail).unwrap();\n            assert!(obj.dir().unwrap_err().is_instance_of::<PyValueError>(py));\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/boolobject.rs",
    "content": "use super::any::PyAnyMethods;\nuse crate::conversion::IntoPyObject;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::PyErr;\nuse crate::{\n    exceptions::PyTypeError, ffi, ffi_ptr_ext::FfiPtrExt, instance::Bound,\n    types::typeobject::PyTypeMethods, Borrowed, FromPyObject, PyAny, Python,\n};\nuse std::convert::Infallible;\nuse std::ptr;\n\n/// Represents a Python `bool`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyBool>`][crate::Py] or [`Bound<'py, PyBool>`][Bound].\n///\n/// For APIs available on `bool` objects, see the [`PyBoolMethods`] trait which is implemented for\n/// [`Bound<'py, PyBool>`][Bound].\n#[repr(transparent)]\npub struct PyBool(PyAny);\n\npyobject_native_type!(PyBool, ffi::PyObject, pyobject_native_static_type_object!(ffi::PyBool_Type), \"builtins\", \"bool\", #checkfunction=ffi::PyBool_Check);\n\nimpl PyBool {\n    /// Depending on `val`, returns `true` or `false`.\n    ///\n    /// # Note\n    /// This returns a [`Borrowed`] reference to one of Pythons `True` or\n    /// `False` singletons\n    #[inline]\n    pub fn new(py: Python<'_>, val: bool) -> Borrowed<'_, '_, Self> {\n        // SAFETY: `Py_True` and `Py_False` are global singletons which are known to be boolean objects\n        unsafe {\n            if val { ffi::Py_True() } else { ffi::Py_False() }\n                .assume_borrowed_unchecked(py)\n                .cast_unchecked()\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyBool`].\n///\n/// These methods are defined for the `Bound<'py, PyBool>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyBool\")]\npub trait PyBoolMethods<'py>: crate::sealed::Sealed {\n    /// Gets whether this boolean is `true`.\n    fn is_true(&self) -> bool;\n}\n\nimpl<'py> PyBoolMethods<'py> for Bound<'py, PyBool> {\n    #[inline]\n    fn is_true(&self) -> bool {\n        unsafe { ptr::eq(self.as_ptr(), ffi::Py_True()) }\n    }\n}\n\n/// Compare `Bound<PyBool>` with `bool`.\nimpl PartialEq<bool> for Bound<'_, PyBool> {\n    #[inline]\n    fn eq(&self, other: &bool) -> bool {\n        self.as_borrowed() == *other\n    }\n}\n\n/// Compare `&Bound<PyBool>` with `bool`.\nimpl PartialEq<bool> for &'_ Bound<'_, PyBool> {\n    #[inline]\n    fn eq(&self, other: &bool) -> bool {\n        self.as_borrowed() == *other\n    }\n}\n\n/// Compare `Bound<PyBool>` with `&bool`.\nimpl PartialEq<&'_ bool> for Bound<'_, PyBool> {\n    #[inline]\n    fn eq(&self, other: &&bool) -> bool {\n        self.as_borrowed() == **other\n    }\n}\n\n/// Compare `bool` with `Bound<PyBool>`\nimpl PartialEq<Bound<'_, PyBool>> for bool {\n    #[inline]\n    fn eq(&self, other: &Bound<'_, PyBool>) -> bool {\n        *self == other.as_borrowed()\n    }\n}\n\n/// Compare `bool` with `&Bound<PyBool>`\nimpl PartialEq<&'_ Bound<'_, PyBool>> for bool {\n    #[inline]\n    fn eq(&self, other: &&'_ Bound<'_, PyBool>) -> bool {\n        *self == other.as_borrowed()\n    }\n}\n\n/// Compare `&bool` with `Bound<PyBool>`\nimpl PartialEq<Bound<'_, PyBool>> for &'_ bool {\n    #[inline]\n    fn eq(&self, other: &Bound<'_, PyBool>) -> bool {\n        **self == other.as_borrowed()\n    }\n}\n\n/// Compare `Borrowed<PyBool>` with `bool`\nimpl PartialEq<bool> for Borrowed<'_, '_, PyBool> {\n    #[inline]\n    fn eq(&self, other: &bool) -> bool {\n        self.is_true() == *other\n    }\n}\n\n/// Compare `Borrowed<PyBool>` with `&bool`\nimpl PartialEq<&bool> for Borrowed<'_, '_, PyBool> {\n    #[inline]\n    fn eq(&self, other: &&bool) -> bool {\n        self.is_true() == **other\n    }\n}\n\n/// Compare `bool` with `Borrowed<PyBool>`\nimpl PartialEq<Borrowed<'_, '_, PyBool>> for bool {\n    #[inline]\n    fn eq(&self, other: &Borrowed<'_, '_, PyBool>) -> bool {\n        *self == other.is_true()\n    }\n}\n\n/// Compare `&bool` with `Borrowed<PyBool>`\nimpl PartialEq<Borrowed<'_, '_, PyBool>> for &'_ bool {\n    #[inline]\n    fn eq(&self, other: &Borrowed<'_, '_, PyBool>) -> bool {\n        **self == other.is_true()\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for bool {\n    type Target = PyBool;\n    type Output = Borrowed<'py, 'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyBool::TYPE_HINT;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PyBool::new(py, self))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &bool {\n    type Target = PyBool;\n    type Output = Borrowed<'py, 'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = bool::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\n/// Converts a Python `bool` to a Rust `bool`.\n///\n/// Fails with `TypeError` if the input is not a Python `bool`.\nimpl FromPyObject<'_, '_> for bool {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyBool::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'_, '_, PyAny>) -> Result<Self, Self::Error> {\n        let err = match obj.cast::<PyBool>() {\n            Ok(obj) => return Ok(obj.is_true()),\n            Err(err) => err,\n        };\n\n        let is_numpy_bool = {\n            let ty = obj.get_type();\n            ty.module().is_ok_and(|module| module == \"numpy\")\n                && ty\n                    .name()\n                    .is_ok_and(|name| name == \"bool_\" || name == \"bool\")\n        };\n\n        if is_numpy_bool {\n            let missing_conversion = |obj: Borrowed<'_, '_, PyAny>| {\n                PyTypeError::new_err(format!(\n                    \"object of type '{}' does not define a '__bool__' conversion\",\n                    obj.get_type()\n                ))\n            };\n\n            #[cfg(not(any(Py_LIMITED_API, PyPy)))]\n            unsafe {\n                let ptr = obj.as_ptr();\n\n                if let Some(tp_as_number) = (*(*ptr).ob_type).tp_as_number.as_ref() {\n                    if let Some(nb_bool) = tp_as_number.nb_bool {\n                        match (nb_bool)(ptr) {\n                            0 => return Ok(false),\n                            1 => return Ok(true),\n                            _ => return Err(crate::PyErr::fetch(obj.py())),\n                        }\n                    }\n                }\n\n                return Err(missing_conversion(obj));\n            }\n\n            #[cfg(any(Py_LIMITED_API, PyPy))]\n            {\n                let meth = obj\n                    .lookup_special(crate::intern!(obj.py(), \"__bool__\"))?\n                    .ok_or_else(|| missing_conversion(obj))?;\n\n                let obj = meth.call0()?.cast_into::<PyBool>()?;\n                return Ok(obj.is_true());\n            }\n        }\n\n        Err(err.into())\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::{PyAnyMethods, PyBool, PyBoolMethods};\n    use crate::IntoPyObject;\n    use crate::Python;\n\n    #[test]\n    fn test_true() {\n        Python::attach(|py| {\n            assert!(PyBool::new(py, true).is_true());\n            let t = PyBool::new(py, true);\n            assert!(t.extract::<bool>().unwrap());\n            assert!(true.into_pyobject(py).unwrap().is(&*PyBool::new(py, true)));\n        });\n    }\n\n    #[test]\n    fn test_false() {\n        Python::attach(|py| {\n            assert!(!PyBool::new(py, false).is_true());\n            let t = PyBool::new(py, false);\n            assert!(!t.extract::<bool>().unwrap());\n            assert!(false\n                .into_pyobject(py)\n                .unwrap()\n                .is(&*PyBool::new(py, false)));\n        });\n    }\n\n    #[test]\n    fn test_pybool_comparisons() {\n        Python::attach(|py| {\n            let py_bool = PyBool::new(py, true);\n            let py_bool_false = PyBool::new(py, false);\n            let rust_bool = true;\n\n            // Bound<'_, PyBool> == bool\n            assert_eq!(*py_bool, rust_bool);\n            assert_ne!(*py_bool_false, rust_bool);\n\n            // Bound<'_, PyBool> == &bool\n            assert_eq!(*py_bool, &rust_bool);\n            assert_ne!(*py_bool_false, &rust_bool);\n\n            // &Bound<'_, PyBool> == bool\n            assert_eq!(&*py_bool, rust_bool);\n            assert_ne!(&*py_bool_false, rust_bool);\n\n            // &Bound<'_, PyBool> == &bool\n            assert_eq!(&*py_bool, &rust_bool);\n            assert_ne!(&*py_bool_false, &rust_bool);\n\n            // bool == Bound<'_, PyBool>\n            assert_eq!(rust_bool, *py_bool);\n            assert_ne!(rust_bool, *py_bool_false);\n\n            // bool == &Bound<'_, PyBool>\n            assert_eq!(rust_bool, &*py_bool);\n            assert_ne!(rust_bool, &*py_bool_false);\n\n            // &bool == Bound<'_, PyBool>\n            assert_eq!(&rust_bool, *py_bool);\n            assert_ne!(&rust_bool, *py_bool_false);\n\n            // &bool == &Bound<'_, PyBool>\n            assert_eq!(&rust_bool, &*py_bool);\n            assert_ne!(&rust_bool, &*py_bool_false);\n\n            // Borrowed<'_, '_, PyBool> == bool\n            assert_eq!(py_bool, rust_bool);\n            assert_ne!(py_bool_false, rust_bool);\n\n            // Borrowed<'_, '_, PyBool> == &bool\n            assert_eq!(py_bool, &rust_bool);\n            assert_ne!(py_bool_false, &rust_bool);\n\n            // bool == Borrowed<'_, '_, PyBool>\n            assert_eq!(rust_bool, py_bool);\n            assert_ne!(rust_bool, py_bool_false);\n\n            // &bool == Borrowed<'_, '_, PyBool>\n            assert_eq!(&rust_bool, py_bool);\n            assert_ne!(&rust_bool, py_bool_false);\n            assert_eq!(py_bool, rust_bool);\n            assert_ne!(py_bool_false, rust_bool);\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/bytearray.rs",
    "content": "use crate::err::{PyErr, PyResult};\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::instance::{Borrowed, Bound};\nuse crate::py_result_ext::PyResultExt;\nuse crate::sync::critical_section::with_critical_section;\nuse crate::{ffi, PyAny, Python};\nuse std::slice;\n\n/// Represents a Python `bytearray`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyByteArray>`][crate::Py] or [`Bound<'py, PyByteArray>`][Bound].\n///\n/// For APIs available on `bytearray` objects, see the [`PyByteArrayMethods`] trait which is implemented for\n/// [`Bound<'py, PyByteArray>`][Bound].\n#[repr(transparent)]\npub struct PyByteArray(PyAny);\n\npyobject_native_type_core!(PyByteArray, pyobject_native_static_type_object!(ffi::PyByteArray_Type), \"builtins\", \"bytearray\", #checkfunction=ffi::PyByteArray_Check);\n\nimpl PyByteArray {\n    /// Creates a new Python bytearray object.\n    ///\n    /// The byte string is initialized by copying the data from the `&[u8]`.\n    pub fn new<'py>(py: Python<'py>, src: &[u8]) -> Bound<'py, PyByteArray> {\n        let ptr = src.as_ptr().cast();\n        let len = src.len() as ffi::Py_ssize_t;\n        unsafe {\n            ffi::PyByteArray_FromStringAndSize(ptr, len)\n                .assume_owned(py)\n                .cast_into_unchecked()\n        }\n    }\n\n    /// Creates a new Python `bytearray` object with an `init` closure to write its contents.\n    /// Before calling `init` the bytearray is zero-initialised.\n    /// * If Python raises a MemoryError on the allocation, `new_with` will return\n    ///   it inside `Err`.\n    /// * If `init` returns `Err(e)`, `new_with` will return `Err(e)`.\n    /// * If `init` returns `Ok(())`, `new_with` will return `Ok(&PyByteArray)`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use pyo3::{prelude::*, types::PyByteArray};\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let py_bytearray = PyByteArray::new_with(py, 10, |bytes: &mut [u8]| {\n    ///         bytes.copy_from_slice(b\"Hello Rust\");\n    ///         Ok(())\n    ///     })?;\n    ///     let bytearray: &[u8] = unsafe { py_bytearray.as_bytes() };\n    ///     assert_eq!(bytearray, b\"Hello Rust\");\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    pub fn new_with<F>(py: Python<'_>, len: usize, init: F) -> PyResult<Bound<'_, PyByteArray>>\n    where\n        F: FnOnce(&mut [u8]) -> PyResult<()>,\n    {\n        unsafe {\n            // Allocate buffer and check for an error\n            let pybytearray: Bound<'_, Self> =\n                ffi::PyByteArray_FromStringAndSize(std::ptr::null(), len as ffi::Py_ssize_t)\n                    .assume_owned_or_err(py)?\n                    .cast_into_unchecked();\n\n            let buffer: *mut u8 = ffi::PyByteArray_AsString(pybytearray.as_ptr()).cast();\n            debug_assert!(!buffer.is_null());\n            // Zero-initialise the uninitialised bytearray\n            std::ptr::write_bytes(buffer, 0u8, len);\n            // (Further) Initialise the bytearray in init\n            // If init returns an Err, pypybytearray will automatically deallocate the buffer\n            init(std::slice::from_raw_parts_mut(buffer, len)).map(|_| pybytearray)\n        }\n    }\n\n    /// Creates a new Python `bytearray` object from another Python object that\n    /// implements the buffer protocol.\n    pub fn from<'py>(src: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyByteArray>> {\n        unsafe {\n            ffi::PyByteArray_FromObject(src.as_ptr())\n                .assume_owned_or_err(src.py())\n                .cast_into_unchecked()\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyByteArray`].\n///\n/// These methods are defined for the `Bound<'py, PyByteArray>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyByteArray\")]\npub trait PyByteArrayMethods<'py>: crate::sealed::Sealed {\n    /// Gets the length of the bytearray.\n    fn len(&self) -> usize;\n\n    /// Checks if the bytearray is empty.\n    fn is_empty(&self) -> bool;\n\n    /// Gets the start of the buffer containing the contents of the bytearray.\n    ///\n    /// # Safety\n    ///\n    /// See the safety requirements of [`PyByteArrayMethods::as_bytes`] and [`PyByteArrayMethods::as_bytes_mut`].\n    fn data(&self) -> *mut u8;\n\n    /// Extracts a slice of the `ByteArray`'s entire buffer.\n    ///\n    /// # Safety\n    ///\n    /// Mutation of the `bytearray` invalidates the slice. If it is used afterwards, the behavior is\n    /// undefined.\n    ///\n    /// These mutations may occur in Python code as well as from Rust:\n    /// - Calling methods like [`PyByteArrayMethods::as_bytes_mut`] and [`PyByteArrayMethods::resize`] will\n    ///   invalidate the slice.\n    /// - Actions like dropping objects or raising exceptions can invoke `__del__`methods or signal\n    ///   handlers, which may execute arbitrary Python code. This means that if Python code has a\n    ///   reference to the `bytearray` you cannot safely use the vast majority of PyO3's API whilst\n    ///   using the slice.\n    ///\n    /// As a result, this slice should only be used for short-lived operations without executing any\n    /// Python code, such as copying into a Vec.\n    /// For free-threaded Python support see also [`with_critical_section`].\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::exceptions::PyRuntimeError;\n    /// use pyo3::sync::critical_section::with_critical_section;\n    /// use pyo3::types::PyByteArray;\n    ///\n    /// #[pyfunction]\n    /// fn a_valid_function(bytes: &Bound<'_, PyByteArray>) -> PyResult<()> {\n    ///     let section = with_critical_section(bytes, || {\n    ///         // SAFETY: We promise to not let the interpreter regain control over the bytearray\n    ///         // or invoke any PyO3 APIs while using the slice.\n    ///         let slice = unsafe { bytes.as_bytes() };\n    ///\n    ///         // Copy only a section of `bytes` while avoiding\n    ///         // `to_vec` which copies the entire thing.\n    ///         slice.get(6..11)\n    ///             .map(Vec::from)\n    ///             .ok_or_else(|| PyRuntimeError::new_err(\"input is not long enough\"))\n    ///     })?;\n    ///\n    ///     // Now we can do things with `section` and call PyO3 APIs again.\n    ///     // ...\n    ///     # assert_eq!(&section, b\"world\");\n    ///\n    ///     Ok(())\n    /// }\n    /// # fn main() -> PyResult<()> {\n    /// #     Python::attach(|py| -> PyResult<()> {\n    /// #         let fun = wrap_pyfunction!(a_valid_function, py)?;\n    /// #         let locals = pyo3::types::PyDict::new(py);\n    /// #         locals.set_item(\"a_valid_function\", fun)?;\n    /// #\n    /// #         py.run(cr#\"b = bytearray(b\"hello world\")\n    /// # a_valid_function(b)\n    /// #\n    /// # try:\n    /// #     a_valid_function(bytearray())\n    /// # except RuntimeError as e:\n    /// #     assert str(e) == 'input is not long enough'\"#,\n    /// #             None,\n    /// #             Some(&locals),\n    /// #         )?;\n    /// #\n    /// #         Ok(())\n    /// #     })\n    /// # }\n    /// ```\n    ///\n    /// # Incorrect usage\n    ///\n    /// The following `bug` function is unsound ⚠️\n    ///\n    /// ```rust,no_run\n    /// # use pyo3::prelude::*;\n    /// # use pyo3::types::PyByteArray;\n    ///\n    /// # #[allow(dead_code)]\n    /// #[pyfunction]\n    /// fn bug(py: Python<'_>, bytes: &Bound<'_, PyByteArray>) {\n    ///     // No critical section is being used.\n    ///     // This means that for no-gil Python another thread could be modifying the\n    ///     // bytearray concurrently and thus invalidate `slice` any time.\n    ///     let slice = unsafe { bytes.as_bytes() };\n    ///\n    ///     // This explicitly yields control back to the Python interpreter...\n    ///     // ...but it's not always this obvious. Many things do this implicitly.\n    ///     py.detach(|| {\n    ///         // Python code could be mutating through its handle to `bytes`,\n    ///         // which makes reading it a data race, which is undefined behavior.\n    ///         println!(\"{:?}\", slice[0]);\n    ///     });\n    ///\n    ///     // Python code might have mutated it, so we can not rely on the slice\n    ///     // remaining valid. As such this is also undefined behavior.\n    ///     println!(\"{:?}\", slice[0]);\n    /// }\n    /// ```\n    unsafe fn as_bytes(&self) -> &[u8];\n\n    /// Extracts a mutable slice of the `ByteArray`'s entire buffer.\n    ///\n    /// # Safety\n    ///\n    /// Any other accesses of the `bytearray`'s buffer invalidate the slice. If it is used\n    /// afterwards, the behavior is undefined. The safety requirements of [`PyByteArrayMethods::as_bytes`]\n    /// apply to this function as well.\n    #[expect(clippy::mut_from_ref)]\n    unsafe fn as_bytes_mut(&self) -> &mut [u8];\n\n    /// Copies the contents of the bytearray to a Rust vector.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use pyo3::prelude::*;\n    /// # use pyo3::types::PyByteArray;\n    /// # Python::attach(|py| {\n    /// let bytearray = PyByteArray::new(py, b\"Hello World.\");\n    /// let mut copied_message = bytearray.to_vec();\n    /// assert_eq!(b\"Hello World.\", copied_message.as_slice());\n    ///\n    /// copied_message[11] = b'!';\n    /// assert_eq!(b\"Hello World!\", copied_message.as_slice());\n    ///\n    /// pyo3::py_run!(py, bytearray, \"assert bytearray == b'Hello World.'\");\n    /// # });\n    /// ```\n    fn to_vec(&self) -> Vec<u8>;\n\n    /// Resizes the bytearray object to the new length `len`.\n    ///\n    /// Note that this will invalidate any pointers obtained by [PyByteArrayMethods::data], as well as\n    /// any (unsafe) slices obtained from [PyByteArrayMethods::as_bytes] and [PyByteArrayMethods::as_bytes_mut].\n    fn resize(&self, len: usize) -> PyResult<()>;\n}\n\nimpl<'py> PyByteArrayMethods<'py> for Bound<'py, PyByteArray> {\n    #[inline]\n    fn len(&self) -> usize {\n        // non-negative Py_ssize_t should always fit into Rust usize\n        unsafe { ffi::PyByteArray_Size(self.as_ptr()) as usize }\n    }\n\n    fn is_empty(&self) -> bool {\n        self.len() == 0\n    }\n\n    fn data(&self) -> *mut u8 {\n        self.as_borrowed().data()\n    }\n\n    unsafe fn as_bytes(&self) -> &[u8] {\n        unsafe { self.as_borrowed().as_bytes() }\n    }\n\n    unsafe fn as_bytes_mut(&self) -> &mut [u8] {\n        unsafe { self.as_borrowed().as_bytes_mut() }\n    }\n\n    fn to_vec(&self) -> Vec<u8> {\n        with_critical_section(self, || {\n            // SAFETY:\n            //  * `self` is a `Bound` object, which guarantees that the Python GIL is held.\n            //  * For no-gil Python, a critical section is used in lieu of the GIL.\n            //  * We don't interact with the interpreter\n            //  * We don't mutate the underlying slice\n            unsafe { self.as_bytes() }.to_vec()\n        })\n    }\n\n    fn resize(&self, len: usize) -> PyResult<()> {\n        unsafe {\n            let result = ffi::PyByteArray_Resize(self.as_ptr(), len as ffi::Py_ssize_t);\n            if result == 0 {\n                Ok(())\n            } else {\n                Err(PyErr::fetch(self.py()))\n            }\n        }\n    }\n}\n\nimpl<'a> Borrowed<'a, '_, PyByteArray> {\n    fn data(&self) -> *mut u8 {\n        unsafe { ffi::PyByteArray_AsString(self.as_ptr()).cast() }\n    }\n\n    pub(crate) unsafe fn as_bytes(self) -> &'a [u8] {\n        unsafe { slice::from_raw_parts(self.data(), self.len()) }\n    }\n\n    unsafe fn as_bytes_mut(self) -> &'a mut [u8] {\n        unsafe { slice::from_raw_parts_mut(self.data(), self.len()) }\n    }\n}\n\nimpl<'py> TryFrom<&Bound<'py, PyAny>> for Bound<'py, PyByteArray> {\n    type Error = crate::PyErr;\n\n    /// Creates a new Python `bytearray` object from another Python object that\n    /// implements the buffer protocol.\n    fn try_from(value: &Bound<'py, PyAny>) -> Result<Self, Self::Error> {\n        PyByteArray::from(value)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::{PyAnyMethods, PyByteArray, PyByteArrayMethods};\n    use crate::{exceptions, Bound, Py, PyAny, Python};\n\n    #[test]\n    fn test_len() {\n        Python::attach(|py| {\n            let src = b\"Hello Python\";\n            let bytearray = PyByteArray::new(py, src);\n            assert_eq!(src.len(), bytearray.len());\n        });\n    }\n\n    #[test]\n    fn test_as_bytes() {\n        Python::attach(|py| {\n            let src = b\"Hello Python\";\n            let bytearray = PyByteArray::new(py, src);\n\n            let slice = unsafe { bytearray.as_bytes() };\n            assert_eq!(src, slice);\n            assert_eq!(bytearray.data() as *const _, slice.as_ptr());\n        });\n    }\n\n    #[test]\n    fn test_as_bytes_mut() {\n        Python::attach(|py| {\n            let src = b\"Hello Python\";\n            let bytearray = PyByteArray::new(py, src);\n\n            let slice = unsafe { bytearray.as_bytes_mut() };\n            assert_eq!(src, slice);\n            assert_eq!(bytearray.data(), slice.as_mut_ptr());\n\n            slice[0..5].copy_from_slice(b\"Hi...\");\n\n            assert_eq!(bytearray.str().unwrap(), \"bytearray(b'Hi... Python')\");\n        });\n    }\n\n    #[test]\n    fn test_to_vec() {\n        Python::attach(|py| {\n            let src = b\"Hello Python\";\n            let bytearray = PyByteArray::new(py, src);\n\n            let vec = bytearray.to_vec();\n            assert_eq!(src, vec.as_slice());\n        });\n    }\n\n    #[test]\n    fn test_from() {\n        Python::attach(|py| {\n            let src = b\"Hello Python\";\n            let bytearray = PyByteArray::new(py, src);\n\n            let ba: Py<PyAny> = bytearray.into();\n            let bytearray = PyByteArray::from(ba.bind(py)).unwrap();\n\n            assert_eq!(src, unsafe { bytearray.as_bytes() });\n        });\n    }\n\n    #[test]\n    fn test_from_err() {\n        Python::attach(|py| {\n            if let Err(err) = PyByteArray::from(py.None().bind(py)) {\n                assert!(err.is_instance_of::<exceptions::PyTypeError>(py));\n            } else {\n                panic!(\"error\");\n            }\n        });\n    }\n\n    #[test]\n    fn test_try_from() {\n        Python::attach(|py| {\n            let src = b\"Hello Python\";\n            let bytearray: &Bound<'_, PyAny> = &PyByteArray::new(py, src);\n            let bytearray: Bound<'_, PyByteArray> = TryInto::try_into(bytearray).unwrap();\n\n            assert_eq!(src, unsafe { bytearray.as_bytes() });\n        });\n    }\n\n    #[test]\n    fn test_resize() {\n        Python::attach(|py| {\n            let src = b\"Hello Python\";\n            let bytearray = PyByteArray::new(py, src);\n\n            bytearray.resize(20).unwrap();\n            assert_eq!(20, bytearray.len());\n        });\n    }\n\n    #[test]\n    fn test_byte_array_new_with() -> super::PyResult<()> {\n        Python::attach(|py| -> super::PyResult<()> {\n            let py_bytearray = PyByteArray::new_with(py, 10, |b: &mut [u8]| {\n                b.copy_from_slice(b\"Hello Rust\");\n                Ok(())\n            })?;\n            let bytearray: &[u8] = unsafe { py_bytearray.as_bytes() };\n            assert_eq!(bytearray, b\"Hello Rust\");\n            Ok(())\n        })\n    }\n\n    #[test]\n    fn test_byte_array_new_with_zero_initialised() -> super::PyResult<()> {\n        Python::attach(|py| -> super::PyResult<()> {\n            let py_bytearray = PyByteArray::new_with(py, 10, |_b: &mut [u8]| Ok(()))?;\n            let bytearray: &[u8] = unsafe { py_bytearray.as_bytes() };\n            assert_eq!(bytearray, &[0; 10]);\n            Ok(())\n        })\n    }\n\n    #[test]\n    fn test_byte_array_new_with_error() {\n        use crate::exceptions::PyValueError;\n        Python::attach(|py| {\n            let py_bytearray_result = PyByteArray::new_with(py, 10, |_b: &mut [u8]| {\n                Err(PyValueError::new_err(\"Hello Crustaceans!\"))\n            });\n            assert!(py_bytearray_result.is_err());\n            assert!(py_bytearray_result\n                .err()\n                .unwrap()\n                .is_instance_of::<PyValueError>(py));\n        })\n    }\n\n    // * wasm has no threading support\n    // * CPython 3.13t is unsound => test fails\n    #[cfg(all(\n        not(target_family = \"wasm\"),\n        any(Py_3_14, not(all(Py_3_13, Py_GIL_DISABLED)))\n    ))]\n    #[test]\n    fn test_data_integrity_in_critical_section() {\n        use crate::instance::Py;\n        use crate::sync::{critical_section::with_critical_section, MutexExt};\n\n        use std::sync::atomic::{AtomicBool, Ordering};\n        use std::sync::Mutex;\n        use std::thread;\n        use std::thread::ScopedJoinHandle;\n        use std::time::Duration;\n\n        const SIZE: usize = 1_000_000;\n        const DATA_VALUE: u8 = 42;\n\n        fn make_byte_array(py: Python<'_>, size: usize, value: u8) -> Bound<'_, PyByteArray> {\n            PyByteArray::new_with(py, size, |b| {\n                b.fill(value);\n                Ok(())\n            })\n            .unwrap()\n        }\n\n        let data: Mutex<Py<PyByteArray>> = Mutex::new(Python::attach(|py| {\n            make_byte_array(py, SIZE, DATA_VALUE).unbind()\n        }));\n\n        fn get_data<'py>(\n            data: &Mutex<Py<PyByteArray>>,\n            py: Python<'py>,\n        ) -> Bound<'py, PyByteArray> {\n            data.lock_py_attached(py).unwrap().bind(py).clone()\n        }\n\n        fn set_data(data: &Mutex<Py<PyByteArray>>, new: Bound<'_, PyByteArray>) {\n            let py = new.py();\n            *data.lock_py_attached(py).unwrap() = new.unbind()\n        }\n\n        let running = AtomicBool::new(true);\n        let extending = AtomicBool::new(false);\n\n        // continuously extends and resets the bytearray in data\n        let worker1 = || {\n            let mut rounds = 0;\n            while running.load(Ordering::SeqCst) && rounds < 50 {\n                Python::attach(|py| {\n                    let byte_array = get_data(&data, py);\n                    extending.store(true, Ordering::SeqCst);\n                    byte_array\n                        .call_method(\"extend\", (&byte_array,), None)\n                        .unwrap();\n                    extending.store(false, Ordering::SeqCst);\n                    set_data(&data, make_byte_array(py, SIZE, DATA_VALUE));\n                    rounds += 1;\n                });\n            }\n        };\n\n        // continuously checks the integrity of bytearray in data\n        let worker2 = || {\n            while running.load(Ordering::SeqCst) {\n                if !extending.load(Ordering::SeqCst) {\n                    // wait until we have a chance to read inconsistent state\n                    continue;\n                }\n                Python::attach(|py| {\n                    let read = get_data(&data, py);\n                    if read.len() == SIZE {\n                        // extend is still not done => wait even more\n                        return;\n                    }\n                    with_critical_section(&read, || {\n                        // SAFETY: we are in a critical section\n                        // This is the whole point of the test: make sure that a\n                        // critical section is sufficient to ensure that the data\n                        // read is consistent.\n                        unsafe {\n                            let bytes = read.as_bytes();\n                            assert!(bytes.iter().rev().take(50).all(|v| *v == DATA_VALUE\n                                && bytes.iter().take(50).all(|v| *v == DATA_VALUE)));\n                        }\n                    });\n                });\n            }\n        };\n\n        thread::scope(|s| {\n            let mut handle1 = Some(s.spawn(worker1));\n            let mut handle2 = Some(s.spawn(worker2));\n            let mut handles = [&mut handle1, &mut handle2];\n\n            let t0 = std::time::Instant::now();\n            while t0.elapsed() < Duration::from_secs(1) {\n                for handle in &mut handles {\n                    if handle\n                        .as_ref()\n                        .map(ScopedJoinHandle::is_finished)\n                        .unwrap_or(false)\n                    {\n                        let res = handle.take().unwrap().join();\n                        if res.is_err() {\n                            running.store(false, Ordering::SeqCst);\n                        }\n                        res.unwrap();\n                    }\n                }\n                if handles.iter().any(|handle| handle.is_none()) {\n                    break;\n                }\n            }\n            running.store(false, Ordering::SeqCst);\n            for handle in &mut handles {\n                if let Some(handle) = handle.take() {\n                    handle.join().unwrap()\n                }\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "src/types/bytes.rs",
    "content": "use crate::byteswriter::PyBytesWriter;\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::instance::{Borrowed, Bound};\nuse crate::{ffi, Py, PyAny, PyResult, Python};\nuse std::io::Write;\nuse std::ops::Index;\nuse std::slice::SliceIndex;\nuse std::str;\n\n/// Represents a Python `bytes` object.\n///\n/// This type is immutable.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyBytes>`][crate::Py] or [`Bound<'py, PyBytes>`][Bound].\n///\n/// For APIs available on `bytes` objects, see the [`PyBytesMethods`] trait which is implemented for\n/// [`Bound<'py, PyBytes>`][Bound].\n///\n/// # Equality\n///\n/// For convenience, [`Bound<'py, PyBytes>`][Bound] implements [`PartialEq<[u8]>`][PartialEq] to allow comparing the\n/// data in the Python bytes to a Rust `[u8]` byte slice.\n///\n/// This is not always the most appropriate way to compare Python bytes, as Python bytes subclasses\n/// may have different equality semantics. In situations where subclasses overriding equality might\n/// be relevant, use [`PyAnyMethods::eq`](crate::types::any::PyAnyMethods::eq), at cost of the\n/// additional overhead of a Python method call.\n///\n/// ```rust\n/// # use pyo3::prelude::*;\n/// use pyo3::types::PyBytes;\n///\n/// # Python::attach(|py| {\n/// let py_bytes = PyBytes::new(py, b\"foo\".as_slice());\n/// // via PartialEq<[u8]>\n/// assert_eq!(py_bytes, b\"foo\".as_slice());\n///\n/// // via Python equality\n/// let other = PyBytes::new(py, b\"foo\".as_slice());\n/// assert!(py_bytes.as_any().eq(other).unwrap());\n///\n/// // Note that `eq` will convert its argument to Python using `IntoPyObject`.\n/// // Byte collections are specialized, so that the following slice will indeed\n/// // convert into a `bytes` object and not a `list`:\n/// assert!(py_bytes.as_any().eq(b\"foo\".as_slice()).unwrap());\n/// # });\n/// ```\n#[repr(transparent)]\npub struct PyBytes(PyAny);\n\npyobject_native_type_core!(PyBytes, pyobject_native_static_type_object!(ffi::PyBytes_Type), \"builtins\", \"bytes\", #checkfunction=ffi::PyBytes_Check);\n\nimpl PyBytes {\n    /// Creates a new Python bytestring object.\n    /// The bytestring is initialized by copying the data from the `&[u8]`.\n    ///\n    /// Panics if out of memory.\n    pub fn new<'p>(py: Python<'p>, s: &[u8]) -> Bound<'p, PyBytes> {\n        let ptr = s.as_ptr().cast();\n        let len = s.len() as ffi::Py_ssize_t;\n        unsafe {\n            ffi::PyBytes_FromStringAndSize(ptr, len)\n                .assume_owned(py)\n                .cast_into_unchecked()\n        }\n    }\n\n    /// Creates a new Python `bytes` object with an `init` closure to write its contents.\n    /// Before calling `init` the bytes' contents are zero-initialised.\n    /// * If Python raises a MemoryError on the allocation, `new_with` will return\n    ///   it inside `Err`.\n    /// * If `init` returns `Err(e)`, `new_with` will return `Err(e)`.\n    /// * If `init` returns `Ok(())`, `new_with` will return `Ok(&PyBytes)`.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// use pyo3::{prelude::*, types::PyBytes};\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let py_bytes = PyBytes::new_with(py, 10, |bytes: &mut [u8]| {\n    ///         bytes.copy_from_slice(b\"Hello Rust\");\n    ///         Ok(())\n    ///     })?;\n    ///     let bytes: &[u8] = py_bytes.extract()?;\n    ///     assert_eq!(bytes, b\"Hello Rust\");\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    #[inline]\n    pub fn new_with<F>(py: Python<'_>, len: usize, init: F) -> PyResult<Bound<'_, PyBytes>>\n    where\n        F: FnOnce(&mut [u8]) -> PyResult<()>,\n    {\n        unsafe {\n            let pyptr = ffi::PyBytes_FromStringAndSize(std::ptr::null(), len as ffi::Py_ssize_t);\n            // Check for an allocation error and return it\n            let pybytes = pyptr.assume_owned_or_err(py)?.cast_into_unchecked();\n            let buffer: *mut u8 = ffi::PyBytes_AsString(pyptr).cast();\n            debug_assert!(!buffer.is_null());\n            // Zero-initialise the uninitialised bytestring\n            std::ptr::write_bytes(buffer, 0u8, len);\n            // (Further) Initialise the bytestring in init\n            // If init returns an Err, pypybytearray will automatically deallocate the buffer\n            init(std::slice::from_raw_parts_mut(buffer, len)).map(|_| pybytes)\n        }\n    }\n\n    /// Creates a new Python `bytes` object using a writer closure.\n    ///\n    /// This function allocates a Python `bytes` object with at least `reserved_capacity` bytes of capacity,\n    /// then provides a mutable writer to the closure `write`. The closure can write any number of bytes,\n    /// even more than the reserved capacity; the buffer will grow dynamically as needed.\n    ///\n    /// If `reserved_capacity` is 0, the buffer will start empty and grow as the writer writes data.\n    ///\n    /// After the closure returns, the resulting bytes object contains the written data.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// use pyo3::{prelude::*, types::PyBytes};\n    /// use std::io::Write;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let py_bytes = PyBytes::new_with_writer(py, 0, |writer| {\n    ///         writer.write_all(b\"hello world\")?;\n    ///         Ok(())\n    ///     })?;\n    ///     assert_eq!(py_bytes.as_bytes(), b\"hello world\");\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    #[inline]\n    pub fn new_with_writer<F>(\n        py: Python<'_>,\n        reserved_capacity: usize,\n        write: F,\n    ) -> PyResult<Bound<'_, PyBytes>>\n    where\n        F: FnOnce(&mut dyn Write) -> PyResult<()>,\n    {\n        let mut writer = PyBytesWriter::with_capacity(py, reserved_capacity)?;\n        write(&mut writer)?;\n        writer.try_into()\n    }\n\n    /// Creates a new Python byte string object from a raw pointer and length.\n    ///\n    /// Panics if out of memory.\n    ///\n    /// # Safety\n    ///\n    /// This function dereferences the raw pointer `ptr` as the\n    /// leading pointer of a slice of length `len`. [As with\n    /// `std::slice::from_raw_parts`, this is\n    /// unsafe](https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html#safety).\n    pub unsafe fn from_ptr(py: Python<'_>, ptr: *const u8, len: usize) -> Bound<'_, PyBytes> {\n        unsafe {\n            ffi::PyBytes_FromStringAndSize(ptr.cast(), len as isize)\n                .assume_owned(py)\n                .cast_into_unchecked()\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyBytes`].\n///\n/// These methods are defined for the `Bound<'py, PyBytes>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyBytes\")]\npub trait PyBytesMethods<'py>: crate::sealed::Sealed {\n    /// Gets the Python string as a byte slice.\n    fn as_bytes(&self) -> &[u8];\n}\n\nimpl<'py> PyBytesMethods<'py> for Bound<'py, PyBytes> {\n    #[inline]\n    fn as_bytes(&self) -> &[u8] {\n        self.as_borrowed().as_bytes()\n    }\n}\n\nimpl<'a> Borrowed<'a, '_, PyBytes> {\n    /// Gets the Python string as a byte slice.\n    #[allow(clippy::wrong_self_convention)]\n    pub(crate) fn as_bytes(self) -> &'a [u8] {\n        unsafe {\n            let buffer = ffi::PyBytes_AsString(self.as_ptr()) as *const u8;\n            let length = ffi::PyBytes_Size(self.as_ptr()) as usize;\n            debug_assert!(!buffer.is_null());\n            std::slice::from_raw_parts(buffer, length)\n        }\n    }\n}\n\nimpl Py<PyBytes> {\n    /// Gets the Python bytes as a byte slice. Because Python bytes are\n    /// immutable, the result may be used for as long as the reference to\n    /// `self` is held, including when the GIL is released.\n    pub fn as_bytes<'a>(&'a self, py: Python<'_>) -> &'a [u8] {\n        self.bind_borrowed(py).as_bytes()\n    }\n}\n\n/// This is the same way [Vec] is indexed.\nimpl<I: SliceIndex<[u8]>> Index<I> for Bound<'_, PyBytes> {\n    type Output = I::Output;\n\n    fn index(&self, index: I) -> &Self::Output {\n        &self.as_bytes()[index]\n    }\n}\n\n/// Compares whether the Python bytes object is equal to the [u8].\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyBytes`].\nimpl PartialEq<[u8]> for Bound<'_, PyBytes> {\n    #[inline]\n    fn eq(&self, other: &[u8]) -> bool {\n        self.as_borrowed() == *other\n    }\n}\n\n/// Compares whether the Python bytes object is equal to the [u8].\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyBytes`].\nimpl PartialEq<&'_ [u8]> for Bound<'_, PyBytes> {\n    #[inline]\n    fn eq(&self, other: &&[u8]) -> bool {\n        self.as_borrowed() == **other\n    }\n}\n\n/// Compares whether the Python bytes object is equal to the [u8].\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyBytes`].\nimpl PartialEq<Bound<'_, PyBytes>> for [u8] {\n    #[inline]\n    fn eq(&self, other: &Bound<'_, PyBytes>) -> bool {\n        *self == other.as_borrowed()\n    }\n}\n\n/// Compares whether the Python bytes object is equal to the [u8].\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyBytes`].\nimpl PartialEq<&'_ Bound<'_, PyBytes>> for [u8] {\n    #[inline]\n    fn eq(&self, other: &&Bound<'_, PyBytes>) -> bool {\n        *self == other.as_borrowed()\n    }\n}\n\n/// Compares whether the Python bytes object is equal to the [u8].\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyBytes`].\nimpl PartialEq<Bound<'_, PyBytes>> for &'_ [u8] {\n    #[inline]\n    fn eq(&self, other: &Bound<'_, PyBytes>) -> bool {\n        **self == other.as_borrowed()\n    }\n}\n\n/// Compares whether the Python bytes object is equal to the [u8].\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyBytes`].\nimpl PartialEq<[u8]> for &'_ Bound<'_, PyBytes> {\n    #[inline]\n    fn eq(&self, other: &[u8]) -> bool {\n        self.as_borrowed() == other\n    }\n}\n\n/// Compares whether the Python bytes object is equal to the [u8].\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyBytes`].\nimpl PartialEq<[u8]> for Borrowed<'_, '_, PyBytes> {\n    #[inline]\n    fn eq(&self, other: &[u8]) -> bool {\n        self.as_bytes() == other\n    }\n}\n\n/// Compares whether the Python bytes object is equal to the [u8].\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyBytes`].\nimpl PartialEq<&[u8]> for Borrowed<'_, '_, PyBytes> {\n    #[inline]\n    fn eq(&self, other: &&[u8]) -> bool {\n        *self == **other\n    }\n}\n\n/// Compares whether the Python bytes object is equal to the [u8].\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyBytes`].\nimpl PartialEq<Borrowed<'_, '_, PyBytes>> for [u8] {\n    #[inline]\n    fn eq(&self, other: &Borrowed<'_, '_, PyBytes>) -> bool {\n        other == self\n    }\n}\n\n/// Compares whether the Python bytes object is equal to the [u8].\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyBytes`].\nimpl PartialEq<Borrowed<'_, '_, PyBytes>> for &'_ [u8] {\n    #[inline]\n    fn eq(&self, other: &Borrowed<'_, '_, PyBytes>) -> bool {\n        other == self\n    }\n}\n\nimpl<'a> AsRef<[u8]> for Borrowed<'a, '_, PyBytes> {\n    #[inline]\n    fn as_ref(&self) -> &'a [u8] {\n        self.as_bytes()\n    }\n}\n\nimpl AsRef<[u8]> for Bound<'_, PyBytes> {\n    #[inline]\n    fn as_ref(&self) -> &[u8] {\n        self.as_bytes()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::PyAnyMethods as _;\n\n    #[test]\n    fn test_bytes_index() {\n        Python::attach(|py| {\n            let bytes = PyBytes::new(py, b\"Hello World\");\n            assert_eq!(bytes[1], b'e');\n        });\n    }\n\n    #[test]\n    fn test_bound_bytes_index() {\n        Python::attach(|py| {\n            let bytes = PyBytes::new(py, b\"Hello World\");\n            assert_eq!(bytes[1], b'e');\n\n            let bytes = &bytes;\n            assert_eq!(bytes[1], b'e');\n        });\n    }\n\n    #[test]\n    fn test_bytes_new_with() -> super::PyResult<()> {\n        Python::attach(|py| -> super::PyResult<()> {\n            let py_bytes = PyBytes::new_with(py, 10, |b: &mut [u8]| {\n                b.copy_from_slice(b\"Hello Rust\");\n                Ok(())\n            })?;\n            let bytes: &[u8] = py_bytes.extract()?;\n            assert_eq!(bytes, b\"Hello Rust\");\n            Ok(())\n        })\n    }\n\n    #[test]\n    fn test_bytes_new_with_zero_initialised() -> super::PyResult<()> {\n        Python::attach(|py| -> super::PyResult<()> {\n            let py_bytes = PyBytes::new_with(py, 10, |_b: &mut [u8]| Ok(()))?;\n            let bytes: &[u8] = py_bytes.extract()?;\n            assert_eq!(bytes, &[0; 10]);\n            Ok(())\n        })\n    }\n\n    #[test]\n    fn test_bytes_new_with_error() {\n        use crate::exceptions::PyValueError;\n        Python::attach(|py| {\n            let py_bytes_result = PyBytes::new_with(py, 10, |_b: &mut [u8]| {\n                Err(PyValueError::new_err(\"Hello Crustaceans!\"))\n            });\n            assert!(py_bytes_result.is_err());\n            assert!(py_bytes_result\n                .err()\n                .unwrap()\n                .is_instance_of::<PyValueError>(py));\n        });\n    }\n\n    #[test]\n    fn test_comparisons() {\n        Python::attach(|py| {\n            let b = b\"hello, world\".as_slice();\n            let py_bytes = PyBytes::new(py, b);\n\n            assert_eq!(py_bytes, b\"hello, world\".as_slice());\n\n            assert_eq!(py_bytes, b);\n            assert_eq!(&py_bytes, b);\n            assert_eq!(b, py_bytes);\n            assert_eq!(b, &py_bytes);\n\n            assert_eq!(py_bytes, *b);\n            assert_eq!(&py_bytes, *b);\n            assert_eq!(*b, py_bytes);\n            assert_eq!(*b, &py_bytes);\n\n            let py_string = py_bytes.as_borrowed();\n\n            assert_eq!(py_string, b);\n            assert_eq!(&py_string, b);\n            assert_eq!(b, py_string);\n            assert_eq!(b, &py_string);\n\n            assert_eq!(py_string, *b);\n            assert_eq!(*b, py_string);\n        })\n    }\n\n    #[test]\n    #[cfg(not(Py_LIMITED_API))]\n    fn test_as_string() {\n        Python::attach(|py| {\n            let b = b\"hello, world\".as_slice();\n            let py_bytes = PyBytes::new(py, b);\n            unsafe {\n                assert_eq!(\n                    ffi::PyBytes_AsString(py_bytes.as_ptr()) as *const std::ffi::c_char,\n                    ffi::PyBytes_AS_STRING(py_bytes.as_ptr()) as *const std::ffi::c_char\n                );\n            }\n        })\n    }\n\n    #[test]\n    fn test_as_ref_slice() {\n        Python::attach(|py| {\n            let b = b\"hello, world\";\n            let py_bytes = PyBytes::new(py, b);\n            let ref_bound: &[u8] = py_bytes.as_ref();\n            assert_eq!(ref_bound, b);\n            let py_bytes_borrowed = py_bytes.as_borrowed();\n            let ref_borrowed: &[u8] = py_bytes_borrowed.as_ref();\n            assert_eq!(ref_borrowed, b);\n        })\n    }\n\n    #[test]\n    fn test_with_writer() {\n        Python::attach(|py| {\n            let bytes = PyBytes::new_with_writer(py, 0, |writer| {\n                writer.write_all(b\"hallo\")?;\n                Ok(())\n            })\n            .unwrap();\n\n            assert_eq!(bytes.as_bytes(), b\"hallo\");\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/capsule.rs",
    "content": "#![deny(clippy::undocumented_unsafe_blocks)]\n\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::py_result_ext::PyResultExt;\nuse crate::{ffi, PyAny};\nuse crate::{Bound, Python};\nuse crate::{PyErr, PyResult};\nuse std::ffi::{c_char, c_int, c_void};\nuse std::ffi::{CStr, CString};\nuse std::mem::offset_of;\nuse std::ptr::{self, NonNull};\n\n/// Represents a Python Capsule\n/// as described in [Capsules](https://docs.python.org/3/c-api/capsule.html#capsules):\n/// > This subtype of PyObject represents an opaque value, useful for C extension\n/// > modules who need to pass an opaque value (as a void* pointer) through Python\n/// > code to other C code. It is often used to make a C function pointer defined\n/// > in one module available to other modules, so the regular import mechanism can\n/// > be used to access C APIs defined in dynamically loaded modules.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyCapsule>`][crate::Py] or [`Bound<'py, PyCapsule>`][Bound].\n///\n/// For APIs available on capsule objects, see the [`PyCapsuleMethods`] trait which is implemented for\n/// [`Bound<'py, PyCapsule>`][Bound].\n///\n/// # Example\n/// ```\n/// use pyo3::{prelude::*, types::PyCapsule, ffi::c_str};\n///\n/// #[repr(C)]\n/// struct Foo {\n///     pub val: u32,\n/// }\n///\n/// let r = Python::attach(|py| -> PyResult<()> {\n///     let foo = Foo { val: 123 };\n///     let capsule = PyCapsule::new(py, foo, Some(c\"builtins.capsule\".to_owned()))?;\n///\n///     let module = PyModule::import(py, \"builtins\")?;\n///     module.add(\"capsule\", capsule)?;\n///\n///     let cap: &Foo = unsafe { PyCapsule::import(py, c\"builtins.capsule\")? };\n///     assert_eq!(cap.val, 123);\n///     Ok(())\n/// });\n/// assert!(r.is_ok());\n/// ```\n#[repr(transparent)]\npub struct PyCapsule(PyAny);\n\npyobject_native_type_core!(PyCapsule, pyobject_native_static_type_object!(ffi::PyCapsule_Type), \"types\", \"CapsuleType\", #checkfunction=ffi::PyCapsule_CheckExact);\n\nimpl PyCapsule {\n    /// Constructs a new capsule whose contents are `value`, associated with `name`.\n    /// `name` is the identifier for the capsule; if it is stored as an attribute of a module,\n    /// the name should be in the format `\"modulename.attribute\"`.\n    ///\n    /// It is checked at compile time that the type T is not zero-sized. Rust function items\n    /// need to be cast to a function pointer (`fn(args) -> result`) to be put into a capsule.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// use pyo3::{prelude::*, types::PyCapsule, ffi::c_str};\n    /// use std::ffi::CStr;\n    /// use std::ptr::NonNull;\n    ///\n    /// // this can be c\"foo\" on Rust 1.77+\n    /// const NAME: &CStr = c\"foo\";\n    ///\n    /// Python::attach(|py| {\n    ///     let capsule = PyCapsule::new(py, 123_u32, Some(NAME.to_owned())).unwrap();\n    ///     let val: NonNull<u32> = capsule.pointer_checked(Some(NAME)).unwrap().cast();\n    ///     assert_eq!(unsafe { *val.as_ref() }, 123);\n    /// });\n    /// ```\n    ///\n    /// However, attempting to construct a `PyCapsule` with a zero-sized type will not compile:\n    ///\n    /// ```compile_fail\n    /// use pyo3::{prelude::*, types::PyCapsule};\n    ///\n    /// Python::attach(|py| {\n    ///     let capsule = PyCapsule::new(py, (), None).unwrap();  // Oops! `()` is zero sized!\n    /// });\n    /// ```\n    pub fn new<T: 'static + Send + AssertNotZeroSized>(\n        py: Python<'_>,\n        value: T,\n        name: Option<CString>,\n    ) -> PyResult<Bound<'_, Self>> {\n        Self::new_with_destructor(py, value, name, |_, _| {})\n    }\n\n    /// Constructs a new capsule whose contents are `value`, associated with `name`.\n    ///\n    /// Also provides a destructor: when the `PyCapsule` is destroyed, it will be passed the original object,\n    /// as well as a `*mut c_void` which will point to the capsule's context, if any.\n    ///\n    /// The `destructor` must be `Send`, because there is no guarantee which thread it will eventually\n    /// be called from.\n    pub fn new_with_destructor<\n        T: 'static + Send + AssertNotZeroSized,\n        F: FnOnce(T, *mut c_void) + Send,\n    >(\n        py: Python<'_>,\n        value: T,\n        name: Option<CString>,\n        destructor: F,\n    ) -> PyResult<Bound<'_, Self>> {\n        AssertNotZeroSized::assert_not_zero_sized(&value);\n\n        // Sanity check for capsule layout\n        debug_assert_eq!(offset_of!(CapsuleContents::<T, F>, value), 0);\n\n        let name_ptr = name.as_ref().map_or(std::ptr::null(), |name| name.as_ptr());\n        let val = Box::into_raw(Box::new(CapsuleContents {\n            value,\n            destructor,\n            name,\n        }));\n\n        // SAFETY:\n        // - `val` is a non-null pointer to valid capsule data\n        // - `name_ptr` is either a valid C string or null\n        // - `destructor` will delete this data when called\n        // - thread is attached to the Python interpreter\n        // - `PyCapsule_New` returns a new reference or null on error\n        unsafe {\n            ffi::PyCapsule_New(val.cast(), name_ptr, Some(capsule_destructor::<T, F>))\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n        }\n    }\n\n    /// Constructs a new capsule from a raw pointer.\n    ///\n    /// Unlike [`PyCapsule::new`], which stores a value and sets the capsule's pointer\n    /// to that value's address, this method uses the pointer directly. This is useful\n    /// for APIs that expect the capsule to hold a specific address (e.g., a function\n    /// pointer for FFI) rather than a pointer to owned data.\n    ///\n    /// The capsule's name should follow Python's naming convention:\n    /// `\"module.attribute\"` for capsules stored as module attributes.\n    ///\n    /// # Safety\n    ///\n    /// - The pointer must be valid for its intended use case.\n    /// - If the pointer refers to data, that data must outlive the capsule.\n    /// - No destructor is registered; use [`PyCapsule::new_with_pointer_and_destructor`]\n    ///   if cleanup is needed.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// use pyo3::{prelude::*, types::PyCapsule};\n    /// use std::ffi::c_void;\n    /// use std::ptr::NonNull;\n    ///\n    /// extern \"C\" fn my_ffi_handler(_: *mut c_void) -> *mut c_void {\n    ///     std::ptr::null_mut()\n    /// }\n    ///\n    /// Python::attach(|py| {\n    ///     let ptr = NonNull::new(my_ffi_handler as *mut c_void).unwrap();\n    ///\n    ///     // SAFETY: `ptr` is a valid function pointer\n    ///     let capsule = unsafe {\n    ///         PyCapsule::new_with_pointer(py, ptr, c\"my_module.my_ffi_handler\")\n    ///     }.unwrap();\n    ///\n    ///     let retrieved = capsule.pointer_checked(Some(c\"my_module.my_ffi_handler\")).unwrap();\n    ///     assert_eq!(retrieved.as_ptr(), my_ffi_handler as *mut c_void);\n    /// });\n    /// ```\n    pub unsafe fn new_with_pointer<'py>(\n        py: Python<'py>,\n        pointer: NonNull<c_void>,\n        name: &'static CStr,\n    ) -> PyResult<Bound<'py, Self>> {\n        // SAFETY: Caller guarantees pointer validity; destructor is None.\n        unsafe { Self::new_with_pointer_and_destructor(py, pointer, name, None) }\n    }\n\n    /// Constructs a new capsule from a raw pointer with an optional destructor.\n    ///\n    /// This is the full-featured version of [`PyCapsule::new_with_pointer`], allowing\n    /// a destructor to be called when the capsule is garbage collected.\n    ///\n    /// Unlike [`PyCapsule::new_with_destructor`], the destructor here must be a raw\n    /// `extern \"C\"` function pointer, not a Rust closure. This is because there is\n    /// no internal storage for a closure—the capsule holds only the raw pointer you\n    /// provide.\n    ///\n    /// # Safety\n    ///\n    /// - The pointer must be valid for its intended use case.\n    /// - If the pointer refers to data, that data must remain valid for the capsule's\n    ///   lifetime, or the destructor must clean it up.\n    /// - The destructor, if provided, must be safe to call from any thread.\n    /// - The destructor should not panic. Panics cannot unwind across the FFI\n    ///   boundary into Python, so a panic will abort the process.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// use pyo3::{prelude::*, types::PyCapsule};\n    /// use std::ffi::c_void;\n    /// use std::ptr::NonNull;\n    ///\n    /// unsafe extern \"C\" fn free_data(capsule: *mut pyo3::ffi::PyObject) {\n    ///     let ptr = pyo3::ffi::PyCapsule_GetPointer(capsule, c\"my_module.data\".as_ptr());\n    ///     if !ptr.is_null() {\n    ///         drop(Box::from_raw(ptr as *mut u32));\n    ///     }\n    /// }\n    ///\n    /// Python::attach(|py| {\n    ///     let data = Box::new(42u32);\n    ///     let ptr = NonNull::new(Box::into_raw(data).cast::<c_void>()).unwrap();\n    ///\n    ///     // SAFETY: `ptr` is valid; `free_data` will deallocate it\n    ///     let capsule = unsafe {\n    ///         PyCapsule::new_with_pointer_and_destructor(\n    ///             py,\n    ///             ptr,\n    ///             c\"my_module.data\",\n    ///             Some(free_data),\n    ///         )\n    ///     }.unwrap();\n    /// });\n    /// ```\n    pub unsafe fn new_with_pointer_and_destructor<'py>(\n        py: Python<'py>,\n        pointer: NonNull<c_void>,\n        name: &'static CStr,\n        destructor: Option<ffi::PyCapsule_Destructor>,\n    ) -> PyResult<Bound<'py, Self>> {\n        let name_ptr = name.as_ptr();\n\n        // SAFETY:\n        // - `pointer` is non-null (guaranteed by `NonNull`)\n        // - `name_ptr` points to a valid C string (guaranteed by `&'static CStr`)\n        // - `destructor` is either None or a valid function pointer (caller guarantees)\n        // - Thread is attached to the Python interpreter\n        unsafe {\n            ffi::PyCapsule_New(pointer.as_ptr(), name_ptr, destructor)\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n        }\n    }\n\n    /// Imports an existing capsule.\n    ///\n    /// The `name` should match the path to the module attribute exactly in the form\n    /// of `\"module.attribute\"`, which should be the same as the name within the capsule.\n    ///\n    /// # Safety\n    ///\n    /// It must be known that the capsule imported by `name` contains an item of type `T`.\n    pub unsafe fn import<'py, T>(py: Python<'py>, name: &CStr) -> PyResult<&'py T> {\n        // SAFETY: `name` is a valid C string, thread is attached to the Python interpreter\n        let ptr = unsafe { ffi::PyCapsule_Import(name.as_ptr(), false as c_int) };\n        if ptr.is_null() {\n            Err(PyErr::fetch(py))\n        } else {\n            // SAFETY: caller has upheld the safety contract\n            Ok(unsafe { &*ptr.cast::<T>() })\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyCapsule`].\n///\n/// These methods are defined for the `Bound<'py, PyCapsule>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n///\n/// # Name checking\n///\n/// Capsules contain pointers to arbitrary data which is cast to a specific type at runtime. This is\n/// inherently quite dangerous, so Python allows capsules to be \"named\" to provide a hint as to\n/// what data is contained in the capsule. Although not a perfect solution, this is better than\n/// nothing.\n///\n/// The methods in this trait take the `name` as an `Option<&CStr>`, which is compared to the name\n/// stored in the capsule (with `None` being used to indicate the capsule has no name).\n#[doc(alias = \"PyCapsule\")]\npub trait PyCapsuleMethods<'py>: crate::sealed::Sealed {\n    /// Sets the context pointer in the capsule.\n    ///\n    /// Returns an error if this capsule is not valid.\n    ///\n    /// # Notes\n    ///\n    /// The context is treated much like the value of the capsule, but should likely act as\n    /// a place to store any state management when using the capsule.\n    ///\n    /// If you want to store a Rust value as the context, and drop it from the destructor, use\n    /// `Box::into_raw` to convert it into a pointer, see the example.\n    ///\n    /// # Example\n    ///\n    /// ```\n    /// use std::ffi::c_void;\n    /// use std::sync::mpsc::{channel, Sender};\n    /// use pyo3::{prelude::*, types::PyCapsule};\n    ///\n    /// let (tx, rx) = channel::<String>();\n    ///\n    /// fn destructor(val: u32, context: *mut c_void) {\n    ///     let ctx = unsafe { *Box::from_raw(context.cast::<Sender<String>>()) };\n    ///     ctx.send(\"Destructor called!\".to_string()).unwrap();\n    /// }\n    ///\n    /// Python::attach(|py| {\n    ///     let capsule =\n    ///         PyCapsule::new_with_destructor(py, 123, None, destructor as fn(u32, *mut c_void))\n    ///             .unwrap();\n    ///     let context = Box::new(tx);  // `Sender<String>` is our context, box it up and ship it!\n    ///     capsule.set_context(Box::into_raw(context).cast()).unwrap();\n    ///     // This scope will end, causing our destructor to be called...\n    /// });\n    ///\n    /// assert_eq!(rx.recv(), Ok(\"Destructor called!\".to_string()));\n    /// ```\n    fn set_context(&self, context: *mut c_void) -> PyResult<()>;\n\n    /// Gets the current context stored in the capsule. If there is no context, the pointer\n    /// will be null.\n    ///\n    /// Returns an error if this capsule is not valid.\n    fn context(&self) -> PyResult<*mut c_void>;\n\n    /// Obtains a reference dereferenced from the pointer of this capsule, without checking its name.\n    ///\n    /// Because this method encourages dereferencing the pointer for longer than necessary, it\n    /// is deprecated. Prefer to use [`pointer_checked()`][PyCapsuleMethods::pointer_checked]\n    /// and dereference the pointer only for as short a time as possible.\n    ///\n    /// # Safety\n    ///\n    /// This performs a dereference of the pointer returned from [`pointer()`][PyCapsuleMethods::pointer].\n    ///\n    /// See the safety notes on [`pointer_checked()`][PyCapsuleMethods::pointer_checked].\n    #[deprecated(since = \"0.27.0\", note = \"to be removed, see `pointer_checked()`\")]\n    unsafe fn reference<T>(&self) -> &T;\n\n    /// Gets the raw pointer stored in this capsule, without checking its name.\n    #[deprecated(since = \"0.27.0\", note = \"use `pointer_checked()` instead\")]\n    fn pointer(&self) -> *mut c_void;\n\n    /// Gets the raw pointer stored in this capsule.\n    ///\n    /// Returns an error if the capsule is not [valid][`PyCapsuleMethods::is_valid_checked`] with the given `name`.\n    ///\n    /// # Safety\n    ///\n    /// This function itself is not `unsafe`, but dereferencing the returned pointer to produce a reference\n    /// is very dangerous:\n    /// - The pointer will need to be [.cast()][NonNull::cast] to a concrete type before dereferencing.\n    ///   As per [name checking](#name-checking), there is no way to statically guarantee this cast is\n    ///   correct, the name is the best available hint to guard against accidental misuse.\n    /// - Arbitrary Python code can change the contents of the capsule, which may invalidate the\n    ///   pointer. The pointer and the reference produced by dereferencing the pointer should both\n    ///   be considered invalid after arbitrary Python code has run.\n    ///\n    /// Users should take care to cast to the correct type and consume the pointer for as little\n    /// duration as possible.\n    fn pointer_checked(&self, name: Option<&CStr>) -> PyResult<NonNull<c_void>>;\n\n    /// Checks if the capsule pointer is not null.\n    ///\n    /// This does not perform any check on the name of the capsule, which is the only mechanism\n    /// that Python provides to make sure that the pointer has the expected type. Prefer to use\n    /// [`is_valid_checked()`][Self::is_valid_checked()] instead.\n    #[deprecated(since = \"0.27.0\", note = \"use `is_valid_checked()` instead\")]\n    fn is_valid(&self) -> bool;\n\n    /// Checks that the capsule name matches `name` and that the pointer is not null.\n    fn is_valid_checked(&self, name: Option<&CStr>) -> bool;\n\n    /// Retrieves the name of this capsule, if set.\n    ///\n    /// Returns an error if this capsule is not valid.\n    ///\n    /// See [`CapsuleName`] for details of how to consume the return value.\n    fn name(&self) -> PyResult<Option<CapsuleName>>;\n}\n\nimpl<'py> PyCapsuleMethods<'py> for Bound<'py, PyCapsule> {\n    #[allow(clippy::not_unsafe_ptr_arg_deref)]\n    fn set_context(&self, context: *mut c_void) -> PyResult<()> {\n        // SAFETY:\n        // - `self.as_ptr()` is a valid object pointer\n        // - `context` is user-provided\n        // - thread is attached to the Python interpreter\n        let result = unsafe { ffi::PyCapsule_SetContext(self.as_ptr(), context) };\n        if result != 0 {\n            Err(PyErr::fetch(self.py()))\n        } else {\n            Ok(())\n        }\n    }\n\n    fn context(&self) -> PyResult<*mut c_void> {\n        // SAFETY:\n        // - `self.as_ptr()` is a valid object pointer\n        // - thread is attached to the Python interpreter\n        let ctx = unsafe { ffi::PyCapsule_GetContext(self.as_ptr()) };\n        if ctx.is_null() {\n            ensure_no_error(self.py())?\n        }\n        Ok(ctx)\n    }\n\n    #[allow(deprecated)]\n    unsafe fn reference<T>(&self) -> &T {\n        // SAFETY:\n        // - caller has upheld the safety contract\n        // - thread is attached to the Python interpreter\n        unsafe { &*self.pointer().cast() }\n    }\n\n    fn pointer(&self) -> *mut c_void {\n        // SAFETY: arguments to `PyCapsule_GetPointer` are valid, errors are handled properly\n        unsafe {\n            let ptr = ffi::PyCapsule_GetPointer(self.as_ptr(), name_ptr_ignore_error(self));\n            if ptr.is_null() {\n                ffi::PyErr_Clear();\n            }\n            ptr\n        }\n    }\n\n    fn pointer_checked(&self, name: Option<&CStr>) -> PyResult<NonNull<c_void>> {\n        // SAFETY:\n        // - `self.as_ptr()` is a valid object pointer\n        // - `name_ptr` is either a valid C string or null\n        // - thread is attached to the Python interpreter\n        let ptr = unsafe { ffi::PyCapsule_GetPointer(self.as_ptr(), name_ptr(name)) };\n        NonNull::new(ptr).ok_or_else(|| PyErr::fetch(self.py()))\n    }\n\n    fn is_valid(&self) -> bool {\n        // SAFETY: As well as if the stored pointer is null, PyCapsule_IsValid also returns false if\n        // self.as_ptr() is null or not a ptr to a PyCapsule object. Both of these are guaranteed\n        // to not be the case thanks to invariants of this PyCapsule struct.\n        let r = unsafe { ffi::PyCapsule_IsValid(self.as_ptr(), name_ptr_ignore_error(self)) };\n        r != 0\n    }\n\n    fn is_valid_checked(&self, name: Option<&CStr>) -> bool {\n        // SAFETY:\n        // - `self.as_ptr()` is a valid object pointer\n        // - `name_ptr` is either a valid C string or null\n        // - thread is attached to the Python interpreter\n        let r = unsafe { ffi::PyCapsule_IsValid(self.as_ptr(), name_ptr(name)) };\n        r != 0\n    }\n\n    fn name(&self) -> PyResult<Option<CapsuleName>> {\n        // SAFETY:\n        // - `self.as_ptr()` is a valid object pointer\n        // - thread is attached to the Python interpreter\n        let name = unsafe { ffi::PyCapsule_GetName(self.as_ptr()) };\n\n        match NonNull::new(name.cast_mut()) {\n            Some(name) => Ok(Some(CapsuleName { ptr: name })),\n            None => {\n                ensure_no_error(self.py())?;\n                Ok(None)\n            }\n        }\n    }\n}\n\n/// The name given to a `capsule` object.\n///\n/// This is a thin wrapper around `*const c_char`, which can be accessed with the [`as_ptr`][Self::as_ptr]\n/// method. The [`as_cstr`][Self::as_cstr] method can be used as a convenience to access the name as a `&CStr`.\n///\n/// There is no guarantee that this capsule name pointer valid for any length of time, as arbitrary\n/// Python code may change the name of a capsule object (by reaching native code which calls\n/// [`PyCapsule_SetName`][ffi::PyCapsule_SetName]). See the safety notes on [`as_cstr`][Self::as_cstr].\n#[derive(Clone, Copy)]\npub struct CapsuleName {\n    /// Pointer to the name c-string, known to be non-null.\n    ptr: NonNull<c_char>,\n}\n\nimpl CapsuleName {\n    /// Returns the capsule name as a `&CStr`.\n    ///\n    /// Note: this method is a thin wrapper around [`CStr::from_ptr`] so (as of Rust 1.91) incurs a\n    /// length calculation on each call.\n    ///\n    /// # Safety\n    ///\n    /// There is no guarantee that the capsule name remains valid for any length of time, as arbitrary\n    /// Python code may change the name of the capsule. The caller should be aware of any conventions\n    /// of the capsule in question related to the lifetime of the name (many capsule names are\n    /// statically allocated, i.e. have the `'static` lifetime, but Python does not require this).\n    ///\n    /// The returned lifetime `'a` is not related to the lifetime of the capsule itself, and the caller is\n    /// responsible for using the `&CStr` for as short a time as possible.\n    pub unsafe fn as_cstr<'a>(self) -> &'a CStr {\n        // SAFETY: caller has upheld the safety contract\n        unsafe { CStr::from_ptr(self.as_ptr()) }\n    }\n\n    /// Returns the raw pointer to the capsule name.\n    pub fn as_ptr(self) -> *const c_char {\n        self.ptr.as_ptr().cast_const()\n    }\n}\n\n// C layout, as casting the capsule pointer to `T` depends on `T` being first.\n#[repr(C)]\nstruct CapsuleContents<T: 'static + Send, D: FnOnce(T, *mut c_void) + Send> {\n    /// Value of the capsule\n    value: T,\n    /// Destructor to be used by the capsule\n    destructor: D,\n    /// Name used when creating the capsule\n    name: Option<CString>,\n}\n\n// Wrapping ffi::PyCapsule_Destructor for a user supplied FnOnce(T) for capsule destructor\nunsafe extern \"C\" fn capsule_destructor<T: 'static + Send, F: FnOnce(T, *mut c_void) + Send>(\n    capsule: *mut ffi::PyObject,\n) {\n    /// Gets the pointer and context from the capsule.\n    ///\n    /// # Safety\n    ///\n    /// - `capsule` must be a valid capsule object\n    unsafe fn get_pointer_ctx(capsule: *mut ffi::PyObject) -> (*mut c_void, *mut c_void) {\n        // SAFETY: `capsule` is known to be a borrowed reference to the capsule being destroyed\n        let name = unsafe { ffi::PyCapsule_GetName(capsule) };\n\n        // SAFETY:\n        // - `capsule` is known to be a borrowed reference to the capsule being destroyed\n        // - `name` is known to be the capsule's name\n        let ptr = unsafe { ffi::PyCapsule_GetPointer(capsule, name) };\n\n        // SAFETY:\n        // - `capsule` is known to be a borrowed reference to the capsule being destroyed\n        let ctx = unsafe { ffi::PyCapsule_GetContext(capsule) };\n\n        (ptr, ctx)\n    }\n\n    // SAFETY: `capsule` is known to be a valid capsule object\n    let (ptr, ctx) = unsafe { get_pointer_ctx(capsule) };\n\n    // SAFETY: `capsule` was knowingly constructed with a boxed `CapsuleContents<T, F>`\n    // and is now being destroyed, so we can move the data from the box.\n    let CapsuleContents::<T, F> {\n        value, destructor, ..\n    } = *unsafe { Box::from_raw(ptr.cast()) };\n\n    destructor(value, ctx);\n}\n\n/// Guarantee `T` is not zero sized at compile time.\n// credit: `<https://users.rust-lang.org/t/is-it-possible-to-assert-at-compile-time-that-foo-t-is-not-called-with-a-zst/67685>`\n#[doc(hidden)]\npub trait AssertNotZeroSized: Sized {\n    const _CONDITION: usize = (std::mem::size_of::<Self>() == 0) as usize;\n    const _CHECK: &'static str =\n        [\"PyCapsule value type T must not be zero-sized!\"][Self::_CONDITION];\n    #[allow(path_statements, clippy::no_effect)]\n    fn assert_not_zero_sized(&self) {\n        <Self as AssertNotZeroSized>::_CHECK;\n    }\n}\n\nimpl<T> AssertNotZeroSized for T {}\n\nfn ensure_no_error(py: Python<'_>) -> PyResult<()> {\n    if let Some(err) = PyErr::take(py) {\n        Err(err)\n    } else {\n        Ok(())\n    }\n}\n\nfn name_ptr_ignore_error(slf: &Bound<'_, PyCapsule>) -> *const c_char {\n    // SAFETY:\n    // - `slf` is known to be a valid capsule object\n    // - thread is attached to the Python interpreter\n    let ptr = unsafe { ffi::PyCapsule_GetName(slf.as_ptr()) };\n    if ptr.is_null() {\n        // SAFETY: thread is attached to the Python interpreter\n        unsafe { ffi::PyErr_Clear() };\n    }\n    ptr\n}\n\nfn name_ptr(name: Option<&CStr>) -> *const c_char {\n    match name {\n        Some(name) => name.as_ptr(),\n        None => ptr::null(),\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::prelude::PyModule;\n    use crate::types::capsule::PyCapsuleMethods;\n    use crate::types::module::PyModuleMethods;\n    use crate::{types::PyCapsule, Py, PyResult, Python};\n    use std::ffi::{c_void, CStr};\n    use std::ptr::NonNull;\n    use std::sync::mpsc::{channel, Sender};\n\n    const NAME: &CStr = c\"foo\";\n\n    #[test]\n    fn test_pycapsule_struct() {\n        #[repr(C)]\n        struct Foo {\n            pub val: u32,\n        }\n\n        impl Foo {\n            fn get_val(&self) -> u32 {\n                self.val\n            }\n        }\n\n        Python::attach(|py| {\n            let foo = Foo { val: 123 };\n\n            let cap = PyCapsule::new(py, foo, Some(NAME.to_owned())).unwrap();\n            assert!(cap.is_valid_checked(Some(NAME)));\n\n            let foo_capi = cap.pointer_checked(Some(NAME)).unwrap().cast::<Foo>();\n            // SAFETY: `foo_capi` contains a `Foo` and will be valid for the duration of the assert\n            assert_eq!(unsafe { foo_capi.as_ref() }.val, 123);\n            // SAFETY: as above\n            assert_eq!(unsafe { foo_capi.as_ref() }.get_val(), 123);\n            assert_eq!(\n                // SAFETY: `cap.name()` has a non-null name\n                unsafe { CStr::from_ptr(cap.name().unwrap().unwrap().as_ptr()) },\n                NAME\n            );\n            // SAFETY: as above\n            assert_eq!(unsafe { cap.name().unwrap().unwrap().as_cstr() }, NAME)\n        })\n    }\n\n    #[test]\n    fn test_pycapsule_func() {\n        fn foo(x: u32) -> u32 {\n            x\n        }\n\n        let cap: Py<PyCapsule> = Python::attach(|py| {\n            let cap = PyCapsule::new(py, foo as fn(u32) -> u32, Some(NAME.to_owned())).unwrap();\n            cap.into()\n        });\n\n        Python::attach(move |py| {\n            let f = cap\n                .bind(py)\n                .pointer_checked(Some(NAME))\n                .unwrap()\n                .cast::<fn(u32) -> u32>();\n            // SAFETY: `f` contains a `fn(u32) -> u32` and will be valid for the duration of the assert\n            assert_eq!(unsafe { f.as_ref() }(123), 123);\n        });\n    }\n\n    #[test]\n    fn test_pycapsule_context() {\n        Python::attach(|py| {\n            let cap = PyCapsule::new(py, 0, Some(NAME.to_owned())).unwrap();\n\n            let c = cap.context().unwrap();\n            assert!(c.is_null());\n\n            let ctx = Box::new(123_u32);\n            cap.set_context(Box::into_raw(ctx).cast()).unwrap();\n\n            let ctx_ptr: *mut c_void = cap.context().unwrap();\n            // SAFETY: `ctx_ptr` contains a boxed `u32` which is being moved out of the capsule\n            let ctx = unsafe { *Box::from_raw(ctx_ptr.cast::<u32>()) };\n            assert_eq!(ctx, 123);\n        })\n    }\n\n    #[test]\n    fn test_pycapsule_import() {\n        #[repr(C)]\n        struct Foo {\n            pub val: u32,\n        }\n\n        Python::attach(|py| {\n            let foo = Foo { val: 123 };\n            let name = c\"builtins.capsule\";\n\n            let capsule = PyCapsule::new(py, foo, Some(name.to_owned())).unwrap();\n\n            let module = PyModule::import(py, \"builtins\").unwrap();\n            module.add(\"capsule\", capsule).unwrap();\n\n            // check error when wrong named passed for capsule.\n            // SAFETY: this function will fail so the cast is never done\n            let result: PyResult<&Foo> = unsafe { PyCapsule::import(py, c\"builtins.non_existent\") };\n            assert!(result.is_err());\n\n            // correct name is okay.\n            // SAFETY: we know the capsule at `name` contains a `Foo`\n            let cap: &Foo = unsafe { PyCapsule::import(py, name) }.unwrap();\n            assert_eq!(cap.val, 123);\n        })\n    }\n\n    #[test]\n    fn test_vec_storage() {\n        let cap: Py<PyCapsule> = Python::attach(|py| {\n            let stuff: Vec<u8> = vec![1, 2, 3, 4];\n            let cap = PyCapsule::new(py, stuff, Some(NAME.to_owned())).unwrap();\n            cap.into()\n        });\n\n        Python::attach(move |py| {\n            let stuff = cap\n                .bind(py)\n                .pointer_checked(Some(NAME))\n                .unwrap()\n                .cast::<Vec<u8>>();\n            // SAFETY: `stuff` contains a `Vec<u8>` and will be valid for the duration of the assert\n            assert_eq!(unsafe { stuff.as_ref() }, &[1, 2, 3, 4]);\n        })\n    }\n\n    #[test]\n    fn test_vec_context() {\n        let context: Vec<u8> = vec![1, 2, 3, 4];\n\n        let cap: Py<PyCapsule> = Python::attach(|py| {\n            let cap = PyCapsule::new(py, 0, Some(NAME.to_owned())).unwrap();\n            cap.set_context(Box::into_raw(Box::new(&context)).cast())\n                .unwrap();\n\n            cap.into()\n        });\n\n        Python::attach(move |py| {\n            let ctx_ptr: *mut c_void = cap.bind(py).context().unwrap();\n            // SAFETY: `ctx_ptr` contains a boxed `&Vec<u8>` which is being moved out of the capsule\n            let ctx = unsafe { *Box::from_raw(ctx_ptr.cast::<&Vec<u8>>()) };\n            assert_eq!(ctx, &vec![1_u8, 2, 3, 4]);\n        })\n    }\n\n    #[test]\n    fn test_pycapsule_destructor() {\n        let (tx, rx) = channel::<bool>();\n\n        fn destructor(_val: u32, ctx: *mut c_void) {\n            assert!(!ctx.is_null());\n            // SAFETY: `ctx` is known to be a boxed `Sender<bool>` needing deletion\n            let context = unsafe { *Box::from_raw(ctx.cast::<Sender<bool>>()) };\n            context.send(true).unwrap();\n        }\n\n        Python::attach(move |py| {\n            let cap =\n                PyCapsule::new_with_destructor(py, 0, Some(NAME.to_owned()), destructor).unwrap();\n            cap.set_context(Box::into_raw(Box::new(tx)).cast()).unwrap();\n        });\n\n        // the destructor was called.\n        assert_eq!(rx.recv(), Ok(true));\n    }\n\n    #[test]\n    fn test_pycapsule_no_name() {\n        Python::attach(|py| {\n            let cap = PyCapsule::new(py, 0usize, None).unwrap();\n\n            assert_eq!(\n                // SAFETY: `cap` is known to contain a `usize`\n                unsafe { cap.pointer_checked(None).unwrap().cast::<usize>().as_ref() },\n                &0usize\n            );\n            assert!(cap.name().unwrap().is_none());\n            assert_eq!(cap.context().unwrap(), std::ptr::null_mut());\n        });\n    }\n\n    #[test]\n    fn test_pycapsule_new_with_pointer() {\n        extern \"C\" fn dummy_handler(_: *mut c_void) -> *mut c_void {\n            std::ptr::null_mut()\n        }\n\n        let fn_ptr =\n            NonNull::new(dummy_handler as *mut c_void).expect(\"function pointer is non-null\");\n\n        Python::attach(|py| {\n            // SAFETY: `fn_ptr` is known to point to `dummy_handler`\n            let capsule =\n                unsafe { PyCapsule::new_with_pointer(py, fn_ptr, c\"test.dummy_handler\") }.unwrap();\n\n            let retrieved_ptr = capsule\n                .pointer_checked(Some(c\"test.dummy_handler\"))\n                .unwrap();\n            assert_eq!(retrieved_ptr.as_ptr(), fn_ptr.as_ptr());\n        });\n    }\n\n    #[test]\n    fn test_pycapsule_new_with_pointer_and_destructor() {\n        use std::sync::mpsc::{channel, TryRecvError};\n\n        let (tx, rx) = channel::<bool>();\n\n        unsafe extern \"C\" fn destructor_fn(capsule: *mut crate::ffi::PyObject) {\n            // SAFETY:\n            // - `capsule` is a valid capsule object being destroyed by Python\n            // - The context was set to a valid `Box<Sender<bool>>` below\n            unsafe {\n                let ctx = crate::ffi::PyCapsule_GetContext(capsule);\n                if !ctx.is_null() {\n                    let sender: Box<Sender<bool>> = Box::from_raw(ctx.cast());\n                    let _ = sender.send(true);\n                }\n            }\n        }\n\n        let dummy_ptr =\n            NonNull::new(0xDEADBEEF as *mut c_void).expect(\"function pointer is non-null\");\n\n        Python::attach(|py| {\n            // SAFETY:\n            // - `dummy_ptr` is non-null (it's a made-up address for testing)\n            // - We're providing a valid destructor function\n            let capsule = unsafe {\n                PyCapsule::new_with_pointer_and_destructor(\n                    py,\n                    dummy_ptr,\n                    c\"test.destructor_capsule\",\n                    Some(destructor_fn),\n                )\n            }\n            .unwrap();\n\n            // Store the sender in the capsule's context\n            let sender_box = Box::new(tx);\n            capsule\n                .set_context(Box::into_raw(sender_box).cast())\n                .unwrap();\n\n            // The destructor hasn't fired yet\n            assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));\n        });\n\n        // After Python::attach scope ends, the capsule should be destroyed\n        assert_eq!(rx.recv(), Ok(true));\n    }\n\n    #[test]\n    fn test_pycapsule_pointer_checked_wrong_name() {\n        Python::attach(|py| {\n            let cap = PyCapsule::new(py, 123u32, Some(c\"correct.name\".to_owned())).unwrap();\n\n            // Requesting with wrong name should fail\n            let result = cap.pointer_checked(Some(c\"wrong.name\"));\n            assert!(result.is_err());\n\n            // Requesting with None when capsule has a name should also fail\n            let result = cap.pointer_checked(None);\n            assert!(result.is_err());\n        });\n    }\n\n    #[test]\n    fn test_pycapsule_pointer_checked_none_vs_some() {\n        Python::attach(|py| {\n            // Capsule with no name\n            let cap_no_name = PyCapsule::new(py, 123u32, None).unwrap();\n\n            // Should succeed with None\n            assert!(cap_no_name.pointer_checked(None).is_ok());\n\n            // Should fail with Some(name)\n            let result = cap_no_name.pointer_checked(Some(c\"some.name\"));\n            assert!(result.is_err());\n        });\n    }\n\n    #[test]\n    fn test_pycapsule_is_valid_checked_wrong_name() {\n        Python::attach(|py| {\n            let cap = PyCapsule::new(py, 123u32, Some(c\"correct.name\".to_owned())).unwrap();\n\n            // Should be valid with correct name\n            assert!(cap.is_valid_checked(Some(c\"correct.name\")));\n\n            // Should be invalid with wrong name\n            assert!(!cap.is_valid_checked(Some(c\"wrong.name\")));\n\n            // Should be invalid with None when capsule has a name\n            assert!(!cap.is_valid_checked(None));\n        });\n    }\n\n    #[test]\n    fn test_pycapsule_is_valid_checked_no_name() {\n        Python::attach(|py| {\n            let cap = PyCapsule::new(py, 123u32, None).unwrap();\n\n            // Should be valid with None\n            assert!(cap.is_valid_checked(None));\n\n            // Should be invalid with any name\n            assert!(!cap.is_valid_checked(Some(c\"any.name\")));\n        });\n    }\n\n    #[test]\n    fn test_pycapsule_context_on_invalid_capsule() {\n        Python::attach(|py| {\n            let cap = PyCapsule::new(py, 123u32, Some(NAME.to_owned())).unwrap();\n\n            // Invalidate the capsule\n            // SAFETY: intentionally breaking the capsule for testing\n            unsafe {\n                crate::ffi::PyCapsule_SetPointer(cap.as_ptr(), std::ptr::null_mut());\n            }\n\n            // context() on invalid capsule should fail\n            let result = cap.context();\n            assert!(result.is_err());\n        });\n    }\n\n    #[test]\n    fn test_pycapsule_import_wrong_module() {\n        Python::attach(|py| {\n            // Try to import from a non-existent module\n            // SAFETY: we expect this to fail, no cast will occur\n            let result: PyResult<&u32> =\n                unsafe { PyCapsule::import(py, c\"nonexistent_module.capsule\") };\n            assert!(result.is_err());\n        });\n    }\n\n    #[test]\n    fn test_pycapsule_import_wrong_attribute() {\n        Python::attach(|py| {\n            // Create a capsule and register it\n            let cap = PyCapsule::new(py, 123u32, Some(c\"builtins.test_cap\".to_owned())).unwrap();\n            let module = crate::prelude::PyModule::import(py, \"builtins\").unwrap();\n            module.add(\"test_cap\", cap).unwrap();\n\n            // Try to import with wrong attribute name\n            // SAFETY: we expect this to fail\n            let result: PyResult<&u32> =\n                unsafe { PyCapsule::import(py, c\"builtins.wrong_attribute\") };\n            assert!(result.is_err());\n        });\n    }\n}\n"
  },
  {
    "path": "src/types/code.rs",
    "content": "use super::PyAnyMethods as _;\nuse super::PyDict;\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::py_result_ext::PyResultExt;\n#[cfg(any(Py_LIMITED_API, PyPy))]\nuse crate::sync::PyOnceLock;\n#[cfg(any(Py_LIMITED_API, PyPy))]\nuse crate::types::{PyType, PyTypeMethods};\n#[cfg(any(Py_LIMITED_API, PyPy))]\nuse crate::Py;\nuse crate::{ffi, Bound, PyAny, PyErr, PyResult, Python};\nuse std::ffi::CStr;\n\n/// Represents a Python code object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyCode>`][crate::Py] or [`Bound<'py, PyCode>`][crate::Bound].\n#[repr(transparent)]\npub struct PyCode(PyAny);\n\n#[cfg(not(any(Py_LIMITED_API, PyPy)))]\npyobject_native_type_core!(\n    PyCode,\n    pyobject_native_static_type_object!(ffi::PyCode_Type),\n    \"types\",\n    \"CodeType\",\n    #checkfunction=ffi::PyCode_Check\n);\n\n#[cfg(any(Py_LIMITED_API, PyPy))]\npyobject_native_type_core!(\n    PyCode,\n    |py| {\n        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        TYPE.import(py, \"types\", \"CodeType\").unwrap().as_type_ptr()\n    },\n    \"types\",\n    \"CodeType\"\n);\n\n/// Compilation mode of [`PyCode::compile`]\npub enum PyCodeInput {\n    /// Python grammar for isolated expressions\n    Eval,\n    /// Python grammar for sequences of statements as read from a file\n    File,\n}\n\nimpl PyCode {\n    /// Compiles code in the given context.\n    ///\n    /// `input` decides whether `code` is treated as\n    /// - [`PyCodeInput::Eval`]: an isolated expression\n    /// - [`PyCodeInput::File`]: a sequence of statements\n    pub fn compile<'py>(\n        py: Python<'py>,\n        code: &CStr,\n        filename: &CStr,\n        input: PyCodeInput,\n    ) -> PyResult<Bound<'py, PyCode>> {\n        let start = match input {\n            PyCodeInput::Eval => ffi::Py_eval_input,\n            PyCodeInput::File => ffi::Py_file_input,\n        };\n        unsafe {\n            ffi::Py_CompileString(code.as_ptr(), filename.as_ptr(), start)\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n        }\n    }\n\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    pub(crate) fn empty<'py>(\n        py: Python<'py>,\n        file_name: &CStr,\n        func_name: &CStr,\n        first_line_number: i32,\n    ) -> Bound<'py, PyCode> {\n        unsafe {\n            ffi::PyCode_NewEmpty(file_name.as_ptr(), func_name.as_ptr(), first_line_number)\n                .cast::<ffi::PyObject>()\n                .assume_owned(py)\n                .cast_into_unchecked()\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyCode`].\n///\n/// These methods are defined for the `Bound<'py, PyCode>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\npub trait PyCodeMethods<'py> {\n    /// Runs code object.\n    ///\n    /// If `globals` is `None`, it defaults to Python module `__main__`.\n    /// If `locals` is `None`, it defaults to the value of `globals`.\n    fn run(\n        &self,\n        globals: Option<&Bound<'py, PyDict>>,\n        locals: Option<&Bound<'py, PyDict>>,\n    ) -> PyResult<Bound<'py, PyAny>>;\n}\n\nimpl<'py> PyCodeMethods<'py> for Bound<'py, PyCode> {\n    fn run(\n        &self,\n        globals: Option<&Bound<'py, PyDict>>,\n        locals: Option<&Bound<'py, PyDict>>,\n    ) -> PyResult<Bound<'py, PyAny>> {\n        let mptr = unsafe {\n            ffi::compat::PyImport_AddModuleRef(c\"__main__\".as_ptr())\n                .assume_owned_or_err(self.py())?\n        };\n        let attr = mptr.getattr(crate::intern!(self.py(), \"__dict__\"))?;\n        let globals = match globals {\n            Some(globals) => globals,\n            None => attr.cast::<PyDict>()?,\n        };\n        let locals = locals.unwrap_or(globals);\n\n        // If `globals` don't provide `__builtins__`, most of the code will fail if Python\n        // version is <3.10. That's probably not what user intended, so insert `__builtins__`\n        // for them.\n        //\n        // See also:\n        // - https://github.com/python/cpython/pull/24564 (the same fix in CPython 3.10)\n        // - https://github.com/PyO3/pyo3/issues/3370\n        let builtins_s = crate::intern!(self.py(), \"__builtins__\");\n        let has_builtins = globals.contains(builtins_s)?;\n        if !has_builtins {\n            crate::sync::critical_section::with_critical_section(globals, || {\n                // check if another thread set __builtins__ while this thread was blocked on the critical section\n                let has_builtins = globals.contains(builtins_s)?;\n                if !has_builtins {\n                    // Inherit current builtins.\n                    let builtins = unsafe { ffi::PyEval_GetBuiltins() };\n\n                    // `PyDict_SetItem` doesn't take ownership of `builtins`, but `PyEval_GetBuiltins`\n                    // seems to return a borrowed reference, so no leak here.\n                    if unsafe {\n                        ffi::PyDict_SetItem(globals.as_ptr(), builtins_s.as_ptr(), builtins)\n                    } == -1\n                    {\n                        return Err(PyErr::fetch(self.py()));\n                    }\n                }\n                Ok(())\n            })?;\n        }\n\n        unsafe {\n            ffi::PyEval_EvalCode(self.as_ptr(), globals.as_ptr(), locals.as_ptr())\n                .assume_owned_or_err(self.py())\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    #[test]\n    fn test_type_object() {\n        use crate::types::PyTypeMethods;\n        use crate::{PyTypeInfo, Python};\n\n        Python::attach(|py| {\n            assert_eq!(super::PyCode::type_object(py).name().unwrap(), \"code\");\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/complex.rs",
    "content": "#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\nuse crate::py_result_ext::PyResultExt;\n#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\nuse crate::types::any::PyAnyMethods;\nuse crate::{ffi, Bound, PyAny, Python};\nuse std::ffi::c_double;\n\n/// Represents a Python [`complex`](https://docs.python.org/3/library/functions.html#complex) object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyComplex>`][crate::Py] or [`Bound<'py, PyComplex>`][Bound].\n///\n/// For APIs available on `complex` objects, see the [`PyComplexMethods`] trait which is implemented for\n/// [`Bound<'py, PyComplex>`][Bound].\n///\n/// Note that `PyComplex` supports only basic operations. For advanced operations\n/// consider using [num-complex](https://docs.rs/num-complex)'s [`Complex`] type instead.\n/// This optional dependency can be activated with the `num-complex` feature flag.\n///\n/// [`Complex`]: https://docs.rs/num-complex/latest/num_complex/struct.Complex.html\n#[repr(transparent)]\npub struct PyComplex(PyAny);\n\npyobject_subclassable_native_type!(PyComplex, ffi::PyComplexObject);\n\npyobject_native_type!(\n    PyComplex,\n    ffi::PyComplexObject,\n    pyobject_native_static_type_object!(ffi::PyComplex_Type),\n    \"builtins\",\n    \"complex\",\n    #checkfunction=ffi::PyComplex_Check\n);\n\nimpl PyComplex {\n    /// Creates a new `PyComplex` from the given real and imaginary values.\n    pub fn from_doubles(py: Python<'_>, real: c_double, imag: c_double) -> Bound<'_, PyComplex> {\n        use crate::ffi_ptr_ext::FfiPtrExt;\n        unsafe {\n            ffi::PyComplex_FromDoubles(real, imag)\n                .assume_owned(py)\n                .cast_into_unchecked()\n        }\n    }\n}\n\n#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\nmod not_limited_impls {\n    use crate::Borrowed;\n\n    use super::*;\n    use std::ops::{Add, Div, Mul, Neg, Sub};\n\n    macro_rules! bin_ops {\n        ($trait:ident, $fn:ident, $op:tt) => {\n            impl<'py> $trait for Borrowed<'_, 'py, PyComplex> {\n                type Output = Bound<'py, PyComplex>;\n                fn $fn(self, other: Self) -> Self::Output {\n                    PyAnyMethods::$fn(self.as_any(), other)\n                    .cast_into().expect(\n                        concat!(\"Complex method \",\n                            stringify!($fn),\n                            \" failed.\")\n                        )\n                }\n            }\n\n            impl<'py> $trait for &Bound<'py, PyComplex> {\n                type Output = Bound<'py, PyComplex>;\n                fn $fn(self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex> {\n                    self.as_borrowed() $op other.as_borrowed()\n                }\n            }\n\n            impl<'py> $trait<Bound<'py, PyComplex>> for &Bound<'py, PyComplex> {\n                type Output = Bound<'py, PyComplex>;\n                fn $fn(self, other: Bound<'py, PyComplex>) -> Bound<'py, PyComplex> {\n                    self.as_borrowed() $op other.as_borrowed()\n                }\n            }\n\n            impl<'py> $trait for Bound<'py, PyComplex> {\n                type Output = Bound<'py, PyComplex>;\n                fn $fn(self, other: Bound<'py, PyComplex>) -> Bound<'py, PyComplex> {\n                    self.as_borrowed() $op other.as_borrowed()\n                }\n            }\n\n            impl<'py> $trait<&Self> for Bound<'py, PyComplex> {\n                type Output = Bound<'py, PyComplex>;\n                fn $fn(self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex> {\n                    self.as_borrowed() $op other.as_borrowed()\n                }\n            }\n        };\n    }\n\n    bin_ops!(Add, add, +);\n    bin_ops!(Sub, sub, -);\n    bin_ops!(Mul, mul, *);\n    bin_ops!(Div, div, /);\n\n    impl<'py> Neg for Borrowed<'_, 'py, PyComplex> {\n        type Output = Bound<'py, PyComplex>;\n        fn neg(self) -> Self::Output {\n            PyAnyMethods::neg(self.as_any())\n                .cast_into()\n                .expect(\"Complex method __neg__ failed.\")\n        }\n    }\n\n    impl<'py> Neg for &Bound<'py, PyComplex> {\n        type Output = Bound<'py, PyComplex>;\n        fn neg(self) -> Bound<'py, PyComplex> {\n            -self.as_borrowed()\n        }\n    }\n\n    impl<'py> Neg for Bound<'py, PyComplex> {\n        type Output = Bound<'py, PyComplex>;\n        fn neg(self) -> Bound<'py, PyComplex> {\n            -self.as_borrowed()\n        }\n    }\n\n    #[cfg(test)]\n    mod tests {\n        use super::PyComplex;\n        use crate::{types::complex::PyComplexMethods, Python};\n        use assert_approx_eq::assert_approx_eq;\n\n        #[test]\n        fn test_add() {\n            Python::attach(|py| {\n                let l = PyComplex::from_doubles(py, 3.0, 1.2);\n                let r = PyComplex::from_doubles(py, 1.0, 2.6);\n                let res = l + r;\n                assert_approx_eq!(res.real(), 4.0);\n                assert_approx_eq!(res.imag(), 3.8);\n            });\n        }\n\n        #[test]\n        fn test_sub() {\n            Python::attach(|py| {\n                let l = PyComplex::from_doubles(py, 3.0, 1.2);\n                let r = PyComplex::from_doubles(py, 1.0, 2.6);\n                let res = l - r;\n                assert_approx_eq!(res.real(), 2.0);\n                assert_approx_eq!(res.imag(), -1.4);\n            });\n        }\n\n        #[test]\n        fn test_mul() {\n            Python::attach(|py| {\n                let l = PyComplex::from_doubles(py, 3.0, 1.2);\n                let r = PyComplex::from_doubles(py, 1.0, 2.6);\n                let res = l * r;\n                assert_approx_eq!(res.real(), -0.12);\n                assert_approx_eq!(res.imag(), 9.0);\n            });\n        }\n\n        #[test]\n        fn test_div() {\n            Python::attach(|py| {\n                let l = PyComplex::from_doubles(py, 3.0, 1.2);\n                let r = PyComplex::from_doubles(py, 1.0, 2.6);\n                let res = l / r;\n                assert_approx_eq!(res.real(), 0.788_659_793_814_432_9);\n                assert_approx_eq!(res.imag(), -0.850_515_463_917_525_7);\n            });\n        }\n\n        #[test]\n        fn test_neg() {\n            Python::attach(|py| {\n                let val = PyComplex::from_doubles(py, 3.0, 1.2);\n                let res = -val;\n                assert_approx_eq!(res.real(), -3.0);\n                assert_approx_eq!(res.imag(), -1.2);\n            });\n        }\n\n        #[test]\n        fn test_abs() {\n            Python::attach(|py| {\n                let val = PyComplex::from_doubles(py, 3.0, 1.2);\n                assert_approx_eq!(val.abs(), 3.231_098_884_280_702_2);\n            });\n        }\n\n        #[test]\n        fn test_pow() {\n            Python::attach(|py| {\n                let l = PyComplex::from_doubles(py, 3.0, 1.2);\n                let r = PyComplex::from_doubles(py, 1.2, 2.6);\n                let val = l.pow(&r);\n                assert_approx_eq!(val.real(), -1.419_309_997_016_603_7);\n                assert_approx_eq!(val.imag(), -0.541_297_466_033_544_6);\n            });\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyComplex`].\n///\n/// These methods are defined for the `Bound<'py, PyComplex>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyComplex\")]\npub trait PyComplexMethods<'py>: crate::sealed::Sealed {\n    /// Returns the real part of the complex number.\n    fn real(&self) -> c_double;\n    /// Returns the imaginary part of the complex number.\n    fn imag(&self) -> c_double;\n    /// Returns `|self|`.\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    fn abs(&self) -> c_double;\n    /// Returns `self` raised to the power of `other`.\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    fn pow(&self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex>;\n}\n\nimpl<'py> PyComplexMethods<'py> for Bound<'py, PyComplex> {\n    fn real(&self) -> c_double {\n        unsafe { ffi::PyComplex_RealAsDouble(self.as_ptr()) }\n    }\n\n    fn imag(&self) -> c_double {\n        unsafe { ffi::PyComplex_ImagAsDouble(self.as_ptr()) }\n    }\n\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    fn abs(&self) -> c_double {\n        PyAnyMethods::abs(self.as_any())\n            .cast_into()\n            .expect(\"Complex method __abs__ failed.\")\n            .extract()\n            .expect(\"Failed to extract to c double.\")\n    }\n\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    fn pow(&self, other: &Bound<'py, PyComplex>) -> Bound<'py, PyComplex> {\n        Python::attach(|py| {\n            PyAnyMethods::pow(self.as_any(), other, py.None())\n                .cast_into()\n                .expect(\"Complex method __pow__ failed.\")\n        })\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::PyComplex;\n    use crate::{types::complex::PyComplexMethods, Python};\n    use assert_approx_eq::assert_approx_eq;\n\n    #[test]\n    fn test_from_double() {\n        Python::attach(|py| {\n            let complex = PyComplex::from_doubles(py, 3.0, 1.2);\n            assert_approx_eq!(complex.real(), 3.0);\n            assert_approx_eq!(complex.imag(), 1.2);\n        });\n    }\n}\n"
  },
  {
    "path": "src/types/datetime.rs",
    "content": "//! Safe Rust wrappers for types defined in the Python `datetime` library\n//!\n//! For more details about these types, see the [Python\n//! documentation](https://docs.python.org/3/library/datetime.html)\n\n#[cfg(not(Py_LIMITED_API))]\nuse crate::err::PyErr;\nuse crate::err::PyResult;\n#[cfg(not(Py_3_9))]\nuse crate::exceptions::PyImportError;\n#[cfg(not(Py_LIMITED_API))]\nuse crate::ffi::{\n    self, PyDateTime_CAPI, PyDateTime_DATE_GET_FOLD, PyDateTime_DATE_GET_HOUR,\n    PyDateTime_DATE_GET_MICROSECOND, PyDateTime_DATE_GET_MINUTE, PyDateTime_DATE_GET_SECOND,\n    PyDateTime_DELTA_GET_DAYS, PyDateTime_DELTA_GET_MICROSECONDS, PyDateTime_DELTA_GET_SECONDS,\n    PyDateTime_FromTimestamp, PyDateTime_GET_DAY, PyDateTime_GET_MONTH, PyDateTime_GET_YEAR,\n    PyDateTime_IMPORT, PyDateTime_TIME_GET_FOLD, PyDateTime_TIME_GET_HOUR,\n    PyDateTime_TIME_GET_MICROSECOND, PyDateTime_TIME_GET_MINUTE, PyDateTime_TIME_GET_SECOND,\n    PyDate_FromTimestamp,\n};\n#[cfg(all(Py_3_10, not(Py_LIMITED_API)))]\nuse crate::ffi::{PyDateTime_DATE_GET_TZINFO, PyDateTime_TIME_GET_TZINFO, Py_IsNone};\n#[cfg(Py_LIMITED_API)]\nuse crate::type_object::PyTypeInfo;\n#[cfg(Py_LIMITED_API)]\nuse crate::types::typeobject::PyTypeMethods;\n#[cfg(Py_LIMITED_API)]\nuse crate::types::IntoPyDict;\nuse crate::types::{any::PyAnyMethods, PyString, PyType};\n#[cfg(not(Py_LIMITED_API))]\nuse crate::{ffi_ptr_ext::FfiPtrExt, py_result_ext::PyResultExt, types::PyTuple, BoundObject};\nuse crate::{sync::PyOnceLock, Py};\nuse crate::{Borrowed, Bound, IntoPyObject, PyAny, Python};\n#[cfg(not(Py_LIMITED_API))]\nuse std::ffi::c_int;\n\n#[cfg(not(Py_LIMITED_API))]\nfn ensure_datetime_api(py: Python<'_>) -> PyResult<&'static PyDateTime_CAPI> {\n    if let Some(api) = unsafe { pyo3_ffi::PyDateTimeAPI().as_ref() } {\n        Ok(api)\n    } else {\n        unsafe {\n            PyDateTime_IMPORT();\n            pyo3_ffi::PyDateTimeAPI().as_ref()\n        }\n        .ok_or_else(|| PyErr::fetch(py))\n    }\n}\n\n#[cfg(not(Py_LIMITED_API))]\nfn expect_datetime_api(py: Python<'_>) -> &'static PyDateTime_CAPI {\n    ensure_datetime_api(py).expect(\"failed to import `datetime` C API\")\n}\n\n// Type Check macros\n//\n// These are bindings around the C API typecheck macros, all of them return\n// `1` if True and `0` if False. In all type check macros, the argument (`op`)\n// must not be `NULL`. The implementations here all call ensure_datetime_api\n// to ensure that the PyDateTimeAPI is initialized before use\n//\n//\n// # Safety\n//\n// These functions must only be called when the GIL is held!\n#[cfg(not(Py_LIMITED_API))]\nmacro_rules! ffi_fun_with_autoinit {\n    ($(#[$outer:meta] unsafe fn $name: ident($arg: ident: *mut PyObject) -> $ret: ty;)*) => {\n        $(\n            #[$outer]\n            #[allow(non_snake_case)]\n            /// # Safety\n            ///\n            /// Must only be called while the GIL is held\n            unsafe fn $name($arg: *mut crate::ffi::PyObject) -> $ret {\n\n                let _ = ensure_datetime_api(unsafe { Python::assume_attached() });\n                unsafe { crate::ffi::$name($arg) }\n            }\n        )*\n\n\n    };\n}\n\n#[cfg(not(Py_LIMITED_API))]\nffi_fun_with_autoinit! {\n    /// Check if `op` is a `PyDateTimeAPI.DateType` or subtype.\n    unsafe fn PyDate_Check(op: *mut PyObject) -> c_int;\n\n    /// Check if `op` is a `PyDateTimeAPI.DateTimeType` or subtype.\n    unsafe fn PyDateTime_Check(op: *mut PyObject) -> c_int;\n\n    /// Check if `op` is a `PyDateTimeAPI.TimeType` or subtype.\n    unsafe fn PyTime_Check(op: *mut PyObject) -> c_int;\n\n    /// Check if `op` is a `PyDateTimeAPI.DetaType` or subtype.\n    unsafe fn PyDelta_Check(op: *mut PyObject) -> c_int;\n\n    /// Check if `op` is a `PyDateTimeAPI.TZInfoType` or subtype.\n    unsafe fn PyTZInfo_Check(op: *mut PyObject) -> c_int;\n}\n\n// Access traits\n\n/// Trait for accessing the date components of a struct containing a date.\n#[cfg(not(Py_LIMITED_API))]\npub trait PyDateAccess {\n    /// Returns the year, as a positive int.\n    ///\n    /// Implementations should conform to the upstream documentation:\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_GET_YEAR>\n    fn get_year(&self) -> i32;\n    /// Returns the month, as an int from 1 through 12.\n    ///\n    /// Implementations should conform to the upstream documentation:\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_GET_MONTH>\n    fn get_month(&self) -> u8;\n    /// Returns the day, as an int from 1 through 31.\n    ///\n    /// Implementations should conform to the upstream documentation:\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_GET_DAY>\n    fn get_day(&self) -> u8;\n}\n\n/// Trait for accessing the components of a struct containing a timedelta.\n///\n/// Note: These access the individual components of a (day, second,\n/// microsecond) representation of the delta, they are *not* intended as\n/// aliases for calculating the total duration in each of these units.\n#[cfg(not(Py_LIMITED_API))]\npub trait PyDeltaAccess {\n    /// Returns the number of days, as an int from -999999999 to 999999999.\n    ///\n    /// Implementations should conform to the upstream documentation:\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_DELTA_GET_DAYS>\n    fn get_days(&self) -> i32;\n    /// Returns the number of seconds, as an int from 0 through 86399.\n    ///\n    /// Implementations should conform to the upstream documentation:\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_DELTA_GET_SECONDS>\n    fn get_seconds(&self) -> i32;\n    /// Returns the number of microseconds, as an int from 0 through 999999.\n    ///\n    /// Implementations should conform to the upstream documentation:\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_DELTA_GET_MICROSECONDS>\n    fn get_microseconds(&self) -> i32;\n}\n\n/// Trait for accessing the time components of a struct containing a time.\n#[cfg(not(Py_LIMITED_API))]\npub trait PyTimeAccess {\n    /// Returns the hour, as an int from 0 through 23.\n    ///\n    /// Implementations should conform to the upstream documentation:\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_DATE_GET_HOUR>\n    fn get_hour(&self) -> u8;\n    /// Returns the minute, as an int from 0 through 59.\n    ///\n    /// Implementations should conform to the upstream documentation:\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_DATE_GET_MINUTE>\n    fn get_minute(&self) -> u8;\n    /// Returns the second, as an int from 0 through 59.\n    ///\n    /// Implementations should conform to the upstream documentation:\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_DATE_GET_SECOND>\n    fn get_second(&self) -> u8;\n    /// Returns the microsecond, as an int from 0 through 999999.\n    ///\n    /// Implementations should conform to the upstream documentation:\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_DATE_GET_MICROSECOND>\n    fn get_microsecond(&self) -> u32;\n    /// Returns whether this date is the later of two moments with the\n    /// same representation, during a repeated interval.\n    ///\n    /// This typically occurs at the end of daylight savings time. Only valid if the\n    /// represented time is ambiguous.\n    /// See [PEP 495](https://www.python.org/dev/peps/pep-0495/) for more detail.\n    fn get_fold(&self) -> bool;\n}\n\n/// Trait for accessing the components of a struct containing a tzinfo.\npub trait PyTzInfoAccess<'py> {\n    /// Returns the tzinfo (which may be None).\n    ///\n    /// Implementations should conform to the upstream documentation:\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_DATE_GET_TZINFO>\n    /// <https://docs.python.org/3/c-api/datetime.html#c.PyDateTime_TIME_GET_TZINFO>\n    fn get_tzinfo(&self) -> Option<Bound<'py, PyTzInfo>>;\n}\n\n/// Bindings around `datetime.date`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyDate>`][crate::Py] or [`Bound<'py, PyDate>`][Bound].\n#[repr(transparent)]\npub struct PyDate(PyAny);\n\n#[cfg(not(Py_LIMITED_API))]\npyobject_native_type!(\n    PyDate,\n    crate::ffi::PyDateTime_Date,\n    |py| expect_datetime_api(py).DateType,\n    \"datetime\",\n    \"date\",\n    #module=Some(\"datetime\"),\n    #checkfunction=PyDate_Check\n);\n#[cfg(not(Py_LIMITED_API))]\npyobject_subclassable_native_type!(PyDate, crate::ffi::PyDateTime_Date);\n\n#[cfg(Py_LIMITED_API)]\npyobject_native_type_core!(\n    PyDate,\n    |py| {\n        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        TYPE.import(py, \"datetime\", \"date\").unwrap().as_type_ptr()\n    },\n    \"datetime\",\n    \"date\",\n    #module=Some(\"datetime\")\n);\n\nimpl PyDate {\n    /// Creates a new `datetime.date`.\n    pub fn new(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult<Bound<'_, PyDate>> {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            let api = ensure_datetime_api(py)?;\n            unsafe {\n                (api.Date_FromDate)(year, c_int::from(month), c_int::from(day), api.DateType)\n                    .assume_owned_or_err(py)\n                    .cast_into_unchecked()\n            }\n        }\n        #[cfg(Py_LIMITED_API)]\n        Ok(Self::type_object(py)\n            .call((year, month, day), None)?\n            .cast_into()?)\n    }\n\n    /// Construct a `datetime.date` from a POSIX timestamp\n    ///\n    /// This is equivalent to `datetime.date.fromtimestamp`\n    pub fn from_timestamp(py: Python<'_>, timestamp: f64) -> PyResult<Bound<'_, PyDate>> {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            let time_tuple = PyTuple::new(py, [timestamp])?;\n\n            // safety ensure that the API is loaded\n            let _api = ensure_datetime_api(py)?;\n\n            unsafe {\n                PyDate_FromTimestamp(time_tuple.as_ptr())\n                    .assume_owned_or_err(py)\n                    .cast_into_unchecked()\n            }\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        Ok(Self::type_object(py)\n            .call_method1(\"fromtimestamp\", (timestamp,))?\n            .cast_into()?)\n    }\n}\n\n#[cfg(not(Py_LIMITED_API))]\nimpl PyDateAccess for Bound<'_, PyDate> {\n    fn get_year(&self) -> i32 {\n        unsafe { PyDateTime_GET_YEAR(self.as_ptr()) }\n    }\n\n    fn get_month(&self) -> u8 {\n        unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u8 }\n    }\n\n    fn get_day(&self) -> u8 {\n        unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u8 }\n    }\n}\n\n/// Bindings for `datetime.datetime`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyDateTime>`][crate::Py] or [`Bound<'py, PyDateTime>`][Bound].\n#[repr(transparent)]\npub struct PyDateTime(PyAny);\n\n#[cfg(not(Py_LIMITED_API))]\npyobject_native_type!(\n    PyDateTime,\n    crate::ffi::PyDateTime_DateTime,\n    |py| expect_datetime_api(py).DateTimeType,\n    \"datetime\",\n    \"datetime\",\n    #module=Some(\"datetime\"),\n    #checkfunction=PyDateTime_Check\n);\n#[cfg(not(Py_LIMITED_API))]\npyobject_subclassable_native_type!(PyDateTime, crate::ffi::PyDateTime_DateTime);\n\n#[cfg(Py_LIMITED_API)]\npyobject_native_type_core!(\n    PyDateTime,\n    |py| {\n        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        TYPE.import(py, \"datetime\", \"datetime\")\n            .unwrap()\n            .as_type_ptr()\n    },\n    \"datetime\",\n    \"datetime\",\n    #module=Some(\"datetime\")\n);\n\nimpl PyDateTime {\n    /// Creates a new `datetime.datetime` object.\n    #[allow(clippy::too_many_arguments)]\n    pub fn new<'py>(\n        py: Python<'py>,\n        year: i32,\n        month: u8,\n        day: u8,\n        hour: u8,\n        minute: u8,\n        second: u8,\n        microsecond: u32,\n        tzinfo: Option<&Bound<'py, PyTzInfo>>,\n    ) -> PyResult<Bound<'py, PyDateTime>> {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            let api = ensure_datetime_api(py)?;\n            unsafe {\n                (api.DateTime_FromDateAndTime)(\n                    year,\n                    c_int::from(month),\n                    c_int::from(day),\n                    c_int::from(hour),\n                    c_int::from(minute),\n                    c_int::from(second),\n                    microsecond as c_int,\n                    opt_to_pyobj(tzinfo),\n                    api.DateTimeType,\n                )\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n            }\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        Ok(Self::type_object(py)\n            .call(\n                (year, month, day, hour, minute, second, microsecond, tzinfo),\n                None,\n            )?\n            .cast_into()?)\n    }\n\n    /// Alternate constructor that takes a `fold` parameter. A `true` value for this parameter\n    /// signifies this this datetime is the later of two moments with the same representation,\n    /// during a repeated interval.\n    ///\n    /// This typically occurs at the end of daylight savings time. Only valid if the\n    /// represented time is ambiguous.\n    /// See [PEP 495](https://www.python.org/dev/peps/pep-0495/) for more detail.\n    #[allow(clippy::too_many_arguments)]\n    pub fn new_with_fold<'py>(\n        py: Python<'py>,\n        year: i32,\n        month: u8,\n        day: u8,\n        hour: u8,\n        minute: u8,\n        second: u8,\n        microsecond: u32,\n        tzinfo: Option<&Bound<'py, PyTzInfo>>,\n        fold: bool,\n    ) -> PyResult<Bound<'py, PyDateTime>> {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            let api = ensure_datetime_api(py)?;\n            unsafe {\n                (api.DateTime_FromDateAndTimeAndFold)(\n                    year,\n                    c_int::from(month),\n                    c_int::from(day),\n                    c_int::from(hour),\n                    c_int::from(minute),\n                    c_int::from(second),\n                    microsecond as c_int,\n                    opt_to_pyobj(tzinfo),\n                    c_int::from(fold),\n                    api.DateTimeType,\n                )\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n            }\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        Ok(Self::type_object(py)\n            .call(\n                (year, month, day, hour, minute, second, microsecond, tzinfo),\n                Some(&[(\"fold\", fold)].into_py_dict(py)?),\n            )?\n            .cast_into()?)\n    }\n\n    /// Construct a `datetime` object from a POSIX timestamp\n    ///\n    /// This is equivalent to `datetime.datetime.fromtimestamp`\n    pub fn from_timestamp<'py>(\n        py: Python<'py>,\n        timestamp: f64,\n        tzinfo: Option<&Bound<'py, PyTzInfo>>,\n    ) -> PyResult<Bound<'py, PyDateTime>> {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            let args = (timestamp, tzinfo).into_pyobject(py)?;\n\n            // safety ensure API is loaded\n            let _api = ensure_datetime_api(py)?;\n\n            unsafe {\n                PyDateTime_FromTimestamp(args.as_ptr())\n                    .assume_owned_or_err(py)\n                    .cast_into_unchecked()\n            }\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        Ok(Self::type_object(py)\n            .call_method1(\"fromtimestamp\", (timestamp, tzinfo))?\n            .cast_into()?)\n    }\n}\n\n#[cfg(not(Py_LIMITED_API))]\nimpl PyDateAccess for Bound<'_, PyDateTime> {\n    fn get_year(&self) -> i32 {\n        unsafe { PyDateTime_GET_YEAR(self.as_ptr()) }\n    }\n\n    fn get_month(&self) -> u8 {\n        unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u8 }\n    }\n\n    fn get_day(&self) -> u8 {\n        unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u8 }\n    }\n}\n\n#[cfg(not(Py_LIMITED_API))]\nimpl PyTimeAccess for Bound<'_, PyDateTime> {\n    fn get_hour(&self) -> u8 {\n        unsafe { PyDateTime_DATE_GET_HOUR(self.as_ptr()) as u8 }\n    }\n\n    fn get_minute(&self) -> u8 {\n        unsafe { PyDateTime_DATE_GET_MINUTE(self.as_ptr()) as u8 }\n    }\n\n    fn get_second(&self) -> u8 {\n        unsafe { PyDateTime_DATE_GET_SECOND(self.as_ptr()) as u8 }\n    }\n\n    fn get_microsecond(&self) -> u32 {\n        unsafe { PyDateTime_DATE_GET_MICROSECOND(self.as_ptr()) as u32 }\n    }\n\n    fn get_fold(&self) -> bool {\n        unsafe { PyDateTime_DATE_GET_FOLD(self.as_ptr()) > 0 }\n    }\n}\n\nimpl<'py> PyTzInfoAccess<'py> for Bound<'py, PyDateTime> {\n    fn get_tzinfo(&self) -> Option<Bound<'py, PyTzInfo>> {\n        #[cfg(all(not(Py_3_10), not(Py_LIMITED_API)))]\n        unsafe {\n            let ptr = self.as_ptr() as *mut ffi::PyDateTime_DateTime;\n            if (*ptr).hastzinfo != 0 {\n                Some(\n                    (*ptr)\n                        .tzinfo\n                        .assume_borrowed(self.py())\n                        .to_owned()\n                        .cast_into_unchecked(),\n                )\n            } else {\n                None\n            }\n        }\n\n        #[cfg(all(Py_3_10, not(Py_LIMITED_API)))]\n        unsafe {\n            let res = PyDateTime_DATE_GET_TZINFO(self.as_ptr());\n            if Py_IsNone(res) == 1 {\n                None\n            } else {\n                Some(\n                    res.assume_borrowed(self.py())\n                        .to_owned()\n                        .cast_into_unchecked(),\n                )\n            }\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        unsafe {\n            let tzinfo = self.getattr(intern!(self.py(), \"tzinfo\")).ok()?;\n            if tzinfo.is_none() {\n                None\n            } else {\n                Some(tzinfo.cast_into_unchecked())\n            }\n        }\n    }\n}\n\n/// Bindings for `datetime.time`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyTime>`][crate::Py] or [`Bound<'py, PyTime>`][Bound].\n#[repr(transparent)]\npub struct PyTime(PyAny);\n\n#[cfg(not(Py_LIMITED_API))]\npyobject_native_type!(\n    PyTime,\n    crate::ffi::PyDateTime_Time,\n    |py| expect_datetime_api(py).TimeType,\n    \"datetime\",\n    \"time\",\n    #module=Some(\"datetime\"),\n    #checkfunction=PyTime_Check\n);\n#[cfg(not(Py_LIMITED_API))]\npyobject_subclassable_native_type!(PyTime, crate::ffi::PyDateTime_Time);\n\n#[cfg(Py_LIMITED_API)]\npyobject_native_type_core!(\n    PyTime,\n    |py| {\n        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        TYPE.import(py, \"datetime\", \"time\").unwrap().as_type_ptr()\n    },\n    \"datetime\",\n    \"time\",\n    #module=Some(\"datetime\")\n);\n\nimpl PyTime {\n    /// Creates a new `datetime.time` object.\n    pub fn new<'py>(\n        py: Python<'py>,\n        hour: u8,\n        minute: u8,\n        second: u8,\n        microsecond: u32,\n        tzinfo: Option<&Bound<'py, PyTzInfo>>,\n    ) -> PyResult<Bound<'py, PyTime>> {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            let api = ensure_datetime_api(py)?;\n            unsafe {\n                (api.Time_FromTime)(\n                    c_int::from(hour),\n                    c_int::from(minute),\n                    c_int::from(second),\n                    microsecond as c_int,\n                    opt_to_pyobj(tzinfo),\n                    api.TimeType,\n                )\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n            }\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        Ok(Self::type_object(py)\n            .call((hour, minute, second, microsecond, tzinfo), None)?\n            .cast_into()?)\n    }\n\n    /// Alternate constructor that takes a `fold` argument. See [`PyDateTime::new_with_fold`].\n    pub fn new_with_fold<'py>(\n        py: Python<'py>,\n        hour: u8,\n        minute: u8,\n        second: u8,\n        microsecond: u32,\n        tzinfo: Option<&Bound<'py, PyTzInfo>>,\n        fold: bool,\n    ) -> PyResult<Bound<'py, PyTime>> {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            let api = ensure_datetime_api(py)?;\n            unsafe {\n                (api.Time_FromTimeAndFold)(\n                    c_int::from(hour),\n                    c_int::from(minute),\n                    c_int::from(second),\n                    microsecond as c_int,\n                    opt_to_pyobj(tzinfo),\n                    fold as c_int,\n                    api.TimeType,\n                )\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n            }\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        Ok(Self::type_object(py)\n            .call(\n                (hour, minute, second, microsecond, tzinfo),\n                Some(&[(\"fold\", fold)].into_py_dict(py)?),\n            )?\n            .cast_into()?)\n    }\n}\n\n#[cfg(not(Py_LIMITED_API))]\nimpl PyTimeAccess for Bound<'_, PyTime> {\n    fn get_hour(&self) -> u8 {\n        unsafe { PyDateTime_TIME_GET_HOUR(self.as_ptr()) as u8 }\n    }\n\n    fn get_minute(&self) -> u8 {\n        unsafe { PyDateTime_TIME_GET_MINUTE(self.as_ptr()) as u8 }\n    }\n\n    fn get_second(&self) -> u8 {\n        unsafe { PyDateTime_TIME_GET_SECOND(self.as_ptr()) as u8 }\n    }\n\n    fn get_microsecond(&self) -> u32 {\n        unsafe { PyDateTime_TIME_GET_MICROSECOND(self.as_ptr()) as u32 }\n    }\n\n    fn get_fold(&self) -> bool {\n        unsafe { PyDateTime_TIME_GET_FOLD(self.as_ptr()) != 0 }\n    }\n}\n\nimpl<'py> PyTzInfoAccess<'py> for Bound<'py, PyTime> {\n    fn get_tzinfo(&self) -> Option<Bound<'py, PyTzInfo>> {\n        #[cfg(all(not(Py_3_10), not(Py_LIMITED_API)))]\n        unsafe {\n            let ptr = self.as_ptr() as *mut ffi::PyDateTime_Time;\n            if (*ptr).hastzinfo != 0 {\n                Some(\n                    (*ptr)\n                        .tzinfo\n                        .assume_borrowed(self.py())\n                        .to_owned()\n                        .cast_into_unchecked(),\n                )\n            } else {\n                None\n            }\n        }\n\n        #[cfg(all(Py_3_10, not(Py_LIMITED_API)))]\n        unsafe {\n            let res = PyDateTime_TIME_GET_TZINFO(self.as_ptr());\n            if Py_IsNone(res) == 1 {\n                None\n            } else {\n                Some(\n                    res.assume_borrowed(self.py())\n                        .to_owned()\n                        .cast_into_unchecked(),\n                )\n            }\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        unsafe {\n            let tzinfo = self.getattr(intern!(self.py(), \"tzinfo\")).ok()?;\n            if tzinfo.is_none() {\n                None\n            } else {\n                Some(tzinfo.cast_into_unchecked())\n            }\n        }\n    }\n}\n\n/// Bindings for `datetime.tzinfo`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyTzInfo>`][crate::Py] or [`Bound<'py, PyTzInfo>`][Bound].\n///\n/// This is an abstract base class, the primary implementations are\n/// [`datetime.timezone`](https://docs.python.org/3/library/datetime.html#timezone-objects)\n/// and the [`zoneinfo` module](https://docs.python.org/3/library/zoneinfo.html).\n///\n/// The constructors [`PyTzInfo::utc`], [`PyTzInfo::fixed_offset`] and [`PyTzInfo::timezone`]\n/// create these concrete subclasses.\n#[repr(transparent)]\npub struct PyTzInfo(PyAny);\n\n#[cfg(not(Py_LIMITED_API))]\npyobject_native_type!(\n    PyTzInfo,\n    crate::ffi::PyObject,\n    |py| expect_datetime_api(py).TZInfoType,\n    \"datetime\",\n    \"tzinfo\",\n    #module=Some(\"datetime\"),\n    #checkfunction=PyTZInfo_Check\n);\n#[cfg(not(Py_LIMITED_API))]\npyobject_subclassable_native_type!(PyTzInfo, crate::ffi::PyObject);\n\n#[cfg(Py_LIMITED_API)]\npyobject_native_type_core!(\n    PyTzInfo,\n    |py| {\n        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        TYPE.import(py, \"datetime\", \"tzinfo\").unwrap().as_type_ptr()\n    },\n    \"datetime\",\n    \"tzinfo\",\n    #module=Some(\"datetime\")\n);\n\nimpl PyTzInfo {\n    /// Equivalent to `datetime.timezone.utc`\n    pub fn utc(py: Python<'_>) -> PyResult<Borrowed<'static, '_, PyTzInfo>> {\n        #[cfg(not(Py_LIMITED_API))]\n        unsafe {\n            Ok(ensure_datetime_api(py)?\n                .TimeZone_UTC\n                .assume_borrowed(py)\n                .cast_unchecked())\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        {\n            static UTC: PyOnceLock<Py<PyTzInfo>> = PyOnceLock::new();\n            UTC.get_or_try_init(py, || {\n                Ok(py\n                    .import(\"datetime\")?\n                    .getattr(\"timezone\")?\n                    .getattr(\"utc\")?\n                    .cast_into()?\n                    .unbind())\n            })\n            .map(|utc| utc.bind_borrowed(py))\n        }\n    }\n\n    /// Equivalent to `zoneinfo.ZoneInfo` constructor\n    pub fn timezone<'py, T>(py: Python<'py>, iana_name: T) -> PyResult<Bound<'py, PyTzInfo>>\n    where\n        T: IntoPyObject<'py, Target = PyString>,\n    {\n        static ZONE_INFO: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n\n        let zoneinfo = ZONE_INFO.import(py, \"zoneinfo\", \"ZoneInfo\");\n\n        #[cfg(not(Py_3_9))]\n        let zoneinfo = zoneinfo\n            .or_else(|_| ZONE_INFO.import(py, \"backports.zoneinfo\", \"ZoneInfo\"))\n            .map_err(|_| PyImportError::new_err(\"Could not import \\\"backports.zoneinfo.ZoneInfo\\\". ZoneInfo is required when converting timezone-aware DateTime's. Please install \\\"backports.zoneinfo\\\" on python < 3.9\"));\n\n        zoneinfo?\n            .call1((iana_name,))?\n            .cast_into()\n            .map_err(Into::into)\n    }\n\n    /// Equivalent to `datetime.timezone` constructor\n    pub fn fixed_offset<'py, T>(py: Python<'py>, offset: T) -> PyResult<Bound<'py, PyTzInfo>>\n    where\n        T: IntoPyObject<'py, Target = PyDelta>,\n    {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            let api = ensure_datetime_api(py)?;\n            let delta = offset.into_pyobject(py).map_err(Into::into)?;\n            unsafe {\n                (api.TimeZone_FromTimeZone)(delta.as_ptr(), std::ptr::null_mut())\n                    .assume_owned_or_err(py)\n                    .cast_into_unchecked()\n            }\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        {\n            static TIMEZONE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n            Ok(TIMEZONE\n                .import(py, \"datetime\", \"timezone\")?\n                .call1((offset,))?\n                .cast_into()?)\n        }\n    }\n}\n\n/// Bindings for `datetime.timedelta`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyDelta>`][crate::Py] or [`Bound<'py, PyDelta>`][Bound].\n#[repr(transparent)]\npub struct PyDelta(PyAny);\n\n#[cfg(not(Py_LIMITED_API))]\npyobject_native_type!(\n    PyDelta,\n    crate::ffi::PyDateTime_Delta,\n    |py| expect_datetime_api(py).DeltaType,\n    \"datetime\",\n    \"timedelta\",\n    #module=Some(\"datetime\"),\n    #checkfunction=PyDelta_Check\n);\n#[cfg(not(Py_LIMITED_API))]\npyobject_subclassable_native_type!(PyDelta, crate::ffi::PyDateTime_Delta);\n\n#[cfg(Py_LIMITED_API)]\npyobject_native_type_core!(\n    PyDelta,\n    |py| {\n        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        TYPE.import(py, \"datetime\", \"timedelta\")\n            .unwrap()\n            .as_type_ptr()\n    },\n    \"datetime\",\n    \"timedelta\",\n    #module=Some(\"datetime\")\n);\n\nimpl PyDelta {\n    /// Creates a new `timedelta`.\n    pub fn new(\n        py: Python<'_>,\n        days: i32,\n        seconds: i32,\n        microseconds: i32,\n        normalize: bool,\n    ) -> PyResult<Bound<'_, PyDelta>> {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            let api = ensure_datetime_api(py)?;\n            unsafe {\n                (api.Delta_FromDelta)(\n                    days as c_int,\n                    seconds as c_int,\n                    microseconds as c_int,\n                    normalize as c_int,\n                    api.DeltaType,\n                )\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n            }\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        let _ = normalize;\n        #[cfg(Py_LIMITED_API)]\n        Ok(Self::type_object(py)\n            .call1((days, seconds, microseconds))?\n            .cast_into()?)\n    }\n}\n\n#[cfg(not(Py_LIMITED_API))]\nimpl PyDeltaAccess for Bound<'_, PyDelta> {\n    fn get_days(&self) -> i32 {\n        unsafe { PyDateTime_DELTA_GET_DAYS(self.as_ptr()) }\n    }\n\n    fn get_seconds(&self) -> i32 {\n        unsafe { PyDateTime_DELTA_GET_SECONDS(self.as_ptr()) }\n    }\n\n    fn get_microseconds(&self) -> i32 {\n        unsafe { PyDateTime_DELTA_GET_MICROSECONDS(self.as_ptr()) }\n    }\n}\n\n// Utility function which returns a borrowed reference to either\n// the underlying tzinfo or None.\n#[cfg(not(Py_LIMITED_API))]\nfn opt_to_pyobj(opt: Option<&Bound<'_, PyTzInfo>>) -> *mut ffi::PyObject {\n    match opt {\n        Some(tzi) => tzi.as_ptr(),\n        None => unsafe { ffi::Py_None() },\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    #[cfg(feature = \"macros\")]\n    use crate::py_run;\n\n    #[test]\n    #[cfg(feature = \"macros\")]\n    #[cfg_attr(target_arch = \"wasm32\", ignore)] // DateTime import fails on wasm for mysterious reasons\n    fn test_datetime_fromtimestamp() {\n        Python::attach(|py| {\n            let dt = PyDateTime::from_timestamp(py, 100.0, None).unwrap();\n            py_run!(\n                py,\n                dt,\n                \"import datetime; assert dt == datetime.datetime.fromtimestamp(100)\"\n            );\n\n            let utc = PyTzInfo::utc(py).unwrap();\n            let dt = PyDateTime::from_timestamp(py, 100.0, Some(&utc)).unwrap();\n            py_run!(\n                py,\n                dt,\n                \"import datetime; assert dt == datetime.datetime.fromtimestamp(100, datetime.timezone.utc)\"\n            );\n        })\n    }\n\n    #[test]\n    #[cfg(feature = \"macros\")]\n    #[cfg_attr(target_arch = \"wasm32\", ignore)] // DateTime import fails on wasm for mysterious reasons\n    fn test_date_fromtimestamp() {\n        Python::attach(|py| {\n            let dt = PyDate::from_timestamp(py, 100.).unwrap();\n            py_run!(\n                py,\n                dt,\n                \"import datetime; assert dt == datetime.date.fromtimestamp(100)\"\n            );\n        })\n    }\n\n    #[test]\n    #[cfg(not(Py_LIMITED_API))]\n    #[cfg_attr(target_arch = \"wasm32\", ignore)] // DateTime import fails on wasm for mysterious reasons\n    fn test_new_with_fold() {\n        Python::attach(|py| {\n            let a = PyDateTime::new_with_fold(py, 2021, 1, 23, 20, 32, 40, 341516, None, false);\n            let b = PyDateTime::new_with_fold(py, 2021, 1, 23, 20, 32, 40, 341516, None, true);\n\n            assert!(!a.unwrap().get_fold());\n            assert!(b.unwrap().get_fold());\n        });\n    }\n\n    #[test]\n    #[cfg_attr(target_arch = \"wasm32\", ignore)] // DateTime import fails on wasm for mysterious reasons\n    fn test_get_tzinfo() {\n        crate::Python::attach(|py| {\n            let utc = PyTzInfo::utc(py).unwrap();\n\n            let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap();\n\n            assert!(dt.get_tzinfo().unwrap().eq(utc).unwrap());\n\n            let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, None).unwrap();\n\n            assert!(dt.get_tzinfo().is_none());\n\n            let t = PyTime::new(py, 0, 0, 0, 0, Some(&utc)).unwrap();\n\n            assert!(t.get_tzinfo().unwrap().eq(utc).unwrap());\n\n            let t = PyTime::new(py, 0, 0, 0, 0, None).unwrap();\n\n            assert!(t.get_tzinfo().is_none());\n        });\n    }\n\n    #[test]\n    #[cfg(all(feature = \"macros\", feature = \"chrono\"))]\n    #[cfg_attr(target_arch = \"wasm32\", ignore)] // DateTime import fails on wasm for mysterious reasons\n    fn test_timezone_from_offset() {\n        use crate::types::PyNone;\n\n        Python::attach(|py| {\n            assert!(\n                PyTzInfo::fixed_offset(py, PyDelta::new(py, 0, -3600, 0, true).unwrap())\n                    .unwrap()\n                    .call_method1(\"utcoffset\", (PyNone::get(py),))\n                    .unwrap()\n                    .cast_into::<PyDelta>()\n                    .unwrap()\n                    .eq(PyDelta::new(py, 0, -3600, 0, true).unwrap())\n                    .unwrap()\n            );\n\n            assert!(\n                PyTzInfo::fixed_offset(py, PyDelta::new(py, 0, 3600, 0, true).unwrap())\n                    .unwrap()\n                    .call_method1(\"utcoffset\", (PyNone::get(py),))\n                    .unwrap()\n                    .cast_into::<PyDelta>()\n                    .unwrap()\n                    .eq(PyDelta::new(py, 0, 3600, 0, true).unwrap())\n                    .unwrap()\n            );\n\n            PyTzInfo::fixed_offset(py, PyDelta::new(py, 1, 0, 0, true).unwrap()).unwrap_err();\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/dict.rs",
    "content": "use crate::err::{self, PyErr, PyResult};\nuse crate::ffi::Py_ssize_t;\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::instance::{Borrowed, Bound};\nuse crate::py_result_ext::PyResultExt;\nuse crate::types::{PyAny, PyList, PyMapping};\nuse crate::{ffi, BoundObject, IntoPyObject, IntoPyObjectExt, Python};\n\n/// Represents a Python `dict`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyDict>`][crate::Py] or [`Bound<'py, PyDict>`][Bound].\n///\n/// For APIs available on `dict` objects, see the [`PyDictMethods`] trait which is implemented for\n/// [`Bound<'py, PyDict>`][Bound].\n#[repr(transparent)]\npub struct PyDict(PyAny);\n\n#[cfg(not(GraalPy))]\npyobject_subclassable_native_type!(PyDict, crate::ffi::PyDictObject);\n\npyobject_native_type!(\n    PyDict,\n    ffi::PyDictObject,\n    pyobject_native_static_type_object!(ffi::PyDict_Type),\n    \"builtins\",\n    \"dict\",\n    #checkfunction=ffi::PyDict_Check\n);\n\n/// Represents a Python `dict_keys`.\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(transparent)]\npub struct PyDictKeys(PyAny);\n\n#[cfg(not(any(PyPy, GraalPy)))]\npyobject_native_type_core!(\n    PyDictKeys,\n    pyobject_native_static_type_object!(ffi::PyDictKeys_Type),\n    \"builtins\",\n    \"dict_keys\",\n    #checkfunction=ffi::PyDictKeys_Check\n);\n\n/// Represents a Python `dict_values`.\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(transparent)]\npub struct PyDictValues(PyAny);\n\n#[cfg(not(any(PyPy, GraalPy)))]\npyobject_native_type_core!(\n    PyDictValues,\n    pyobject_native_static_type_object!(ffi::PyDictValues_Type),\n    \"builtins\",\n    \"dict_values\",\n    #checkfunction=ffi::PyDictValues_Check\n);\n\n/// Represents a Python `dict_items`.\n#[cfg(not(any(PyPy, GraalPy)))]\n#[repr(transparent)]\npub struct PyDictItems(PyAny);\n\n#[cfg(not(any(PyPy, GraalPy)))]\npyobject_native_type_core!(\n    PyDictItems,\n    pyobject_native_static_type_object!(ffi::PyDictItems_Type),\n    \"builtins\",\n    \"dict_items\",\n    #checkfunction=ffi::PyDictItems_Check\n);\n\nimpl PyDict {\n    /// Creates a new empty dictionary.\n    pub fn new(py: Python<'_>) -> Bound<'_, PyDict> {\n        unsafe { ffi::PyDict_New().assume_owned(py).cast_into_unchecked() }\n    }\n\n    /// Creates a new dictionary from the sequence given.\n    ///\n    /// The sequence must consist of `(PyObject, PyObject)`. This is\n    /// equivalent to `dict([(\"a\", 1), (\"b\", 2)])`.\n    ///\n    /// Returns an error on invalid input. In the case of key collisions,\n    /// this keeps the last entry seen.\n    #[cfg(not(any(PyPy, GraalPy)))]\n    pub fn from_sequence<'py>(seq: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyDict>> {\n        let py = seq.py();\n        let dict = Self::new(py);\n        err::error_on_minusone(py, unsafe {\n            ffi::PyDict_MergeFromSeq2(dict.as_ptr(), seq.as_ptr(), 1)\n        })?;\n        Ok(dict)\n    }\n}\n\n/// Implementation of functionality for [`PyDict`].\n///\n/// These methods are defined for the `Bound<'py, PyDict>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyDict\")]\npub trait PyDictMethods<'py>: crate::sealed::Sealed {\n    /// Returns a new dictionary that contains the same key-value pairs as self.\n    ///\n    /// This is equivalent to the Python expression `self.copy()`.\n    fn copy(&self) -> PyResult<Bound<'py, PyDict>>;\n\n    /// Empties an existing dictionary of all key-value pairs.\n    fn clear(&self);\n\n    /// Return the number of items in the dictionary.\n    ///\n    /// This is equivalent to the Python expression `len(self)`.\n    fn len(&self) -> usize;\n\n    /// Checks if the dict is empty, i.e. `len(self) == 0`.\n    fn is_empty(&self) -> bool;\n\n    /// Determines if the dictionary contains the specified key.\n    ///\n    /// This is equivalent to the Python expression `key in self`.\n    fn contains<K>(&self, key: K) -> PyResult<bool>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Gets an item from the dictionary.\n    ///\n    /// Returns `None` if the item is not present, or if an error occurs.\n    ///\n    /// To get a `KeyError` for non-existing keys, use `PyAny::get_item`.\n    fn get_item<K>(&self, key: K) -> PyResult<Option<Bound<'py, PyAny>>>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Sets an item value.\n    ///\n    /// This is equivalent to the Python statement `self[key] = value`.\n    fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>,\n        V: IntoPyObject<'py>;\n\n    /// Deletes an item.\n    ///\n    /// This is equivalent to the Python statement `del self[key]`.\n    fn del_item<K>(&self, key: K) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Returns a list of dict keys.\n    ///\n    /// This is equivalent to the Python expression `list(dict.keys())`.\n    fn keys(&self) -> Bound<'py, PyList>;\n\n    /// Returns a list of dict values.\n    ///\n    /// This is equivalent to the Python expression `list(dict.values())`.\n    fn values(&self) -> Bound<'py, PyList>;\n\n    /// Returns a list of dict items.\n    ///\n    /// This is equivalent to the Python expression `list(dict.items())`.\n    fn items(&self) -> Bound<'py, PyList>;\n\n    /// Returns an iterator of `(key, value)` pairs in this dictionary.\n    ///\n    /// # Panics\n    ///\n    /// If PyO3 detects that the dictionary is mutated during iteration, it will panic.\n    /// It is allowed to modify values as you iterate over the dictionary, but only\n    /// so long as the set of keys does not change.\n    fn iter(&self) -> BoundDictIterator<'py>;\n\n    /// Iterates over the contents of this dictionary while holding a critical section on the dict.\n    /// This is useful when the GIL is disabled and the dictionary is shared between threads.\n    /// It is not guaranteed that the dictionary will not be modified during iteration when the\n    /// closure calls arbitrary Python code that releases the critical section held by the\n    /// iterator. Otherwise, the dictionary will not be modified during iteration.\n    ///\n    /// This method is a small performance optimization over `.iter().try_for_each()` when the\n    /// nightly feature is not enabled because we cannot implement an optimised version of\n    /// `iter().try_fold()` on stable yet. If your iteration is infallible then this method has the\n    /// same performance as `.iter().for_each()`.\n    fn locked_for_each<F>(&self, closure: F) -> PyResult<()>\n    where\n        F: Fn(Bound<'py, PyAny>, Bound<'py, PyAny>) -> PyResult<()>;\n\n    /// Returns `self` cast as a `PyMapping`.\n    fn as_mapping(&self) -> &Bound<'py, PyMapping>;\n\n    /// Returns `self` cast as a `PyMapping`.\n    fn into_mapping(self) -> Bound<'py, PyMapping>;\n\n    /// Update this dictionary with the key/value pairs from another.\n    ///\n    /// This is equivalent to the Python expression `self.update(other)`. If `other` is a `PyDict`, you may want\n    /// to use `self.update(other.as_mapping())`, note: `PyDict::as_mapping` is a zero-cost conversion.\n    fn update(&self, other: &Bound<'_, PyMapping>) -> PyResult<()>;\n\n    /// Add key/value pairs from another dictionary to this one only when they do not exist in this.\n    ///\n    /// This is equivalent to the Python expression `self.update({k: v for k, v in other.items() if k not in self})`.\n    /// If `other` is a `PyDict`, you may want to use `self.update_if_missing(other.as_mapping())`,\n    /// note: `PyDict::as_mapping` is a zero-cost conversion.\n    ///\n    /// This method uses [`PyDict_Merge`](https://docs.python.org/3/c-api/dict.html#c.PyDict_Merge) internally,\n    /// so should have the same performance as `update`.\n    fn update_if_missing(&self, other: &Bound<'_, PyMapping>) -> PyResult<()>;\n}\n\nimpl<'py> PyDictMethods<'py> for Bound<'py, PyDict> {\n    fn copy(&self) -> PyResult<Bound<'py, PyDict>> {\n        unsafe {\n            ffi::PyDict_Copy(self.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    fn clear(&self) {\n        unsafe { ffi::PyDict_Clear(self.as_ptr()) }\n    }\n\n    fn len(&self) -> usize {\n        dict_len(self) as usize\n    }\n\n    fn is_empty(&self) -> bool {\n        self.len() == 0\n    }\n\n    fn contains<K>(&self, key: K) -> PyResult<bool>\n    where\n        K: IntoPyObject<'py>,\n    {\n        fn inner(dict: &Bound<'_, PyDict>, key: Borrowed<'_, '_, PyAny>) -> PyResult<bool> {\n            match unsafe { ffi::PyDict_Contains(dict.as_ptr(), key.as_ptr()) } {\n                1 => Ok(true),\n                0 => Ok(false),\n                _ => Err(PyErr::fetch(dict.py())),\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn get_item<K>(&self, key: K) -> PyResult<Option<Bound<'py, PyAny>>>\n    where\n        K: IntoPyObject<'py>,\n    {\n        fn inner<'py>(\n            dict: &Bound<'py, PyDict>,\n            key: Borrowed<'_, '_, PyAny>,\n        ) -> PyResult<Option<Bound<'py, PyAny>>> {\n            let py = dict.py();\n            let mut result: *mut ffi::PyObject = std::ptr::null_mut();\n            match unsafe {\n                ffi::compat::PyDict_GetItemRef(dict.as_ptr(), key.as_ptr(), &mut result)\n            } {\n                std::ffi::c_int::MIN..=-1 => Err(PyErr::fetch(py)),\n                0 => Ok(None),\n                1..=std::ffi::c_int::MAX => {\n                    // Safety: PyDict_GetItemRef positive return value means the result is a valid\n                    // owned reference\n                    Ok(Some(unsafe { result.assume_owned_unchecked(py) }))\n                }\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>,\n        V: IntoPyObject<'py>,\n    {\n        fn inner(\n            dict: &Bound<'_, PyDict>,\n            key: Borrowed<'_, '_, PyAny>,\n            value: Borrowed<'_, '_, PyAny>,\n        ) -> PyResult<()> {\n            err::error_on_minusone(dict.py(), unsafe {\n                ffi::PyDict_SetItem(dict.as_ptr(), key.as_ptr(), value.as_ptr())\n            })\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n            value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn del_item<K>(&self, key: K) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>,\n    {\n        fn inner(dict: &Bound<'_, PyDict>, key: Borrowed<'_, '_, PyAny>) -> PyResult<()> {\n            err::error_on_minusone(dict.py(), unsafe {\n                ffi::PyDict_DelItem(dict.as_ptr(), key.as_ptr())\n            })\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn keys(&self) -> Bound<'py, PyList> {\n        unsafe {\n            ffi::PyDict_Keys(self.as_ptr())\n                .assume_owned(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    fn values(&self) -> Bound<'py, PyList> {\n        unsafe {\n            ffi::PyDict_Values(self.as_ptr())\n                .assume_owned(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    fn items(&self) -> Bound<'py, PyList> {\n        unsafe {\n            ffi::PyDict_Items(self.as_ptr())\n                .assume_owned(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    fn iter(&self) -> BoundDictIterator<'py> {\n        BoundDictIterator::new(self.clone())\n    }\n\n    fn locked_for_each<F>(&self, f: F) -> PyResult<()>\n    where\n        F: Fn(Bound<'py, PyAny>, Bound<'py, PyAny>) -> PyResult<()>,\n    {\n        #[cfg(feature = \"nightly\")]\n        {\n            // We don't need a critical section when the nightly feature is enabled because\n            // try_for_each is locked by the implementation of try_fold.\n            self.iter().try_for_each(|(key, value)| f(key, value))\n        }\n\n        #[cfg(not(feature = \"nightly\"))]\n        {\n            crate::sync::critical_section::with_critical_section(self, || {\n                self.iter().try_for_each(|(key, value)| f(key, value))\n            })\n        }\n    }\n\n    fn as_mapping(&self) -> &Bound<'py, PyMapping> {\n        unsafe { self.cast_unchecked() }\n    }\n\n    fn into_mapping(self) -> Bound<'py, PyMapping> {\n        unsafe { self.cast_into_unchecked() }\n    }\n\n    fn update(&self, other: &Bound<'_, PyMapping>) -> PyResult<()> {\n        err::error_on_minusone(self.py(), unsafe {\n            ffi::PyDict_Update(self.as_ptr(), other.as_ptr())\n        })\n    }\n\n    fn update_if_missing(&self, other: &Bound<'_, PyMapping>) -> PyResult<()> {\n        err::error_on_minusone(self.py(), unsafe {\n            ffi::PyDict_Merge(self.as_ptr(), other.as_ptr(), 0)\n        })\n    }\n}\n\nimpl<'a, 'py> Borrowed<'a, 'py, PyDict> {\n    /// Iterates over the contents of this dictionary without incrementing reference counts.\n    ///\n    /// # Safety\n    /// It must be known that this dictionary will not be modified during iteration,\n    /// for example, when parsing arguments in a keyword arguments dictionary.\n    pub(crate) unsafe fn iter_borrowed(self) -> BorrowedDictIter<'a, 'py> {\n        BorrowedDictIter::new(self)\n    }\n}\n\nfn dict_len(dict: &Bound<'_, PyDict>) -> Py_ssize_t {\n    #[cfg(any(not(Py_3_8), PyPy, GraalPy, Py_LIMITED_API, Py_GIL_DISABLED))]\n    unsafe {\n        ffi::PyDict_Size(dict.as_ptr())\n    }\n\n    #[cfg(all(\n        Py_3_8,\n        not(PyPy),\n        not(GraalPy),\n        not(Py_LIMITED_API),\n        not(Py_GIL_DISABLED)\n    ))]\n    unsafe {\n        (*dict.as_ptr().cast::<ffi::PyDictObject>()).ma_used\n    }\n}\n\n/// PyO3 implementation of an iterator for a Python `dict` object.\npub struct BoundDictIterator<'py> {\n    dict: Bound<'py, PyDict>,\n    inner: DictIterImpl,\n}\n\nenum DictIterImpl {\n    DictIter {\n        ppos: ffi::Py_ssize_t,\n        di_used: ffi::Py_ssize_t,\n        remaining: ffi::Py_ssize_t,\n    },\n}\n\nimpl DictIterImpl {\n    #[deny(unsafe_op_in_unsafe_fn)]\n    #[inline]\n    /// Safety: the dict should be locked with a critical section on the free-threaded build\n    /// and otherwise not shared between threads in code that releases the GIL.\n    unsafe fn next_unchecked<'py>(\n        &mut self,\n        dict: &Bound<'py, PyDict>,\n    ) -> Option<(Bound<'py, PyAny>, Bound<'py, PyAny>)> {\n        match self {\n            Self::DictIter {\n                di_used,\n                remaining,\n                ppos,\n                ..\n            } => {\n                let ma_used = dict_len(dict);\n\n                // These checks are similar to what CPython does.\n                //\n                // If the dimension of the dict changes e.g. key-value pairs are removed\n                // or added during iteration, this will panic next time when `next` is called\n                if *di_used != ma_used {\n                    *di_used = -1;\n                    panic!(\"dictionary changed size during iteration\");\n                };\n\n                // If the dict is changed in such a way that the length remains constant\n                // then this will panic at the end of iteration - similar to this:\n                //\n                // d = {\"a\":1, \"b\":2, \"c\": 3}\n                //\n                // for k, v in d.items():\n                //     d[f\"{k}_\"] = 4\n                //     del d[k]\n                //     print(k)\n                //\n                if *remaining == -1 {\n                    *di_used = -1;\n                    panic!(\"dictionary keys changed during iteration\");\n                };\n\n                let mut key: *mut ffi::PyObject = std::ptr::null_mut();\n                let mut value: *mut ffi::PyObject = std::ptr::null_mut();\n\n                if unsafe { ffi::PyDict_Next(dict.as_ptr(), ppos, &mut key, &mut value) != 0 } {\n                    *remaining -= 1;\n                    let py = dict.py();\n                    // Safety:\n                    // - PyDict_Next returns borrowed values\n                    // - we have already checked that `PyDict_Next` succeeded, so we can assume these to be non-null\n                    Some((\n                        unsafe { key.assume_borrowed_unchecked(py).to_owned() },\n                        unsafe { value.assume_borrowed_unchecked(py).to_owned() },\n                    ))\n                } else {\n                    None\n                }\n            }\n        }\n    }\n\n    #[cfg(Py_GIL_DISABLED)]\n    #[inline]\n    fn with_critical_section<F, R>(&mut self, dict: &Bound<'_, PyDict>, f: F) -> R\n    where\n        F: FnOnce(&mut Self) -> R,\n    {\n        match self {\n            Self::DictIter { .. } => {\n                crate::sync::critical_section::with_critical_section(dict, || f(self))\n            }\n        }\n    }\n}\n\nimpl<'py> Iterator for BoundDictIterator<'py> {\n    type Item = (Bound<'py, PyAny>, Bound<'py, PyAny>);\n\n    #[inline]\n    fn next(&mut self) -> Option<Self::Item> {\n        #[cfg(Py_GIL_DISABLED)]\n        {\n            self.inner\n                .with_critical_section(&self.dict, |inner| unsafe {\n                    inner.next_unchecked(&self.dict)\n                })\n        }\n        #[cfg(not(Py_GIL_DISABLED))]\n        {\n            unsafe { self.inner.next_unchecked(&self.dict) }\n        }\n    }\n\n    #[inline]\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let len = self.len();\n        (len, Some(len))\n    }\n\n    #[inline]\n    fn count(self) -> usize\n    where\n        Self: Sized,\n    {\n        self.len()\n    }\n\n    #[inline]\n    #[cfg(Py_GIL_DISABLED)]\n    fn fold<B, F>(mut self, init: B, mut f: F) -> B\n    where\n        Self: Sized,\n        F: FnMut(B, Self::Item) -> B,\n    {\n        self.inner.with_critical_section(&self.dict, |inner| {\n            let mut accum = init;\n            while let Some(x) = unsafe { inner.next_unchecked(&self.dict) } {\n                accum = f(accum, x);\n            }\n            accum\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, feature = \"nightly\"))]\n    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R\n    where\n        Self: Sized,\n        F: FnMut(B, Self::Item) -> R,\n        R: std::ops::Try<Output = B>,\n    {\n        self.inner.with_critical_section(&self.dict, |inner| {\n            let mut accum = init;\n            while let Some(x) = unsafe { inner.next_unchecked(&self.dict) } {\n                accum = f(accum, x)?\n            }\n            R::from_output(accum)\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn all<F>(&mut self, mut f: F) -> bool\n    where\n        Self: Sized,\n        F: FnMut(Self::Item) -> bool,\n    {\n        self.inner.with_critical_section(&self.dict, |inner| {\n            while let Some(x) = unsafe { inner.next_unchecked(&self.dict) } {\n                if !f(x) {\n                    return false;\n                }\n            }\n            true\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn any<F>(&mut self, mut f: F) -> bool\n    where\n        Self: Sized,\n        F: FnMut(Self::Item) -> bool,\n    {\n        self.inner.with_critical_section(&self.dict, |inner| {\n            while let Some(x) = unsafe { inner.next_unchecked(&self.dict) } {\n                if f(x) {\n                    return true;\n                }\n            }\n            false\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>\n    where\n        Self: Sized,\n        P: FnMut(&Self::Item) -> bool,\n    {\n        self.inner.with_critical_section(&self.dict, |inner| {\n            while let Some(x) = unsafe { inner.next_unchecked(&self.dict) } {\n                if predicate(&x) {\n                    return Some(x);\n                }\n            }\n            None\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn find_map<B, F>(&mut self, mut f: F) -> Option<B>\n    where\n        Self: Sized,\n        F: FnMut(Self::Item) -> Option<B>,\n    {\n        self.inner.with_critical_section(&self.dict, |inner| {\n            while let Some(x) = unsafe { inner.next_unchecked(&self.dict) } {\n                if let found @ Some(_) = f(x) {\n                    return found;\n                }\n            }\n            None\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn position<P>(&mut self, mut predicate: P) -> Option<usize>\n    where\n        Self: Sized,\n        P: FnMut(Self::Item) -> bool,\n    {\n        self.inner.with_critical_section(&self.dict, |inner| {\n            let mut acc = 0;\n            while let Some(x) = unsafe { inner.next_unchecked(&self.dict) } {\n                if predicate(x) {\n                    return Some(acc);\n                }\n                acc += 1;\n            }\n            None\n        })\n    }\n}\n\nimpl ExactSizeIterator for BoundDictIterator<'_> {\n    fn len(&self) -> usize {\n        match self.inner {\n            DictIterImpl::DictIter { remaining, .. } => remaining as usize,\n        }\n    }\n}\n\nimpl<'py> BoundDictIterator<'py> {\n    fn new(dict: Bound<'py, PyDict>) -> Self {\n        let remaining = dict_len(&dict);\n\n        Self {\n            dict,\n            inner: DictIterImpl::DictIter {\n                ppos: 0,\n                di_used: remaining,\n                remaining,\n            },\n        }\n    }\n}\n\nimpl<'py> IntoIterator for Bound<'py, PyDict> {\n    type Item = (Bound<'py, PyAny>, Bound<'py, PyAny>);\n    type IntoIter = BoundDictIterator<'py>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        BoundDictIterator::new(self)\n    }\n}\n\nimpl<'py> IntoIterator for &Bound<'py, PyDict> {\n    type Item = (Bound<'py, PyAny>, Bound<'py, PyAny>);\n    type IntoIter = BoundDictIterator<'py>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.iter()\n    }\n}\n\nmod borrowed_iter {\n    use super::*;\n\n    /// Variant of the above which is used to iterate the items of the dictionary\n    /// without incrementing reference counts. This is only safe if it's known\n    /// that the dictionary will not be modified during iteration.\n    pub struct BorrowedDictIter<'a, 'py> {\n        dict: Borrowed<'a, 'py, PyDict>,\n        ppos: ffi::Py_ssize_t,\n        len: ffi::Py_ssize_t,\n    }\n\n    impl<'a, 'py> Iterator for BorrowedDictIter<'a, 'py> {\n        type Item = (Borrowed<'a, 'py, PyAny>, Borrowed<'a, 'py, PyAny>);\n\n        #[inline]\n        fn next(&mut self) -> Option<Self::Item> {\n            let mut key: *mut ffi::PyObject = std::ptr::null_mut();\n            let mut value: *mut ffi::PyObject = std::ptr::null_mut();\n\n            // Safety: self.dict lives sufficiently long that the pointer is not dangling\n            if unsafe { ffi::PyDict_Next(self.dict.as_ptr(), &mut self.ppos, &mut key, &mut value) }\n                != 0\n            {\n                let py = self.dict.py();\n                self.len -= 1;\n                // Safety:\n                // - PyDict_Next returns borrowed values\n                // - we have already checked that `PyDict_Next` succeeded, so we can assume these to be non-null\n                Some(unsafe {\n                    (\n                        key.assume_borrowed_unchecked(py),\n                        value.assume_borrowed_unchecked(py),\n                    )\n                })\n            } else {\n                None\n            }\n        }\n\n        #[inline]\n        fn size_hint(&self) -> (usize, Option<usize>) {\n            let len = self.len();\n            (len, Some(len))\n        }\n\n        #[inline]\n        fn count(self) -> usize\n        where\n            Self: Sized,\n        {\n            self.len()\n        }\n    }\n\n    impl ExactSizeIterator for BorrowedDictIter<'_, '_> {\n        fn len(&self) -> usize {\n            self.len as usize\n        }\n    }\n\n    impl<'a, 'py> BorrowedDictIter<'a, 'py> {\n        pub(super) fn new(dict: Borrowed<'a, 'py, PyDict>) -> Self {\n            let len = dict_len(&dict);\n            BorrowedDictIter { dict, ppos: 0, len }\n        }\n    }\n}\n\npub(crate) use borrowed_iter::BorrowedDictIter;\n\n/// Conversion trait that allows a sequence of tuples to be converted into `PyDict`\n/// Primary use case for this trait is `call` and `call_method` methods as keywords argument.\npub trait IntoPyDict<'py>: Sized {\n    /// Converts self into a `PyDict` object pointer. Whether pointer owned or borrowed\n    /// depends on implementation.\n    fn into_py_dict(self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>>;\n}\n\nimpl<'py, T, I> IntoPyDict<'py> for I\nwhere\n    T: PyDictItem<'py>,\n    I: IntoIterator<Item = T>,\n{\n    fn into_py_dict(self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {\n        let dict = PyDict::new(py);\n        self.into_iter().try_for_each(|item| {\n            let (key, value) = item.unpack();\n            dict.set_item(key, value)\n        })?;\n        Ok(dict)\n    }\n}\n\n/// Represents a tuple which can be used as a PyDict item.\ntrait PyDictItem<'py> {\n    type K: IntoPyObject<'py>;\n    type V: IntoPyObject<'py>;\n    fn unpack(self) -> (Self::K, Self::V);\n}\n\nimpl<'py, K, V> PyDictItem<'py> for (K, V)\nwhere\n    K: IntoPyObject<'py>,\n    V: IntoPyObject<'py>,\n{\n    type K = K;\n    type V = V;\n\n    fn unpack(self) -> (Self::K, Self::V) {\n        (self.0, self.1)\n    }\n}\n\nimpl<'a, 'py, K, V> PyDictItem<'py> for &'a (K, V)\nwhere\n    &'a K: IntoPyObject<'py>,\n    &'a V: IntoPyObject<'py>,\n{\n    type K = &'a K;\n    type V = &'a V;\n\n    fn unpack(self) -> (Self::K, Self::V) {\n        (&self.0, &self.1)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::{PyAnyMethods as _, PyTuple};\n    use std::collections::{BTreeMap, HashMap};\n\n    #[test]\n    fn test_new() {\n        Python::attach(|py| {\n            let dict = [(7, 32)].into_py_dict(py).unwrap();\n            assert_eq!(\n                32,\n                dict.get_item(7i32)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n            );\n            assert!(dict.get_item(8i32).unwrap().is_none());\n            let map: HashMap<i32, i32> = [(7, 32)].iter().cloned().collect();\n            assert_eq!(map, dict.extract().unwrap());\n            let map: BTreeMap<i32, i32> = [(7, 32)].iter().cloned().collect();\n            assert_eq!(map, dict.extract().unwrap());\n        });\n    }\n\n    #[test]\n    #[cfg(not(any(PyPy, GraalPy)))]\n    fn test_from_sequence() {\n        Python::attach(|py| {\n            let items = PyList::new(py, vec![(\"a\", 1), (\"b\", 2)]).unwrap();\n            let dict = PyDict::from_sequence(&items).unwrap();\n            assert_eq!(\n                1,\n                dict.get_item(\"a\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n            );\n            assert_eq!(\n                2,\n                dict.get_item(\"b\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n            );\n            let map: HashMap<String, i32> =\n                [(\"a\".into(), 1), (\"b\".into(), 2)].into_iter().collect();\n            assert_eq!(map, dict.extract().unwrap());\n            let map: BTreeMap<String, i32> =\n                [(\"a\".into(), 1), (\"b\".into(), 2)].into_iter().collect();\n            assert_eq!(map, dict.extract().unwrap());\n        });\n    }\n\n    #[test]\n    #[cfg(not(any(PyPy, GraalPy)))]\n    fn test_from_sequence_err() {\n        Python::attach(|py| {\n            let items = PyList::new(py, vec![\"a\", \"b\"]).unwrap();\n            assert!(PyDict::from_sequence(&items).is_err());\n        });\n    }\n\n    #[test]\n    fn test_copy() {\n        Python::attach(|py| {\n            let dict = [(7, 32)].into_py_dict(py).unwrap();\n\n            let ndict = dict.copy().unwrap();\n            assert_eq!(\n                32,\n                ndict\n                    .get_item(7i32)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n            );\n            assert!(ndict.get_item(8i32).unwrap().is_none());\n        });\n    }\n\n    #[test]\n    fn test_len() {\n        Python::attach(|py| {\n            let mut v = HashMap::<i32, i32>::new();\n            let dict = (&v).into_pyobject(py).unwrap();\n            assert_eq!(0, dict.len());\n            v.insert(7, 32);\n            let dict2 = v.into_pyobject(py).unwrap();\n            assert_eq!(1, dict2.len());\n        });\n    }\n\n    #[test]\n    fn test_contains() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            let dict = v.into_pyobject(py).unwrap();\n            assert!(dict.contains(7i32).unwrap());\n            assert!(!dict.contains(8i32).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_get_item() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            let dict = v.into_pyobject(py).unwrap();\n            assert_eq!(\n                32,\n                dict.get_item(7i32)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n            );\n            assert!(dict.get_item(8i32).unwrap().is_none());\n        });\n    }\n\n    #[cfg(feature = \"macros\")]\n    #[test]\n    fn test_get_item_error_path() {\n        use crate::exceptions::PyTypeError;\n\n        #[crate::pyclass(crate = \"crate\")]\n        struct HashErrors;\n\n        #[crate::pymethods(crate = \"crate\")]\n        impl HashErrors {\n            #[new]\n            fn new() -> Self {\n                HashErrors {}\n            }\n\n            fn __hash__(&self) -> PyResult<isize> {\n                Err(PyTypeError::new_err(\"Error from __hash__\"))\n            }\n        }\n\n        Python::attach(|py| {\n            let class = py.get_type::<HashErrors>();\n            let instance = class.call0().unwrap();\n            let d = PyDict::new(py);\n            match d.get_item(instance) {\n                Ok(_) => {\n                    panic!(\"this get_item call should always error\")\n                }\n                Err(err) => {\n                    assert!(err.is_instance_of::<PyTypeError>(py));\n                    assert!(err.value(py).to_string().contains(\"Error from __hash__\"));\n                }\n            }\n        })\n    }\n\n    #[test]\n    fn test_set_item() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            let dict = v.into_pyobject(py).unwrap();\n            assert!(dict.set_item(7i32, 42i32).is_ok()); // change\n            assert!(dict.set_item(8i32, 123i32).is_ok()); // insert\n            assert_eq!(\n                42i32,\n                dict.get_item(7i32)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n            );\n            assert_eq!(\n                123i32,\n                dict.get_item(8i32)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n            );\n        });\n    }\n\n    #[test]\n    fn test_set_item_refcnt() {\n        Python::attach(|py| {\n            let cnt;\n            let obj = py.eval(c\"object()\", None, None).unwrap();\n            {\n                cnt = obj._get_refcnt();\n                let _dict = [(10, &obj)].into_py_dict(py);\n            }\n            {\n                assert_eq!(cnt, obj._get_refcnt());\n            }\n        });\n    }\n\n    #[test]\n    fn test_set_item_does_not_update_original_object() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            let dict = (&v).into_pyobject(py).unwrap();\n            assert!(dict.set_item(7i32, 42i32).is_ok()); // change\n            assert!(dict.set_item(8i32, 123i32).is_ok()); // insert\n            assert_eq!(32i32, v[&7i32]); // not updated!\n            assert_eq!(None, v.get(&8i32));\n        });\n    }\n\n    #[test]\n    fn test_del_item() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            let dict = v.into_pyobject(py).unwrap();\n            assert!(dict.del_item(7i32).is_ok());\n            assert_eq!(0, dict.len());\n            assert!(dict.get_item(7i32).unwrap().is_none());\n        });\n    }\n\n    #[test]\n    fn test_del_item_does_not_update_original_object() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            let dict = (&v).into_pyobject(py).unwrap();\n            assert!(dict.del_item(7i32).is_ok()); // change\n            assert_eq!(32i32, *v.get(&7i32).unwrap()); // not updated!\n        });\n    }\n\n    #[test]\n    fn test_items() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let dict = v.into_pyobject(py).unwrap();\n            // Can't just compare against a vector of tuples since we don't have a guaranteed ordering.\n            let mut key_sum = 0;\n            let mut value_sum = 0;\n            for el in dict.items() {\n                let tuple = el.cast::<PyTuple>().unwrap();\n                key_sum += tuple.get_item(0).unwrap().extract::<i32>().unwrap();\n                value_sum += tuple.get_item(1).unwrap().extract::<i32>().unwrap();\n            }\n            assert_eq!(7 + 8 + 9, key_sum);\n            assert_eq!(32 + 42 + 123, value_sum);\n        });\n    }\n\n    #[test]\n    fn test_keys() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let dict = v.into_pyobject(py).unwrap();\n            // Can't just compare against a vector of tuples since we don't have a guaranteed ordering.\n            let mut key_sum = 0;\n            for el in dict.keys() {\n                key_sum += el.extract::<i32>().unwrap();\n            }\n            assert_eq!(7 + 8 + 9, key_sum);\n        });\n    }\n\n    #[test]\n    fn test_values() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let dict = v.into_pyobject(py).unwrap();\n            // Can't just compare against a vector of tuples since we don't have a guaranteed ordering.\n            let mut values_sum = 0;\n            for el in dict.values() {\n                values_sum += el.extract::<i32>().unwrap();\n            }\n            assert_eq!(32 + 42 + 123, values_sum);\n        });\n    }\n\n    #[test]\n    fn test_iter() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let dict = v.into_pyobject(py).unwrap();\n            let mut key_sum = 0;\n            let mut value_sum = 0;\n            for (key, value) in dict {\n                key_sum += key.extract::<i32>().unwrap();\n                value_sum += value.extract::<i32>().unwrap();\n            }\n            assert_eq!(7 + 8 + 9, key_sum);\n            assert_eq!(32 + 42 + 123, value_sum);\n        });\n    }\n\n    #[test]\n    fn test_iter_bound() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let dict = v.into_pyobject(py).unwrap();\n            let mut key_sum = 0;\n            let mut value_sum = 0;\n            for (key, value) in dict {\n                key_sum += key.extract::<i32>().unwrap();\n                value_sum += value.extract::<i32>().unwrap();\n            }\n            assert_eq!(7 + 8 + 9, key_sum);\n            assert_eq!(32 + 42 + 123, value_sum);\n        });\n    }\n\n    #[test]\n    fn test_iter_value_mutated() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n\n            let dict = (&v).into_pyobject(py).unwrap();\n\n            for (key, value) in &dict {\n                dict.set_item(key, value.extract::<i32>().unwrap() + 7)\n                    .unwrap();\n            }\n        });\n    }\n\n    #[test]\n    #[should_panic]\n    fn test_iter_key_mutated() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            for i in 0..10 {\n                v.insert(i * 2, i * 2);\n            }\n            let dict = v.into_pyobject(py).unwrap();\n\n            for (i, (key, value)) in dict.iter().enumerate() {\n                let key = key.extract::<i32>().unwrap();\n                let value = value.extract::<i32>().unwrap();\n\n                dict.set_item(key + 1, value + 1).unwrap();\n\n                if i > 1000 {\n                    // avoid this test just running out of memory if it fails\n                    break;\n                };\n            }\n        });\n    }\n\n    #[test]\n    #[should_panic]\n    fn test_iter_key_mutated_constant_len() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            for i in 0..10 {\n                v.insert(i * 2, i * 2);\n            }\n            let dict = v.into_pyobject(py).unwrap();\n\n            for (i, (key, value)) in dict.iter().enumerate() {\n                let key = key.extract::<i32>().unwrap();\n                let value = value.extract::<i32>().unwrap();\n                dict.del_item(key).unwrap();\n                dict.set_item(key + 1, value + 1).unwrap();\n\n                if i > 1000 {\n                    // avoid this test just running out of memory if it fails\n                    break;\n                };\n            }\n        });\n    }\n\n    #[test]\n    fn test_iter_size_hint() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let dict = (&v).into_pyobject(py).unwrap();\n\n            let mut iter = dict.iter();\n            assert_eq!(iter.size_hint(), (v.len(), Some(v.len())));\n            iter.next();\n            assert_eq!(iter.size_hint(), (v.len() - 1, Some(v.len() - 1)));\n\n            // Exhaust iterator.\n            for _ in &mut iter {}\n\n            assert_eq!(iter.size_hint(), (0, Some(0)));\n\n            assert!(iter.next().is_none());\n\n            assert_eq!(iter.size_hint(), (0, Some(0)));\n        });\n    }\n\n    #[test]\n    fn test_into_iter() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let dict = v.into_pyobject(py).unwrap();\n            let mut key_sum = 0;\n            let mut value_sum = 0;\n            for (key, value) in dict {\n                key_sum += key.extract::<i32>().unwrap();\n                value_sum += value.extract::<i32>().unwrap();\n            }\n            assert_eq!(7 + 8 + 9, key_sum);\n            assert_eq!(32 + 42 + 123, value_sum);\n        });\n    }\n\n    #[test]\n    fn test_hashmap_into_dict() {\n        Python::attach(|py| {\n            let mut map = HashMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let py_map = map.into_py_dict(py).unwrap();\n\n            assert_eq!(py_map.len(), 1);\n            assert_eq!(\n                py_map\n                    .get_item(1)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                1\n            );\n        });\n    }\n\n    #[test]\n    fn test_btreemap_into_dict() {\n        Python::attach(|py| {\n            let mut map = BTreeMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let py_map = map.into_py_dict(py).unwrap();\n\n            assert_eq!(py_map.len(), 1);\n            assert_eq!(\n                py_map\n                    .get_item(1)\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                1\n            );\n        });\n    }\n\n    #[test]\n    fn test_vec_into_dict() {\n        Python::attach(|py| {\n            let vec = vec![(\"a\", 1), (\"b\", 2), (\"c\", 3)];\n            let py_map = vec.into_py_dict(py).unwrap();\n\n            assert_eq!(py_map.len(), 3);\n            assert_eq!(\n                py_map\n                    .get_item(\"b\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                2\n            );\n        });\n    }\n\n    #[test]\n    fn test_slice_into_dict() {\n        Python::attach(|py| {\n            let arr = [(\"a\", 1), (\"b\", 2), (\"c\", 3)];\n            let py_map = arr.into_py_dict(py).unwrap();\n\n            assert_eq!(py_map.len(), 3);\n            assert_eq!(\n                py_map\n                    .get_item(\"b\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                2\n            );\n        });\n    }\n\n    #[test]\n    fn dict_as_mapping() {\n        Python::attach(|py| {\n            let mut map = HashMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let py_map = map.into_py_dict(py).unwrap();\n\n            assert_eq!(py_map.as_mapping().len().unwrap(), 1);\n            assert_eq!(\n                py_map\n                    .as_mapping()\n                    .get_item(1)\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                1\n            );\n        });\n    }\n\n    #[test]\n    fn dict_into_mapping() {\n        Python::attach(|py| {\n            let mut map = HashMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let py_map = map.into_py_dict(py).unwrap();\n\n            let py_mapping = py_map.into_mapping();\n            assert_eq!(py_mapping.len().unwrap(), 1);\n            assert_eq!(py_mapping.get_item(1).unwrap().extract::<i32>().unwrap(), 1);\n        });\n    }\n\n    #[cfg(not(any(PyPy, GraalPy)))]\n    fn abc_dict(py: Python<'_>) -> Bound<'_, PyDict> {\n        let mut map = HashMap::<&'static str, i32>::new();\n        map.insert(\"a\", 1);\n        map.insert(\"b\", 2);\n        map.insert(\"c\", 3);\n        map.into_py_dict(py).unwrap()\n    }\n\n    #[test]\n    #[cfg(not(any(PyPy, GraalPy)))]\n    fn dict_keys_view() {\n        Python::attach(|py| {\n            let dict = abc_dict(py);\n            let keys = dict.call_method0(\"keys\").unwrap();\n            assert!(keys.is_instance(&py.get_type::<PyDictKeys>()).unwrap());\n        })\n    }\n\n    #[test]\n    #[cfg(not(any(PyPy, GraalPy)))]\n    fn dict_values_view() {\n        Python::attach(|py| {\n            let dict = abc_dict(py);\n            let values = dict.call_method0(\"values\").unwrap();\n            assert!(values.is_instance(&py.get_type::<PyDictValues>()).unwrap());\n        })\n    }\n\n    #[test]\n    #[cfg(not(any(PyPy, GraalPy)))]\n    fn dict_items_view() {\n        Python::attach(|py| {\n            let dict = abc_dict(py);\n            let items = dict.call_method0(\"items\").unwrap();\n            assert!(items.is_instance(&py.get_type::<PyDictItems>()).unwrap());\n        })\n    }\n\n    #[test]\n    fn dict_update() {\n        Python::attach(|py| {\n            let dict = [(\"a\", 1), (\"b\", 2), (\"c\", 3)].into_py_dict(py).unwrap();\n            let other = [(\"b\", 4), (\"c\", 5), (\"d\", 6)].into_py_dict(py).unwrap();\n            dict.update(other.as_mapping()).unwrap();\n            assert_eq!(dict.len(), 4);\n            assert_eq!(\n                dict.get_item(\"a\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                1\n            );\n            assert_eq!(\n                dict.get_item(\"b\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                4\n            );\n            assert_eq!(\n                dict.get_item(\"c\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                5\n            );\n            assert_eq!(\n                dict.get_item(\"d\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                6\n            );\n\n            assert_eq!(other.len(), 3);\n            assert_eq!(\n                other\n                    .get_item(\"b\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                4\n            );\n            assert_eq!(\n                other\n                    .get_item(\"c\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                5\n            );\n            assert_eq!(\n                other\n                    .get_item(\"d\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                6\n            );\n        })\n    }\n\n    #[test]\n    fn dict_update_if_missing() {\n        Python::attach(|py| {\n            let dict = [(\"a\", 1), (\"b\", 2), (\"c\", 3)].into_py_dict(py).unwrap();\n            let other = [(\"b\", 4), (\"c\", 5), (\"d\", 6)].into_py_dict(py).unwrap();\n            dict.update_if_missing(other.as_mapping()).unwrap();\n            assert_eq!(dict.len(), 4);\n            assert_eq!(\n                dict.get_item(\"a\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                1\n            );\n            assert_eq!(\n                dict.get_item(\"b\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                2\n            );\n            assert_eq!(\n                dict.get_item(\"c\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                3\n            );\n            assert_eq!(\n                dict.get_item(\"d\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                6\n            );\n\n            assert_eq!(other.len(), 3);\n            assert_eq!(\n                other\n                    .get_item(\"b\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                4\n            );\n            assert_eq!(\n                other\n                    .get_item(\"c\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                5\n            );\n            assert_eq!(\n                other\n                    .get_item(\"d\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                6\n            );\n        })\n    }\n\n    #[test]\n    fn test_iter_all() {\n        Python::attach(|py| {\n            let dict = [(1, true), (2, true), (3, true)].into_py_dict(py).unwrap();\n            assert!(dict.iter().all(|(_, v)| v.extract::<bool>().unwrap()));\n\n            let dict = [(1, true), (2, false), (3, true)].into_py_dict(py).unwrap();\n            assert!(!dict.iter().all(|(_, v)| v.extract::<bool>().unwrap()));\n        });\n    }\n\n    #[test]\n    fn test_iter_any() {\n        Python::attach(|py| {\n            let dict = [(1, true), (2, false), (3, false)]\n                .into_py_dict(py)\n                .unwrap();\n            assert!(dict.iter().any(|(_, v)| v.extract::<bool>().unwrap()));\n\n            let dict = [(1, false), (2, false), (3, false)]\n                .into_py_dict(py)\n                .unwrap();\n            assert!(!dict.iter().any(|(_, v)| v.extract::<bool>().unwrap()));\n        });\n    }\n\n    #[test]\n    #[allow(clippy::search_is_some)]\n    fn test_iter_find() {\n        Python::attach(|py| {\n            let dict = [(1, false), (2, true), (3, false)]\n                .into_py_dict(py)\n                .unwrap();\n\n            assert_eq!(\n                Some((2, true)),\n                dict.iter()\n                    .find(|(_, v)| v.extract::<bool>().unwrap())\n                    .map(|(k, v)| (k.extract().unwrap(), v.extract().unwrap()))\n            );\n\n            let dict = [(1, false), (2, false), (3, false)]\n                .into_py_dict(py)\n                .unwrap();\n\n            assert!(dict\n                .iter()\n                .find(|(_, v)| v.extract::<bool>().unwrap())\n                .is_none());\n        });\n    }\n\n    #[test]\n    #[allow(clippy::search_is_some)]\n    fn test_iter_position() {\n        Python::attach(|py| {\n            let dict = [(1, false), (2, false), (3, true)]\n                .into_py_dict(py)\n                .unwrap();\n            assert_eq!(\n                Some(2),\n                dict.iter().position(|(_, v)| v.extract::<bool>().unwrap())\n            );\n\n            let dict = [(1, false), (2, false), (3, false)]\n                .into_py_dict(py)\n                .unwrap();\n            assert!(dict\n                .iter()\n                .position(|(_, v)| v.extract::<bool>().unwrap())\n                .is_none());\n        });\n    }\n\n    #[test]\n    fn test_iter_fold() {\n        Python::attach(|py| {\n            let dict = [(1, 1), (2, 2), (3, 3)].into_py_dict(py).unwrap();\n            let sum = dict\n                .iter()\n                .fold(0, |acc, (_, v)| acc + v.extract::<i32>().unwrap());\n            assert_eq!(sum, 6);\n        });\n    }\n\n    #[test]\n    fn test_iter_try_fold() {\n        Python::attach(|py| {\n            let dict = [(1, 1), (2, 2), (3, 3)].into_py_dict(py).unwrap();\n            let sum = dict\n                .iter()\n                .try_fold(0, |acc, (_, v)| PyResult::Ok(acc + v.extract::<i32>()?))\n                .unwrap();\n            assert_eq!(sum, 6);\n\n            let dict = [(1, \"foo\"), (2, \"bar\")].into_py_dict(py).unwrap();\n            assert!(dict\n                .iter()\n                .try_fold(0, |acc, (_, v)| PyResult::Ok(acc + v.extract::<i32>()?))\n                .is_err());\n        });\n    }\n\n    #[test]\n    fn test_iter_count() {\n        Python::attach(|py| {\n            let dict = [(1, 1), (2, 2), (3, 3)].into_py_dict(py).unwrap();\n            assert_eq!(dict.iter().count(), 3);\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/ellipsis.rs",
    "content": "#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_identifier, PyStaticExpr};\nuse crate::{\n    ffi, ffi_ptr_ext::FfiPtrExt, types::any::PyAnyMethods, Borrowed, Bound, PyAny, PyTypeInfo,\n    Python,\n};\n\n/// Represents the Python `Ellipsis` object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyEllipsis>`][crate::Py] or [`Bound<'py, PyEllipsis>`][Bound].\n#[repr(transparent)]\npub struct PyEllipsis(PyAny);\n\npyobject_native_type_named!(PyEllipsis);\n\nimpl PyEllipsis {\n    /// Returns the `Ellipsis` object.\n    #[inline]\n    pub fn get(py: Python<'_>) -> Borrowed<'_, '_, PyEllipsis> {\n        // SAFETY: `Py_Ellipsis` is a global singleton which is known to be the ellipsis object\n        unsafe {\n            ffi::Py_Ellipsis()\n                .assume_borrowed_unchecked(py)\n                .cast_unchecked()\n        }\n    }\n}\n\nunsafe impl PyTypeInfo for PyEllipsis {\n    const NAME: &'static str = \"ellipsis\";\n    const MODULE: Option<&'static str> = None;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const TYPE_HINT: PyStaticExpr = type_hint_identifier!(\"types\", \"EllipsisType\");\n\n    fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject {\n        unsafe { ffi::Py_TYPE(ffi::Py_Ellipsis()) }\n    }\n\n    #[inline]\n    fn is_type_of(object: &Bound<'_, PyAny>) -> bool {\n        // ellipsis is not usable as a base type\n        Self::is_exact_type_of(object)\n    }\n\n    #[inline]\n    fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool {\n        object.is(&**Self::get(object.py()))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::any::PyAnyMethods;\n    use crate::types::{PyDict, PyEllipsis};\n    use crate::{PyTypeInfo, Python};\n\n    #[test]\n    fn test_ellipsis_is_itself() {\n        Python::attach(|py| {\n            assert!(PyEllipsis::get(py).is_instance_of::<PyEllipsis>());\n            assert!(PyEllipsis::get(py).is_exact_instance_of::<PyEllipsis>());\n        })\n    }\n\n    #[test]\n    fn test_ellipsis_type_object_consistent() {\n        Python::attach(|py| {\n            assert!(PyEllipsis::get(py)\n                .get_type()\n                .is(PyEllipsis::type_object(py)));\n        })\n    }\n\n    #[test]\n    fn test_dict_is_not_ellipsis() {\n        Python::attach(|py| {\n            assert!(PyDict::new(py).cast::<PyEllipsis>().is_err());\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/float.rs",
    "content": "use crate::conversion::IntoPyObject;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::{\n    ffi, ffi_ptr_ext::FfiPtrExt, instance::Bound, Borrowed, FromPyObject, PyAny, PyErr, Python,\n};\nuse std::convert::Infallible;\nuse std::ffi::c_double;\n\n/// Represents a Python `float` object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyFloat>`][crate::Py] or [`Bound<'py, PyFloat>`][Bound].\n///\n/// For APIs available on `float` objects, see the [`PyFloatMethods`] trait which is implemented for\n/// [`Bound<'py, PyFloat>`][Bound].\n///\n/// You can usually avoid directly working with this type\n/// by using [`IntoPyObject`] and [`extract`][crate::types::PyAnyMethods::extract]\n/// with [`f32`]/[`f64`].\n#[repr(transparent)]\npub struct PyFloat(PyAny);\n\npyobject_subclassable_native_type!(PyFloat, crate::ffi::PyFloatObject);\n\npyobject_native_type!(\n    PyFloat,\n    ffi::PyFloatObject,\n    pyobject_native_static_type_object!(ffi::PyFloat_Type),\n    \"builtins\",\n    \"float\",\n    #checkfunction=ffi::PyFloat_Check\n);\n\nimpl PyFloat {\n    /// Creates a new Python `float` object.\n    pub fn new(py: Python<'_>, val: c_double) -> Bound<'_, PyFloat> {\n        unsafe {\n            ffi::PyFloat_FromDouble(val)\n                .assume_owned(py)\n                .cast_into_unchecked()\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyFloat`].\n///\n/// These methods are defined for the `Bound<'py, PyFloat>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyFloat\")]\npub trait PyFloatMethods<'py>: crate::sealed::Sealed {\n    /// Gets the value of this float.\n    fn value(&self) -> c_double;\n}\n\nimpl<'py> PyFloatMethods<'py> for Bound<'py, PyFloat> {\n    fn value(&self) -> c_double {\n        #[cfg(not(Py_LIMITED_API))]\n        unsafe {\n            // Safety: self is PyFloat object\n            ffi::PyFloat_AS_DOUBLE(self.as_ptr())\n        }\n\n        #[cfg(Py_LIMITED_API)]\n        unsafe {\n            ffi::PyFloat_AsDouble(self.as_ptr())\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for f64 {\n    type Target = PyFloat;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyFloat::TYPE_HINT;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PyFloat::new(py, self))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &f64 {\n    type Target = PyFloat;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = f64::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'py> FromPyObject<'_, 'py> for f64 {\n    type Error = PyErr;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyFloat::TYPE_HINT;\n\n    // PyFloat_AsDouble returns -1.0 upon failure\n    #[allow(clippy::float_cmp)]\n    fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        // On non-limited API, .value() uses PyFloat_AS_DOUBLE which\n        // allows us to have an optimized fast path for the case when\n        // we have exactly a `float` object (it's not worth going through\n        // `isinstance` machinery for subclasses).\n        #[cfg(not(Py_LIMITED_API))]\n        if let Ok(float) = obj.cast_exact::<PyFloat>() {\n            return Ok(float.value());\n        }\n\n        let v = unsafe { ffi::PyFloat_AsDouble(obj.as_ptr()) };\n\n        if v == -1.0 {\n            if let Some(err) = PyErr::take(obj.py()) {\n                return Err(err);\n            }\n        }\n\n        Ok(v)\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for f32 {\n    type Target = PyFloat;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PyFloat::TYPE_HINT;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PyFloat::new(py, self.into()))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &f32 {\n    type Target = PyFloat;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = f32::OUTPUT_TYPE;\n\n    #[inline]\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        (*self).into_pyobject(py)\n    }\n}\n\nimpl<'a, 'py> FromPyObject<'a, 'py> for f32 {\n    type Error = <f64 as FromPyObject<'a, 'py>>::Error;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const INPUT_TYPE: PyStaticExpr = PyFloat::TYPE_HINT;\n\n    fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {\n        Ok(obj.extract::<f64>()? as f32)\n    }\n}\n\nmacro_rules! impl_partial_eq_for_float {\n    ($float_type: ty) => {\n        impl PartialEq<$float_type> for Bound<'_, PyFloat> {\n            #[inline]\n            fn eq(&self, other: &$float_type) -> bool {\n                self.value() as $float_type == *other\n            }\n        }\n\n        impl PartialEq<$float_type> for &Bound<'_, PyFloat> {\n            #[inline]\n            fn eq(&self, other: &$float_type) -> bool {\n                self.value() as $float_type == *other\n            }\n        }\n\n        impl PartialEq<&$float_type> for Bound<'_, PyFloat> {\n            #[inline]\n            fn eq(&self, other: &&$float_type) -> bool {\n                self.value() as $float_type == **other\n            }\n        }\n\n        impl PartialEq<Bound<'_, PyFloat>> for $float_type {\n            #[inline]\n            fn eq(&self, other: &Bound<'_, PyFloat>) -> bool {\n                other.value() as $float_type == *self\n            }\n        }\n\n        impl PartialEq<&'_ Bound<'_, PyFloat>> for $float_type {\n            #[inline]\n            fn eq(&self, other: &&'_ Bound<'_, PyFloat>) -> bool {\n                other.value() as $float_type == *self\n            }\n        }\n\n        impl PartialEq<Bound<'_, PyFloat>> for &'_ $float_type {\n            #[inline]\n            fn eq(&self, other: &Bound<'_, PyFloat>) -> bool {\n                other.value() as $float_type == **self\n            }\n        }\n\n        impl PartialEq<$float_type> for Borrowed<'_, '_, PyFloat> {\n            #[inline]\n            fn eq(&self, other: &$float_type) -> bool {\n                self.value() as $float_type == *other\n            }\n        }\n\n        impl PartialEq<&$float_type> for Borrowed<'_, '_, PyFloat> {\n            #[inline]\n            fn eq(&self, other: &&$float_type) -> bool {\n                self.value() as $float_type == **other\n            }\n        }\n\n        impl PartialEq<Borrowed<'_, '_, PyFloat>> for $float_type {\n            #[inline]\n            fn eq(&self, other: &Borrowed<'_, '_, PyFloat>) -> bool {\n                other.value() as $float_type == *self\n            }\n        }\n\n        impl PartialEq<Borrowed<'_, '_, PyFloat>> for &$float_type {\n            #[inline]\n            fn eq(&self, other: &Borrowed<'_, '_, PyFloat>) -> bool {\n                other.value() as $float_type == **self\n            }\n        }\n    };\n}\n\nimpl_partial_eq_for_float!(f64);\nimpl_partial_eq_for_float!(f32);\n\n#[cfg(test)]\nmod tests {\n    use crate::{\n        conversion::IntoPyObject,\n        types::{PyAnyMethods, PyFloat, PyFloatMethods},\n        Python,\n    };\n\n    macro_rules! num_to_py_object_and_back (\n        ($func_name:ident, $t1:ty, $t2:ty) => (\n            #[test]\n            fn $func_name() {\n                use assert_approx_eq::assert_approx_eq;\n\n                Python::attach(|py| {\n\n                let val = 123 as $t1;\n                let obj = val.into_pyobject(py).unwrap();\n                assert_approx_eq!(obj.extract::<$t2>().unwrap(), val as $t2);\n                });\n            }\n        )\n    );\n\n    num_to_py_object_and_back!(to_from_f64, f64, f64);\n    num_to_py_object_and_back!(to_from_f32, f32, f32);\n    num_to_py_object_and_back!(int_to_float, i32, f64);\n\n    #[test]\n    fn test_float_value() {\n        use assert_approx_eq::assert_approx_eq;\n\n        Python::attach(|py| {\n            let v = 1.23f64;\n            let obj = PyFloat::new(py, 1.23);\n            assert_approx_eq!(v, obj.value());\n        });\n    }\n\n    #[test]\n    fn test_pyfloat_comparisons() {\n        Python::attach(|py| {\n            let f_64 = 1.01f64;\n            let py_f64 = PyFloat::new(py, 1.01);\n            let py_f64_ref = &py_f64;\n            let py_f64_borrowed = py_f64.as_borrowed();\n\n            // Bound<'_, PyFloat> == f64 and vice versa\n            assert_eq!(py_f64, f_64);\n            assert_eq!(f_64, py_f64);\n\n            // Bound<'_, PyFloat> == &f64 and vice versa\n            assert_eq!(py_f64, &f_64);\n            assert_eq!(&f_64, py_f64);\n\n            // &Bound<'_, PyFloat> == &f64 and vice versa\n            assert_eq!(py_f64_ref, f_64);\n            assert_eq!(f_64, py_f64_ref);\n\n            // &Bound<'_, PyFloat> == &f64 and vice versa\n            assert_eq!(py_f64_ref, &f_64);\n            assert_eq!(&f_64, py_f64_ref);\n\n            // Borrowed<'_, '_, PyFloat> == f64 and vice versa\n            assert_eq!(py_f64_borrowed, f_64);\n            assert_eq!(f_64, py_f64_borrowed);\n\n            // Borrowed<'_, '_, PyFloat> == &f64 and vice versa\n            assert_eq!(py_f64_borrowed, &f_64);\n            assert_eq!(&f_64, py_f64_borrowed);\n\n            let f_32 = 2.02f32;\n            let py_f32 = PyFloat::new(py, 2.02);\n            let py_f32_ref = &py_f32;\n            let py_f32_borrowed = py_f32.as_borrowed();\n\n            // Bound<'_, PyFloat> == f32 and vice versa\n            assert_eq!(py_f32, f_32);\n            assert_eq!(f_32, py_f32);\n\n            // Bound<'_, PyFloat> == &f32 and vice versa\n            assert_eq!(py_f32, &f_32);\n            assert_eq!(&f_32, py_f32);\n\n            // &Bound<'_, PyFloat> == &f32 and vice versa\n            assert_eq!(py_f32_ref, f_32);\n            assert_eq!(f_32, py_f32_ref);\n\n            // &Bound<'_, PyFloat> == &f32 and vice versa\n            assert_eq!(py_f32_ref, &f_32);\n            assert_eq!(&f_32, py_f32_ref);\n\n            // Borrowed<'_, '_, PyFloat> == f32 and vice versa\n            assert_eq!(py_f32_borrowed, f_32);\n            assert_eq!(f_32, py_f32_borrowed);\n\n            // Borrowed<'_, '_, PyFloat> == &f32 and vice versa\n            assert_eq!(py_f32_borrowed, &f_32);\n            assert_eq!(&f_32, py_f32_borrowed);\n        });\n    }\n}\n"
  },
  {
    "path": "src/types/frame.rs",
    "content": "use crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::sealed::Sealed;\nuse crate::types::{PyCode, PyDict};\nuse crate::PyAny;\nuse crate::{ffi, Bound, PyResult, Python};\nuse pyo3_ffi::PyObject;\nuse std::ffi::CStr;\n\n/// Represents a Python frame.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyFrame>`][crate::Py] or [`Bound<'py, PyFrame>`][crate::Bound].\n#[repr(transparent)]\npub struct PyFrame(PyAny);\n\npyobject_native_type_core!(\n    PyFrame,\n    pyobject_native_static_type_object!(ffi::PyFrame_Type),\n    \"types\",\n    \"FrameType\",\n    #checkfunction=ffi::PyFrame_Check\n);\n\nimpl PyFrame {\n    /// Creates a new frame object.\n    pub fn new<'py>(\n        py: Python<'py>,\n        file_name: &CStr,\n        func_name: &CStr,\n        line_number: i32,\n    ) -> PyResult<Bound<'py, PyFrame>> {\n        // Safety: Thread is attached because we have a python token\n        let state = unsafe { ffi::compat::PyThreadState_GetUnchecked() };\n        let code = PyCode::empty(py, file_name, func_name, line_number);\n        let globals = PyDict::new(py);\n        let locals = PyDict::new(py);\n\n        unsafe {\n            Ok(ffi::PyFrame_New(\n                state,\n                code.into_ptr().cast(),\n                globals.as_ptr(),\n                locals.as_ptr(),\n            )\n            .cast::<PyObject>()\n            .assume_owned_or_err(py)?\n            .cast_into_unchecked::<PyFrame>())\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyFrame`].\n///\n/// These methods are defined for the `Bound<'py, PyFrame>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyFrame\")]\npub trait PyFrameMethods<'py>: Sealed {\n    /// Returns the line number of the current instruction in the frame.\n    fn line_number(&self) -> i32;\n}\n\nimpl<'py> PyFrameMethods<'py> for Bound<'py, PyFrame> {\n    fn line_number(&self) -> i32 {\n        unsafe { ffi::PyFrame_GetLineNumber(self.as_ptr().cast()) }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_frame_creation() {\n        Python::attach(|py| {\n            let frame = PyFrame::new(py, c\"file.py\", c\"func\", 42).unwrap();\n            assert_eq!(frame.line_number(), 42);\n        });\n    }\n}\n"
  },
  {
    "path": "src/types/frozenset.rs",
    "content": "use crate::types::PyIterator;\nuse crate::{\n    err::{self, PyErr, PyResult},\n    ffi,\n    ffi_ptr_ext::FfiPtrExt,\n    py_result_ext::PyResultExt,\n    Bound, PyAny, Python,\n};\nuse crate::{Borrowed, BoundObject, IntoPyObject, IntoPyObjectExt};\nuse std::ptr;\n\n/// Allows building a Python `frozenset` one item at a time\npub struct PyFrozenSetBuilder<'py> {\n    py_frozen_set: Bound<'py, PyFrozenSet>,\n}\n\nimpl<'py> PyFrozenSetBuilder<'py> {\n    /// Create a new `FrozenSetBuilder`.\n    /// Since this allocates a `PyFrozenSet` internally it may\n    /// panic when running out of memory.\n    pub fn new(py: Python<'py>) -> PyResult<PyFrozenSetBuilder<'py>> {\n        Ok(PyFrozenSetBuilder {\n            py_frozen_set: PyFrozenSet::empty(py)?,\n        })\n    }\n\n    /// Adds an element to the set.\n    pub fn add<K>(&mut self, key: K) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>,\n    {\n        fn inner(frozenset: &Bound<'_, PyFrozenSet>, key: Borrowed<'_, '_, PyAny>) -> PyResult<()> {\n            err::error_on_minusone(frozenset.py(), unsafe {\n                ffi::PySet_Add(frozenset.as_ptr(), key.as_ptr())\n            })\n        }\n\n        inner(\n            &self.py_frozen_set,\n            key.into_pyobject_or_pyerr(self.py_frozen_set.py())?\n                .into_any()\n                .as_borrowed(),\n        )\n    }\n\n    /// Finish building the set and take ownership of its current value\n    pub fn finalize(self) -> Bound<'py, PyFrozenSet> {\n        self.py_frozen_set\n    }\n}\n\n/// Represents a  Python `frozenset`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyFrozenSet>`][crate::Py] or [`Bound<'py, PyFrozenSet>`][Bound].\n///\n/// For APIs available on `frozenset` objects, see the [`PyFrozenSetMethods`] trait which is implemented for\n/// [`Bound<'py, PyFrozenSet>`][Bound].\n#[repr(transparent)]\npub struct PyFrozenSet(PyAny);\n\n#[cfg(not(any(PyPy, GraalPy)))]\npyobject_subclassable_native_type!(PyFrozenSet, crate::ffi::PySetObject);\n#[cfg(not(any(PyPy, GraalPy)))]\npyobject_native_type!(\n    PyFrozenSet,\n    ffi::PySetObject,\n    pyobject_native_static_type_object!(ffi::PyFrozenSet_Type),\n    \"builtins\",\n    \"frozenset\",\n    #checkfunction=ffi::PyFrozenSet_Check\n);\n\n#[cfg(any(PyPy, GraalPy))]\npyobject_native_type_core!(\n    PyFrozenSet,\n    pyobject_native_static_type_object!(ffi::PyFrozenSet_Type),\n    \"builtins\",\n    \"frozenset\",\n    #checkfunction=ffi::PyFrozenSet_Check\n);\n\nimpl PyFrozenSet {\n    /// Creates a new frozenset.\n    ///\n    /// May panic when running out of memory.\n    #[inline]\n    pub fn new<'py, T>(\n        py: Python<'py>,\n        elements: impl IntoIterator<Item = T>,\n    ) -> PyResult<Bound<'py, PyFrozenSet>>\n    where\n        T: IntoPyObject<'py>,\n    {\n        let mut builder = PyFrozenSetBuilder::new(py)?;\n        for e in elements {\n            builder.add(e)?;\n        }\n        Ok(builder.finalize())\n    }\n\n    /// Creates a new empty frozen set\n    pub fn empty(py: Python<'_>) -> PyResult<Bound<'_, PyFrozenSet>> {\n        unsafe {\n            ffi::PyFrozenSet_New(ptr::null_mut())\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyFrozenSet`].\n///\n/// These methods are defined for the `Bound<'py, PyFrozenSet>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyFrozenSet\")]\npub trait PyFrozenSetMethods<'py>: crate::sealed::Sealed {\n    /// Returns the number of items in the set.\n    ///\n    /// This is equivalent to the Python expression `len(self)`.\n    fn len(&self) -> usize;\n\n    /// Checks if set is empty.\n    fn is_empty(&self) -> bool {\n        self.len() == 0\n    }\n\n    /// Determines if the set contains the specified key.\n    ///\n    /// This is equivalent to the Python expression `key in self`.\n    fn contains<K>(&self, key: K) -> PyResult<bool>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Returns an iterator of values in this set.\n    fn iter(&self) -> BoundFrozenSetIterator<'py>;\n}\n\nimpl<'py> PyFrozenSetMethods<'py> for Bound<'py, PyFrozenSet> {\n    #[inline]\n    fn len(&self) -> usize {\n        unsafe { ffi::PySet_Size(self.as_ptr()) as usize }\n    }\n\n    fn contains<K>(&self, key: K) -> PyResult<bool>\n    where\n        K: IntoPyObject<'py>,\n    {\n        fn inner(\n            frozenset: &Bound<'_, PyFrozenSet>,\n            key: Borrowed<'_, '_, PyAny>,\n        ) -> PyResult<bool> {\n            match unsafe { ffi::PySet_Contains(frozenset.as_ptr(), key.as_ptr()) } {\n                1 => Ok(true),\n                0 => Ok(false),\n                _ => Err(PyErr::fetch(frozenset.py())),\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn iter(&self) -> BoundFrozenSetIterator<'py> {\n        BoundFrozenSetIterator::new(self.clone())\n    }\n}\n\nimpl<'py> IntoIterator for Bound<'py, PyFrozenSet> {\n    type Item = Bound<'py, PyAny>;\n    type IntoIter = BoundFrozenSetIterator<'py>;\n\n    /// Returns an iterator of values in this set.\n    fn into_iter(self) -> Self::IntoIter {\n        BoundFrozenSetIterator::new(self)\n    }\n}\n\nimpl<'py> IntoIterator for &Bound<'py, PyFrozenSet> {\n    type Item = Bound<'py, PyAny>;\n    type IntoIter = BoundFrozenSetIterator<'py>;\n\n    /// Returns an iterator of values in this set.\n    fn into_iter(self) -> Self::IntoIter {\n        self.iter()\n    }\n}\n\n/// PyO3 implementation of an iterator for a Python `frozenset` object.\npub struct BoundFrozenSetIterator<'py>(Bound<'py, PyIterator>);\n\nimpl<'py> BoundFrozenSetIterator<'py> {\n    pub(super) fn new(set: Bound<'py, PyFrozenSet>) -> Self {\n        Self(PyIterator::from_object(&set).expect(\"frozenset should always be iterable\"))\n    }\n}\n\nimpl<'py> Iterator for BoundFrozenSetIterator<'py> {\n    type Item = Bound<'py, super::PyAny>;\n\n    /// Advances the iterator and returns the next value.\n    fn next(&mut self) -> Option<Self::Item> {\n        self.0\n            .next()\n            .map(|result| result.expect(\"frozenset iteration should be infallible\"))\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let len = ExactSizeIterator::len(self);\n        (len, Some(len))\n    }\n\n    #[inline]\n    fn count(self) -> usize\n    where\n        Self: Sized,\n    {\n        self.len()\n    }\n}\n\nimpl ExactSizeIterator for BoundFrozenSetIterator<'_> {\n    fn len(&self) -> usize {\n        self.0.size_hint().0\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::PyAnyMethods as _;\n\n    #[test]\n    fn test_frozenset_new_and_len() {\n        Python::attach(|py| {\n            let set = PyFrozenSet::new(py, [1]).unwrap();\n            assert_eq!(1, set.len());\n\n            let v = vec![1];\n            assert!(PyFrozenSet::new(py, &[v]).is_err());\n        });\n    }\n\n    #[test]\n    fn test_frozenset_empty() {\n        Python::attach(|py| {\n            let set = PyFrozenSet::empty(py).unwrap();\n            assert_eq!(0, set.len());\n            assert!(set.is_empty());\n        });\n    }\n\n    #[test]\n    fn test_frozenset_contains() {\n        Python::attach(|py| {\n            let set = PyFrozenSet::new(py, [1]).unwrap();\n            assert!(set.contains(1).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_frozenset_iter() {\n        Python::attach(|py| {\n            let set = PyFrozenSet::new(py, [1]).unwrap();\n\n            for el in set {\n                assert_eq!(1i32, el.extract::<i32>().unwrap());\n            }\n        });\n    }\n\n    #[test]\n    fn test_frozenset_iter_bound() {\n        Python::attach(|py| {\n            let set = PyFrozenSet::new(py, [1]).unwrap();\n\n            for el in &set {\n                assert_eq!(1i32, el.extract::<i32>().unwrap());\n            }\n        });\n    }\n\n    #[test]\n    fn test_frozenset_iter_size_hint() {\n        Python::attach(|py| {\n            let set = PyFrozenSet::new(py, [1]).unwrap();\n            let mut iter = set.iter();\n\n            // Exact size\n            assert_eq!(iter.len(), 1);\n            assert_eq!(iter.size_hint(), (1, Some(1)));\n            iter.next();\n            assert_eq!(iter.len(), 0);\n            assert_eq!(iter.size_hint(), (0, Some(0)));\n        });\n    }\n\n    #[test]\n    fn test_frozenset_builder() {\n        use super::PyFrozenSetBuilder;\n\n        Python::attach(|py| {\n            let mut builder = PyFrozenSetBuilder::new(py).unwrap();\n\n            // add an item\n            builder.add(1).unwrap();\n            builder.add(2).unwrap();\n            builder.add(2).unwrap();\n\n            // finalize it\n            let set = builder.finalize();\n\n            assert!(set.contains(1).unwrap());\n            assert!(set.contains(2).unwrap());\n            assert!(!set.contains(3).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_iter_count() {\n        Python::attach(|py| {\n            let set = PyFrozenSet::new(py, vec![1, 2, 3]).unwrap();\n            assert_eq!(set.iter().count(), 3);\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/function.rs",
    "content": "use crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::impl_::pyfunction::create_py_c_function;\nuse crate::py_result_ext::PyResultExt;\nuse crate::types::capsule::PyCapsuleMethods;\nuse crate::{\n    ffi,\n    impl_::pymethods::{self, PyMethodDef},\n    types::{PyCapsule, PyDict, PyModule, PyTuple},\n};\nuse crate::{Bound, PyAny, PyResult, Python};\nuse std::cell::UnsafeCell;\nuse std::ffi::CStr;\nuse std::ptr::NonNull;\n\n/// Represents a builtin Python function object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyCFunction>`][crate::Py] or [`Bound<'py, PyCFunction>`][Bound].\n#[repr(transparent)]\npub struct PyCFunction(PyAny);\n\npyobject_native_type_core!(PyCFunction, pyobject_native_static_type_object!(ffi::PyCFunction_Type), \"builtins\", \"builtin_function_or_method\", #checkfunction=ffi::PyCFunction_Check);\n\nimpl PyCFunction {\n    /// Create a new built-in function with keywords (*args and/or **kwargs).\n    ///\n    /// To create `name` and `doc` static strings on Rust versions older than 1.77 (which added c\"\" literals),\n    /// use the [`c_str!`](crate::ffi::c_str) macro.\n    pub fn new_with_keywords<'py>(\n        py: Python<'py>,\n        fun: ffi::PyCFunctionWithKeywords,\n        name: &'static CStr,\n        doc: &'static CStr,\n        module: Option<&Bound<'py, PyModule>>,\n    ) -> PyResult<Bound<'py, Self>> {\n        let def = PyMethodDef::cfunction_with_keywords(name, fun, doc).into_raw();\n        // FIXME: stop leaking the def\n        let def = Box::leak(Box::new(def));\n        // Safety: def is static\n        unsafe { create_py_c_function(py, def, module) }\n    }\n\n    /// Create a new built-in function which takes no arguments.\n    ///\n    /// To create `name` and `doc` static strings on Rust versions older than 1.77 (which added c\"\" literals),\n    /// use the [`c_str!`](crate::ffi::c_str) macro.\n    pub fn new<'py>(\n        py: Python<'py>,\n        fun: ffi::PyCFunction,\n        name: &'static CStr,\n        doc: &'static CStr,\n        module: Option<&Bound<'py, PyModule>>,\n    ) -> PyResult<Bound<'py, Self>> {\n        let def = PyMethodDef::noargs(name, fun, doc).into_raw();\n        // FIXME: stop leaking the def\n        let def = Box::leak(Box::new(def));\n        // Safety: def is static\n        unsafe { create_py_c_function(py, def, module) }\n    }\n\n    /// Create a new function from a closure.\n    ///\n    /// # Examples\n    ///\n    /// ```\n    /// # use pyo3::prelude::*;\n    /// # use pyo3::{py_run, types::{PyCFunction, PyDict, PyTuple}};\n    ///\n    /// Python::attach(|py| {\n    ///     let add_one = |args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>| -> PyResult<_> {\n    ///         let i = args.extract::<(i64,)>()?.0;\n    ///         Ok(i+1)\n    ///     };\n    ///     let add_one = PyCFunction::new_closure(py, None, None, add_one).unwrap();\n    ///     py_run!(py, add_one, \"assert add_one(42) == 43\");\n    /// });\n    /// ```\n    pub fn new_closure<'py, F, R>(\n        py: Python<'py>,\n        name: Option<&'static CStr>,\n        doc: Option<&'static CStr>,\n        closure: F,\n    ) -> PyResult<Bound<'py, Self>>\n    where\n        F: Fn(&Bound<'_, PyTuple>, Option<&Bound<'_, PyDict>>) -> R + Send + 'static,\n        for<'p> R: crate::impl_::callback::IntoPyCallbackOutput<'p, *mut ffi::PyObject>,\n    {\n        let name = name.unwrap_or(c\"pyo3-closure\");\n        let doc = doc.unwrap_or(c\"\");\n        let method_def =\n            pymethods::PyMethodDef::cfunction_with_keywords(name, run_closure::<F, R>, doc);\n        let def = method_def.into_raw();\n\n        let capsule = PyCapsule::new(\n            py,\n            ClosureDestructor::<F> {\n                closure,\n                def: UnsafeCell::new(def),\n            },\n            Some(CLOSURE_CAPSULE_NAME.to_owned()),\n        )?;\n\n        let data: NonNull<ClosureDestructor<F>> =\n            capsule.pointer_checked(Some(CLOSURE_CAPSULE_NAME))?.cast();\n\n        // SAFETY: The capsule has just been created with the value, and will exist as long as\n        // the function object exists.\n        let method_def = unsafe { data.as_ref().def.get() };\n\n        // SAFETY: The arguments to `PyCFunction_NewEx` are valid, we are attached to the\n        // interpreter and we know the function either returns a new reference or errors.\n        unsafe {\n            ffi::PyCFunction_NewEx(method_def, capsule.as_ptr(), std::ptr::null_mut())\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n        }\n    }\n}\n\nstatic CLOSURE_CAPSULE_NAME: &CStr = c\"pyo3-closure\";\n\nunsafe extern \"C\" fn run_closure<F, R>(\n    capsule_ptr: *mut ffi::PyObject,\n    args: *mut ffi::PyObject,\n    kwargs: *mut ffi::PyObject,\n) -> *mut ffi::PyObject\nwhere\n    F: Fn(&Bound<'_, PyTuple>, Option<&Bound<'_, PyDict>>) -> R + Send + 'static,\n    for<'py> R: crate::impl_::callback::IntoPyCallbackOutput<'py, *mut ffi::PyObject>,\n{\n    unsafe {\n        crate::impl_::trampoline::cfunction_with_keywords::inner(\n            capsule_ptr,\n            args,\n            kwargs,\n            |py, capsule_ptr, args, kwargs| {\n                let boxed_fn: &ClosureDestructor<F> =\n                    &*(ffi::PyCapsule_GetPointer(capsule_ptr, CLOSURE_CAPSULE_NAME.as_ptr())\n                        as *mut ClosureDestructor<F>);\n                let args = Bound::ref_from_ptr(py, &args).cast_unchecked::<PyTuple>();\n                let kwargs = Bound::ref_from_ptr_or_opt(py, &kwargs)\n                    .as_ref()\n                    .map(|b| b.cast_unchecked::<PyDict>());\n                let result = (boxed_fn.closure)(args, kwargs);\n                crate::impl_::callback::convert(py, result)\n            },\n        )\n    }\n}\n\nstruct ClosureDestructor<F> {\n    closure: F,\n    // Wrapped in UnsafeCell because Python C-API wants a *mut pointer\n    // to this member.\n    def: UnsafeCell<ffi::PyMethodDef>,\n}\n\n// Safety: F is send and none of the fields are ever mutated\nunsafe impl<F: Send> Send for ClosureDestructor<F> {}\n\n/// Represents a Python function object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyFunction>`][crate::Py] or [`Bound<'py, PyFunction>`][Bound].\n#[repr(transparent)]\n#[cfg(not(Py_LIMITED_API))]\npub struct PyFunction(PyAny);\n\n#[cfg(not(Py_LIMITED_API))]\npyobject_native_type_core!(PyFunction, pyobject_native_static_type_object!(ffi::PyFunction_Type), \"builtins\", \"function\", #checkfunction=ffi::PyFunction_Check);\n"
  },
  {
    "path": "src/types/genericalias.rs",
    "content": "use crate::err::PyResult;\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::py_result_ext::PyResultExt;\nuse crate::{ffi, Bound, PyAny, Python};\n\n/// Represents a Python [`types.GenericAlias`](https://docs.python.org/3/library/types.html#types.GenericAlias) object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyGenericAlias>`][crate::Py] or [`Bound<'py, PyGenericAlias>`][Bound].\n///\n/// This type is particularly convenient for users implementing\n/// [`__class_getitem__`](https://docs.python.org/3/reference/datamodel.html#object.__class_getitem__)\n/// for PyO3 classes to allow runtime parameterization.\n#[repr(transparent)]\npub struct PyGenericAlias(PyAny);\n\npyobject_native_type!(\n    PyGenericAlias,\n    ffi::PyDictObject,\n    pyobject_native_static_type_object!(ffi::Py_GenericAliasType),\n    \"builtins\",\n    \"GenericAlias\"\n);\n\nimpl PyGenericAlias {\n    /// Creates a new Python GenericAlias object.\n    ///\n    /// origin should be a non-parameterized generic class.\n    /// args should be a tuple (possibly of length 1) of types which parameterize origin.\n    pub fn new<'py>(\n        py: Python<'py>,\n        origin: &Bound<'py, PyAny>,\n        args: &Bound<'py, PyAny>,\n    ) -> PyResult<Bound<'py, PyGenericAlias>> {\n        unsafe {\n            ffi::Py_GenericAlias(origin.as_ptr(), args.as_ptr())\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::instance::BoundObject;\n    use crate::types::any::PyAnyMethods;\n    use crate::Python;\n\n    use super::PyGenericAlias;\n\n    // Tests that PyGenericAlias::new is identical to types.GenericAlias\n    // created from Python.\n    #[test]\n    fn equivalency_test() {\n        Python::attach(|py| {\n            let list_int = py.eval(c\"list[int]\", None, None).unwrap().into_bound();\n\n            let cls = py.eval(c\"list\", None, None).unwrap().into_bound();\n            let key = py.eval(c\"(int,)\", None, None).unwrap().into_bound();\n            let generic_alias = PyGenericAlias::new(py, &cls, &key).unwrap();\n\n            assert!(generic_alias.eq(list_int).unwrap());\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/iterator.rs",
    "content": "use crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::py_result_ext::PyResultExt;\nuse crate::sync::PyOnceLock;\n#[cfg(Py_LIMITED_API)]\nuse crate::types::PyAnyMethods;\nuse crate::types::{PyType, PyTypeMethods};\nuse crate::{ffi, Bound, Py, PyAny, PyErr, PyResult};\n\n/// A Python iterator object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyIterator>`][crate::Py] or [`Bound<'py, PyIterator>`][Bound].\n///\n/// # Examples\n///\n/// ```rust\n/// use pyo3::prelude::*;\n/// use pyo3::ffi::c_str;\n///\n/// # fn main() -> PyResult<()> {\n/// Python::attach(|py| -> PyResult<()> {\n///     let list = py.eval(c\"iter([1, 2, 3, 4])\", None, None)?;\n///     let numbers: PyResult<Vec<usize>> = list\n///         .try_iter()?\n///         .map(|i| i.and_then(|i|i.extract::<usize>()))\n///         .collect();\n///     let sum: usize = numbers?.iter().sum();\n///     assert_eq!(sum, 10);\n///     Ok(())\n/// })\n/// # }\n/// ```\n#[repr(transparent)]\npub struct PyIterator(PyAny);\n\npyobject_native_type_core!(\n    PyIterator,\n    |py| {\n        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        TYPE.import(py, \"collections.abc\", \"Iterator\")\n            .unwrap()\n            .as_type_ptr()\n    },\n    \"collections.abc\",\n    \"Iterator\",\n    #module=Some(\"collections.abc\"),\n    #checkfunction=ffi::PyIter_Check\n);\n\nimpl PyIterator {\n    /// Builds an iterator for an iterable Python object; the equivalent of calling `iter(obj)` in Python.\n    ///\n    /// Usually it is more convenient to write [`obj.try_iter()`][crate::types::any::PyAnyMethods::try_iter],\n    /// which is a more concise way of calling this function.\n    pub fn from_object<'py>(obj: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyIterator>> {\n        unsafe {\n            ffi::PyObject_GetIter(obj.as_ptr())\n                .assume_owned_or_err(obj.py())\n                .cast_into_unchecked()\n        }\n    }\n}\n\n/// Outcomes from sending a value into a python generator\n#[derive(Debug)]\n#[cfg(all(not(PyPy), Py_3_10))]\npub enum PySendResult<'py> {\n    /// The generator yielded a new value\n    Next(Bound<'py, PyAny>),\n    /// The generator completed, returning a (possibly None) final value\n    Return(Bound<'py, PyAny>),\n}\n\n#[cfg(all(not(PyPy), Py_3_10))]\nimpl<'py> Bound<'py, PyIterator> {\n    /// Sends a value into a python generator. This is the equivalent of calling\n    /// `generator.send(value)` in Python. This resumes the generator and continues its execution\n    /// until the next `yield` or `return` statement. When the generator completes, the (optional)\n    /// return value will be returned as `PySendResult::Return`. All subsequent calls will return\n    /// `PySendResult::Return(None)`. The first call to `send` must be made with `None` as the\n    /// argument to start the generator, failing to do so will raise a `TypeError`.\n    #[inline]\n    pub fn send(&self, value: &Bound<'py, PyAny>) -> PyResult<PySendResult<'py>> {\n        let py = self.py();\n        let mut result = std::ptr::null_mut();\n        match unsafe { ffi::PyIter_Send(self.as_ptr(), value.as_ptr(), &mut result) } {\n            ffi::PySendResult::PYGEN_ERROR => Err(PyErr::fetch(py)),\n            ffi::PySendResult::PYGEN_RETURN => Ok(PySendResult::Return(unsafe {\n                result.assume_owned_unchecked(py)\n            })),\n            ffi::PySendResult::PYGEN_NEXT => Ok(PySendResult::Next(unsafe {\n                result.assume_owned_unchecked(py)\n            })),\n        }\n    }\n}\n\nimpl<'py> Iterator for Bound<'py, PyIterator> {\n    type Item = PyResult<Bound<'py, PyAny>>;\n\n    /// Retrieves the next item from an iterator.\n    ///\n    /// Returns `None` when the iterator is exhausted.\n    /// If an exception occurs, returns `Some(Err(..))`.\n    /// Further `next()` calls after an exception occurs are likely\n    /// to repeatedly result in the same exception.\n    fn next(&mut self) -> Option<Self::Item> {\n        let py = self.py();\n        let mut item = std::ptr::null_mut();\n\n        // SAFETY: `self` is a valid iterator object, `item` is a valid pointer to receive the next item\n        match unsafe { ffi::compat::PyIter_NextItem(self.as_ptr(), &mut item) } {\n            std::ffi::c_int::MIN..=-1 => Some(Err(PyErr::fetch(py))),\n            0 => None,\n            // SAFETY: `item` is guaranteed to be a non-null strong reference\n            1..=std::ffi::c_int::MAX => Some(Ok(unsafe { item.assume_owned_unchecked(py) })),\n        }\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        match length_hint(self) {\n            Ok(hint) => (hint, None),\n            Err(e) => {\n                e.write_unraisable(self.py(), Some(self));\n                (0, None)\n            }\n        }\n    }\n}\n\n#[cfg(not(Py_LIMITED_API))]\nfn length_hint(iter: &Bound<'_, PyIterator>) -> PyResult<usize> {\n    // SAFETY: `iter` is a valid iterator object\n    let hint = unsafe { ffi::PyObject_LengthHint(iter.as_ptr(), 0) };\n    if hint < 0 {\n        Err(PyErr::fetch(iter.py()))\n    } else {\n        Ok(hint as usize)\n    }\n}\n\n/// On the limited API, we cannot use `PyObject_LengthHint`, so we fall back to calling\n/// `operator.length_hint()`, which is documented equivalent to calling `PyObject_LengthHint`.\n#[cfg(Py_LIMITED_API)]\nfn length_hint(iter: &Bound<'_, PyIterator>) -> PyResult<usize> {\n    static LENGTH_HINT: PyOnceLock<Py<PyAny>> = PyOnceLock::new();\n    let length_hint = LENGTH_HINT.import(iter.py(), \"operator\", \"length_hint\")?;\n    length_hint.call1((iter, 0))?.extract()\n}\n\nimpl<'py> IntoIterator for &Bound<'py, PyIterator> {\n    type Item = PyResult<Bound<'py, PyAny>>;\n    type IntoIter = Bound<'py, PyIterator>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.clone()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::PyIterator;\n    #[cfg(all(not(PyPy), Py_3_10))]\n    use super::PySendResult;\n    use crate::exceptions::PyTypeError;\n    #[cfg(all(not(PyPy), Py_3_10))]\n    use crate::types::PyNone;\n    use crate::types::{PyAnyMethods, PyDict, PyList, PyListMethods};\n    #[cfg(all(feature = \"macros\", Py_3_8))]\n    use crate::PyErr;\n    use crate::{IntoPyObject, PyTypeInfo, Python};\n\n    #[test]\n    fn vec_iter() {\n        Python::attach(|py| {\n            let inst = vec![10, 20].into_pyobject(py).unwrap();\n            let mut it = inst.try_iter().unwrap();\n            assert_eq!(\n                10_i32,\n                it.next().unwrap().unwrap().extract::<'_, i32>().unwrap()\n            );\n            assert_eq!(\n                20_i32,\n                it.next().unwrap().unwrap().extract::<'_, i32>().unwrap()\n            );\n            assert!(it.next().is_none());\n        });\n    }\n\n    #[test]\n    fn iter_refcnt() {\n        let (obj, count) = Python::attach(|py| {\n            let obj = vec![10, 20].into_pyobject(py).unwrap();\n            let count = obj._get_refcnt();\n            (obj.unbind(), count)\n        });\n\n        Python::attach(|py| {\n            let inst = obj.bind(py);\n            let mut it = inst.try_iter().unwrap();\n\n            assert_eq!(\n                10_i32,\n                it.next().unwrap().unwrap().extract::<'_, i32>().unwrap()\n            );\n        });\n\n        Python::attach(move |py| {\n            assert_eq!(count, obj._get_refcnt(py));\n        });\n    }\n\n    #[test]\n    fn iter_item_refcnt() {\n        Python::attach(|py| {\n            let count;\n            let obj = py.eval(c\"object()\", None, None).unwrap();\n            let list = {\n                let list = PyList::empty(py);\n                list.append(10).unwrap();\n                list.append(&obj).unwrap();\n                count = obj._get_refcnt();\n                list\n            };\n\n            {\n                let mut it = list.iter();\n\n                assert_eq!(10_i32, it.next().unwrap().extract::<'_, i32>().unwrap());\n                assert!(it.next().unwrap().is(&obj));\n                assert!(it.next().is_none());\n            }\n            assert_eq!(count, obj._get_refcnt());\n        });\n    }\n\n    #[test]\n    fn fibonacci_generator() {\n        let fibonacci_generator = cr#\"\ndef fibonacci(target):\n    a = 1\n    b = 1\n    for _ in range(target):\n        yield a\n        a, b = b, a + b\n\"#;\n\n        Python::attach(|py| {\n            let context = PyDict::new(py);\n            py.run(fibonacci_generator, None, Some(&context)).unwrap();\n\n            let generator = py.eval(c\"fibonacci(5)\", None, Some(&context)).unwrap();\n            for (actual, expected) in generator.try_iter().unwrap().zip(&[1, 1, 2, 3, 5]) {\n                let actual = actual.unwrap().extract::<usize>().unwrap();\n                assert_eq!(actual, *expected)\n            }\n        });\n    }\n\n    #[test]\n    #[cfg(all(not(PyPy), Py_3_10))]\n    fn send_generator() {\n        let generator = cr#\"\ndef gen():\n    value = None\n    while(True):\n        value = yield value\n        if value is None:\n            return\n\"#;\n\n        Python::attach(|py| {\n            let context = PyDict::new(py);\n            py.run(generator, None, Some(&context)).unwrap();\n\n            let generator = py.eval(c\"gen()\", None, Some(&context)).unwrap();\n\n            let one = 1i32.into_pyobject(py).unwrap();\n            assert!(matches!(\n                generator.try_iter().unwrap().send(&PyNone::get(py)).unwrap(),\n                PySendResult::Next(value) if value.is_none()\n            ));\n            assert!(matches!(\n                generator.try_iter().unwrap().send(&one).unwrap(),\n                PySendResult::Next(value) if value.is(&one)\n            ));\n            assert!(matches!(\n                generator.try_iter().unwrap().send(&PyNone::get(py)).unwrap(),\n                PySendResult::Return(value) if value.is_none()\n            ));\n        });\n    }\n\n    #[test]\n    fn fibonacci_generator_bound() {\n        use crate::types::any::PyAnyMethods;\n        use crate::Bound;\n\n        let fibonacci_generator = cr#\"\ndef fibonacci(target):\n    a = 1\n    b = 1\n    for _ in range(target):\n        yield a\n        a, b = b, a + b\n\"#;\n\n        Python::attach(|py| {\n            let context = PyDict::new(py);\n            py.run(fibonacci_generator, None, Some(&context)).unwrap();\n\n            let generator: Bound<'_, PyIterator> = py\n                .eval(c\"fibonacci(5)\", None, Some(&context))\n                .unwrap()\n                .cast_into()\n                .unwrap();\n            let mut items = vec![];\n            for actual in &generator {\n                let actual = actual.unwrap().extract::<usize>().unwrap();\n                items.push(actual);\n            }\n            assert_eq!(items, [1, 1, 2, 3, 5]);\n        });\n    }\n\n    #[test]\n    fn int_not_iterable() {\n        Python::attach(|py| {\n            let x = 5i32.into_pyobject(py).unwrap();\n            let err = PyIterator::from_object(&x).unwrap_err();\n\n            assert!(err.is_instance_of::<PyTypeError>(py));\n        });\n    }\n\n    #[test]\n    #[cfg(feature = \"macros\")]\n    fn python_class_not_iterator() {\n        use crate::PyErr;\n\n        #[crate::pyclass(crate = \"crate\")]\n        struct Downcaster {\n            failed: Option<PyErr>,\n        }\n\n        #[crate::pymethods(crate = \"crate\")]\n        impl Downcaster {\n            fn downcast_iterator(&mut self, obj: &crate::Bound<'_, crate::PyAny>) {\n                self.failed = Some(obj.cast::<PyIterator>().unwrap_err().into());\n            }\n        }\n\n        // Regression test for 2913\n        Python::attach(|py| {\n            let downcaster = crate::Py::new(py, Downcaster { failed: None }).unwrap();\n            crate::py_run!(\n                py,\n                downcaster,\n                r#\"\n                    from collections.abc import Sequence\n\n                    class MySequence(Sequence):\n                        def __init__(self):\n                            self._data = [1, 2, 3]\n\n                        def __getitem__(self, index):\n                            return self._data[index]\n\n                        def __len__(self):\n                            return len(self._data)\n\n                    downcaster.downcast_iterator(MySequence())\n                \"#\n            );\n\n            assert_eq!(\n                downcaster.borrow_mut(py).failed.take().unwrap().to_string(),\n                \"TypeError: 'MySequence' object is not an instance of 'Iterator'\"\n            );\n        });\n    }\n\n    #[test]\n    #[cfg(feature = \"macros\")]\n    fn python_class_iterator() {\n        #[crate::pyfunction(crate = \"crate\")]\n        fn assert_iterator(obj: &crate::Bound<'_, crate::PyAny>) {\n            assert!(obj.cast::<PyIterator>().is_ok())\n        }\n\n        // Regression test for 2913\n        Python::attach(|py| {\n            let assert_iterator = crate::wrap_pyfunction!(assert_iterator, py).unwrap();\n            crate::py_run!(\n                py,\n                assert_iterator,\n                r#\"\n                    class MyIter:\n                        def __next__(self):\n                            raise StopIteration\n\n                    assert_iterator(MyIter())\n                \"#\n            );\n        });\n    }\n\n    #[test]\n    fn length_hint_becomes_size_hint_lower_bound() {\n        Python::attach(|py| {\n            let list = py.eval(c\"[1, 2, 3]\", None, None).unwrap();\n            let iter = list.try_iter().unwrap();\n            let hint = iter.size_hint();\n            assert_eq!(hint, (3, None));\n        });\n    }\n\n    #[test]\n    #[cfg(all(feature = \"macros\", Py_3_8))]\n    fn length_hint_error() {\n        #[crate::pyfunction(crate = \"crate\")]\n        fn test_size_hint(obj: &crate::Bound<'_, crate::PyAny>, should_error: bool) {\n            let iter = obj.cast::<PyIterator>().unwrap();\n            crate::test_utils::UnraisableCapture::enter(obj.py(), |capture| {\n                assert_eq!((0, None), iter.size_hint());\n                assert_eq!(should_error, capture.take_capture().is_some());\n            });\n            assert!(PyErr::take(obj.py()).is_none());\n        }\n\n        Python::attach(|py| {\n            let test_size_hint = crate::wrap_pyfunction!(test_size_hint, py).unwrap();\n            crate::py_run!(\n                py,\n                test_size_hint,\n                r#\"\n                    class NoHintIter:\n                        def __next__(self):\n                            raise StopIteration\n\n                        def __length_hint__(self):\n                            return NotImplemented\n\n                    class ErrorHintIter:\n                        def __next__(self):\n                            raise StopIteration\n\n                        def __length_hint__(self):\n                            raise ValueError(\"bad hint impl\")\n\n                    test_size_hint(NoHintIter(), False)\n                    test_size_hint(ErrorHintIter(), True)\n                \"#\n            );\n        });\n    }\n\n    #[test]\n    fn test_type_object() {\n        Python::attach(|py| {\n            let abc = PyIterator::type_object(py);\n            let iter = py.eval(c\"iter(())\", None, None).unwrap();\n            assert!(iter.is_instance(&abc).unwrap());\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/list.rs",
    "content": "use crate::err::{self, PyResult};\nuse crate::ffi::{self, Py_ssize_t};\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::internal_tricks::get_ssize_index;\nuse crate::types::sequence::PySequenceMethods;\nuse crate::types::{PySequence, PyTuple};\nuse crate::{Borrowed, Bound, BoundObject, IntoPyObject, IntoPyObjectExt, PyAny, PyErr, Python};\nuse std::iter::FusedIterator;\n#[cfg(feature = \"nightly\")]\nuse std::num::NonZero;\n\n/// Represents a Python `list`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyList>`][crate::Py] or [`Bound<'py, PyList>`][Bound].\n///\n/// For APIs available on `list` objects, see the [`PyListMethods`] trait which is implemented for\n/// [`Bound<'py, PyList>`][Bound].\n#[repr(transparent)]\npub struct PyList(PyAny);\n\npyobject_native_type_core!(\n    PyList,\n    pyobject_native_static_type_object!(ffi::PyList_Type),\n    \"builtins\", \"list\",\n    #checkfunction=ffi::PyList_Check\n);\n\n#[cfg(Py_3_12)]\nimpl crate::impl_::pyclass::PyClassBaseType for PyList {\n    type LayoutAsBase = crate::impl_::pycell::PyVariableClassObjectBase;\n    type BaseNativeType = Self;\n    type Initializer = crate::impl_::pyclass_init::PyNativeTypeInitializer<Self>;\n    type PyClassMutability = crate::pycell::impl_::ImmutableClass;\n    type Layout<T: crate::impl_::pyclass::PyClassImpl> =\n        crate::impl_::pycell::PyVariableClassObject<T>;\n}\n\nimpl PyList {\n    /// Constructs a new list with the given elements.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyList;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let elements: Vec<i32> = vec![0, 1, 2, 3, 4, 5];\n    ///     let list = PyList::new(py, elements)?;\n    ///     assert_eq!(format!(\"{:?}\", list), \"[0, 1, 2, 3, 4, 5]\");\n    /// # Ok(())\n    /// })\n    /// # }\n    /// ```\n    ///\n    /// # Panics\n    ///\n    /// This function will panic if `element`'s [`Iterator::size_hint`] implementation is incorrect.\n    /// All standard library structures implement this trait correctly, if they do, so calling this\n    /// function with (for example) [`Vec`]`<T>` or `&[T]` will always succeed.\n    #[track_caller]\n    pub fn new<'py, T>(\n        py: Python<'py>,\n        elements: impl IntoIterator<Item = T>,\n    ) -> PyResult<Bound<'py, PyList>>\n    where\n        T: IntoPyObject<'py>,\n    {\n        let mut elements = elements.into_iter().map(|e| e.into_bound_py_any(py));\n        let (min_len, _) = elements.size_hint();\n\n        // PyList_New checks for overflow but has a bad error message, so we check ourselves\n        let len: Py_ssize_t = min_len\n            .try_into()\n            .expect(\"out of range integral type conversion attempted on `elements.len()`\");\n\n        let list = unsafe { ffi::PyList_New(len).assume_owned(py).cast_into_unchecked() };\n\n        let count = (&mut elements)\n            .take(len as usize)\n            .try_fold(0, |count, item| unsafe {\n                #[cfg(not(Py_LIMITED_API))]\n                ffi::PyList_SET_ITEM(list.as_ptr(), count, item?.into_ptr());\n                #[cfg(Py_LIMITED_API)]\n                ffi::PyList_SetItem(list.as_ptr(), count, item?.into_ptr());\n                Ok::<_, PyErr>(count + 1)\n            })?;\n\n        assert_eq!(len, count, \"Attempted to create PyList but `elements` was smaller than reported by its `size_hint` implementation.\");\n\n        elements.try_for_each(|item| list.append(item?))?;\n\n        Ok(list)\n    }\n\n    /// Constructs a new empty list.\n    pub fn empty(py: Python<'_>) -> Bound<'_, PyList> {\n        unsafe { ffi::PyList_New(0).assume_owned(py).cast_into_unchecked() }\n    }\n}\n\n/// Implementation of functionality for [`PyList`].\n///\n/// These methods are defined for the `Bound<'py, PyList>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyList\")]\npub trait PyListMethods<'py>: crate::sealed::Sealed {\n    /// Returns the length of the list.\n    fn len(&self) -> usize;\n\n    /// Checks if the list is empty.\n    fn is_empty(&self) -> bool;\n\n    /// Returns `self` cast as a `PySequence`.\n    fn as_sequence(&self) -> &Bound<'py, PySequence>;\n\n    /// Returns `self` cast as a `PySequence`.\n    fn into_sequence(self) -> Bound<'py, PySequence>;\n\n    /// Gets the list item at the specified index.\n    /// # Example\n    /// ```\n    /// use pyo3::{prelude::*, types::PyList};\n    /// Python::attach(|py| {\n    ///     let list = PyList::new(py, [2, 3, 5, 7]).unwrap();\n    ///     let obj = list.get_item(0);\n    ///     assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 2);\n    /// });\n    /// ```\n    fn get_item(&self, index: usize) -> PyResult<Bound<'py, PyAny>>;\n\n    /// Gets the list item at the specified index. Undefined behavior on bad index, or if the list\n    /// contains a null pointer at the specified index. Use with caution.\n    ///\n    /// # Safety\n    ///\n    /// - Caller must verify that the index is within the bounds of the list.\n    /// - A null pointer is only legal in a list which is in the process of being initialized, callers\n    ///   can typically assume the list item is non-null unless they are knowingly filling an\n    ///   uninitialized list. (If a list were to contain a null pointer element, accessing it from Python\n    ///   typically causes a segfault.)\n    /// - On the free-threaded build, caller must verify they have exclusive access to the list\n    ///   via a lock or by holding the innermost critical section on the list.\n    #[cfg(not(Py_LIMITED_API))]\n    unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny>;\n\n    /// Takes the slice `self[low:high]` and returns it as a new list.\n    ///\n    /// Indices must be nonnegative, and out-of-range indices are clipped to\n    /// `self.len()`.\n    fn get_slice(&self, low: usize, high: usize) -> Bound<'py, PyList>;\n\n    /// Sets the item at the specified index.\n    ///\n    /// Raises `IndexError` if the index is out of range.\n    fn set_item<I>(&self, index: usize, item: I) -> PyResult<()>\n    where\n        I: IntoPyObject<'py>;\n\n    /// Deletes the `index`th element of self.\n    ///\n    /// This is equivalent to the Python statement `del self[i]`.\n    fn del_item(&self, index: usize) -> PyResult<()>;\n\n    /// Assigns the sequence `seq` to the slice of `self` from `low` to `high`.\n    ///\n    /// This is equivalent to the Python statement `self[low:high] = v`.\n    fn set_slice(&self, low: usize, high: usize, seq: &Bound<'_, PyAny>) -> PyResult<()>;\n\n    /// Deletes the slice from `low` to `high` from `self`.\n    ///\n    /// This is equivalent to the Python statement `del self[low:high]`.\n    fn del_slice(&self, low: usize, high: usize) -> PyResult<()>;\n\n    /// Appends an item to the list.\n    fn append<I>(&self, item: I) -> PyResult<()>\n    where\n        I: IntoPyObject<'py>;\n\n    /// Inserts an item at the specified index.\n    ///\n    /// If `index >= self.len()`, inserts at the end.\n    fn insert<I>(&self, index: usize, item: I) -> PyResult<()>\n    where\n        I: IntoPyObject<'py>;\n\n    /// Determines if self contains `value`.\n    ///\n    /// This is equivalent to the Python expression `value in self`.\n    fn contains<V>(&self, value: V) -> PyResult<bool>\n    where\n        V: IntoPyObject<'py>;\n\n    /// Returns the first index `i` for which `self[i] == value`.\n    ///\n    /// This is equivalent to the Python expression `self.index(value)`.\n    fn index<V>(&self, value: V) -> PyResult<usize>\n    where\n        V: IntoPyObject<'py>;\n\n    /// Returns an iterator over this list's items.\n    fn iter(&self) -> BoundListIterator<'py>;\n\n    /// Iterates over the contents of this list while holding a critical section on the list.\n    /// This is useful when the GIL is disabled and the list is shared between threads.\n    /// It is not guaranteed that the list will not be modified during iteration when the\n    /// closure calls arbitrary Python code that releases the critical section held by the\n    /// iterator. Otherwise, the list will not be modified during iteration.\n    ///\n    /// This is equivalent to for_each if the GIL is enabled.\n    fn locked_for_each<F>(&self, closure: F) -> PyResult<()>\n    where\n        F: Fn(Bound<'py, PyAny>) -> PyResult<()>;\n\n    /// Sorts the list in-place. Equivalent to the Python expression `l.sort()`.\n    fn sort(&self) -> PyResult<()>;\n\n    /// Reverses the list in-place. Equivalent to the Python expression `l.reverse()`.\n    fn reverse(&self) -> PyResult<()>;\n\n    /// Return a new tuple containing the contents of the list; equivalent to the Python expression `tuple(list)`.\n    ///\n    /// This method is equivalent to `self.as_sequence().to_tuple()` and faster than `PyTuple::new(py, this_list)`.\n    fn to_tuple(&self) -> Bound<'py, PyTuple>;\n}\n\nimpl<'py> PyListMethods<'py> for Bound<'py, PyList> {\n    /// Returns the length of the list.\n    fn len(&self) -> usize {\n        unsafe {\n            #[cfg(not(Py_LIMITED_API))]\n            let size = ffi::PyList_GET_SIZE(self.as_ptr());\n            #[cfg(Py_LIMITED_API)]\n            let size = ffi::PyList_Size(self.as_ptr());\n\n            // non-negative Py_ssize_t should always fit into Rust usize\n            size as usize\n        }\n    }\n\n    /// Checks if the list is empty.\n    fn is_empty(&self) -> bool {\n        self.len() == 0\n    }\n\n    /// Returns `self` cast as a `PySequence`.\n    fn as_sequence(&self) -> &Bound<'py, PySequence> {\n        unsafe { self.cast_unchecked() }\n    }\n\n    /// Returns `self` cast as a `PySequence`.\n    fn into_sequence(self) -> Bound<'py, PySequence> {\n        unsafe { self.cast_into_unchecked() }\n    }\n\n    /// Gets the list item at the specified index.\n    /// # Example\n    /// ```\n    /// use pyo3::{prelude::*, types::PyList};\n    /// Python::attach(|py| {\n    ///     let list = PyList::new(py, [2, 3, 5, 7]).unwrap();\n    ///     let obj = list.get_item(0);\n    ///     assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 2);\n    /// });\n    /// ```\n    fn get_item(&self, index: usize) -> PyResult<Bound<'py, PyAny>> {\n        unsafe {\n            ffi::compat::PyList_GetItemRef(self.as_ptr(), index as Py_ssize_t)\n                .assume_owned_or_err(self.py())\n        }\n    }\n\n    /// Gets the list item at the specified index. Undefined behavior on bad index. Use with caution.\n    ///\n    /// # Safety\n    ///\n    /// Caller must verify that the index is within the bounds of the list.\n    #[cfg(not(Py_LIMITED_API))]\n    unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny> {\n        // SAFETY: caller has upheld the safety contract\n        unsafe {\n            ffi::PyList_GET_ITEM(self.as_ptr(), index as Py_ssize_t)\n                .assume_borrowed_unchecked(self.py())\n        }\n        // PyList_GET_ITEM return borrowed ptr; must make owned for safety (see #890).\n        .to_owned()\n    }\n\n    /// Takes the slice `self[low:high]` and returns it as a new list.\n    ///\n    /// Indices must be nonnegative, and out-of-range indices are clipped to\n    /// `self.len()`.\n    fn get_slice(&self, low: usize, high: usize) -> Bound<'py, PyList> {\n        unsafe {\n            ffi::PyList_GetSlice(self.as_ptr(), get_ssize_index(low), get_ssize_index(high))\n                .assume_owned(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    /// Sets the item at the specified index.\n    ///\n    /// Raises `IndexError` if the index is out of range.\n    fn set_item<I>(&self, index: usize, item: I) -> PyResult<()>\n    where\n        I: IntoPyObject<'py>,\n    {\n        fn inner(list: &Bound<'_, PyList>, index: usize, item: Bound<'_, PyAny>) -> PyResult<()> {\n            err::error_on_minusone(list.py(), unsafe {\n                ffi::PyList_SetItem(list.as_ptr(), get_ssize_index(index), item.into_ptr())\n            })\n        }\n\n        let py = self.py();\n        inner(self, index, item.into_bound_py_any(py)?)\n    }\n\n    /// Deletes the `index`th element of self.\n    ///\n    /// This is equivalent to the Python statement `del self[i]`.\n    #[inline]\n    fn del_item(&self, index: usize) -> PyResult<()> {\n        self.as_sequence().del_item(index)\n    }\n\n    /// Assigns the sequence `seq` to the slice of `self` from `low` to `high`.\n    ///\n    /// This is equivalent to the Python statement `self[low:high] = v`.\n    #[inline]\n    fn set_slice(&self, low: usize, high: usize, seq: &Bound<'_, PyAny>) -> PyResult<()> {\n        err::error_on_minusone(self.py(), unsafe {\n            ffi::PyList_SetSlice(\n                self.as_ptr(),\n                get_ssize_index(low),\n                get_ssize_index(high),\n                seq.as_ptr(),\n            )\n        })\n    }\n\n    /// Deletes the slice from `low` to `high` from `self`.\n    ///\n    /// This is equivalent to the Python statement `del self[low:high]`.\n    #[inline]\n    fn del_slice(&self, low: usize, high: usize) -> PyResult<()> {\n        self.as_sequence().del_slice(low, high)\n    }\n\n    /// Appends an item to the list.\n    fn append<I>(&self, item: I) -> PyResult<()>\n    where\n        I: IntoPyObject<'py>,\n    {\n        fn inner(list: &Bound<'_, PyList>, item: Borrowed<'_, '_, PyAny>) -> PyResult<()> {\n            err::error_on_minusone(list.py(), unsafe {\n                ffi::PyList_Append(list.as_ptr(), item.as_ptr())\n            })\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            item.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    /// Inserts an item at the specified index.\n    ///\n    /// If `index >= self.len()`, inserts at the end.\n    fn insert<I>(&self, index: usize, item: I) -> PyResult<()>\n    where\n        I: IntoPyObject<'py>,\n    {\n        fn inner(\n            list: &Bound<'_, PyList>,\n            index: usize,\n            item: Borrowed<'_, '_, PyAny>,\n        ) -> PyResult<()> {\n            err::error_on_minusone(list.py(), unsafe {\n                ffi::PyList_Insert(list.as_ptr(), get_ssize_index(index), item.as_ptr())\n            })\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            index,\n            item.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    /// Determines if self contains `value`.\n    ///\n    /// This is equivalent to the Python expression `value in self`.\n    #[inline]\n    fn contains<V>(&self, value: V) -> PyResult<bool>\n    where\n        V: IntoPyObject<'py>,\n    {\n        self.as_sequence().contains(value)\n    }\n\n    /// Returns the first index `i` for which `self[i] == value`.\n    ///\n    /// This is equivalent to the Python expression `self.index(value)`.\n    #[inline]\n    fn index<V>(&self, value: V) -> PyResult<usize>\n    where\n        V: IntoPyObject<'py>,\n    {\n        self.as_sequence().index(value)\n    }\n\n    /// Returns an iterator over this list's items.\n    fn iter(&self) -> BoundListIterator<'py> {\n        BoundListIterator::new(self.clone())\n    }\n\n    /// Iterates over a list while holding a critical section, calling a closure on each item\n    fn locked_for_each<F>(&self, closure: F) -> PyResult<()>\n    where\n        F: Fn(Bound<'py, PyAny>) -> PyResult<()>,\n    {\n        crate::sync::critical_section::with_critical_section(self, || {\n            self.iter().try_for_each(closure)\n        })\n    }\n\n    /// Sorts the list in-place. Equivalent to the Python expression `l.sort()`.\n    fn sort(&self) -> PyResult<()> {\n        err::error_on_minusone(self.py(), unsafe { ffi::PyList_Sort(self.as_ptr()) })\n    }\n\n    /// Reverses the list in-place. Equivalent to the Python expression `l.reverse()`.\n    fn reverse(&self) -> PyResult<()> {\n        err::error_on_minusone(self.py(), unsafe { ffi::PyList_Reverse(self.as_ptr()) })\n    }\n\n    /// Return a new tuple containing the contents of the list; equivalent to the Python expression `tuple(list)`.\n    ///\n    /// This method is equivalent to `self.as_sequence().to_tuple()` and faster than `PyTuple::new(py, this_list)`.\n    fn to_tuple(&self) -> Bound<'py, PyTuple> {\n        unsafe {\n            ffi::PyList_AsTuple(self.as_ptr())\n                .assume_owned(self.py())\n                .cast_into_unchecked()\n        }\n    }\n}\n\n// New types for type checking when using BoundListIterator associated methods, like\n// BoundListIterator::next_unchecked.\nstruct Index(usize);\nstruct Length(usize);\n\n/// Used by `PyList::iter()`.\npub struct BoundListIterator<'py> {\n    list: Bound<'py, PyList>,\n    index: Index,\n    length: Length,\n}\n\nimpl<'py> BoundListIterator<'py> {\n    fn new(list: Bound<'py, PyList>) -> Self {\n        Self {\n            index: Index(0),\n            length: Length(list.len()),\n            list,\n        }\n    }\n\n    /// # Safety\n    ///\n    /// On the free-threaded build, caller must verify they have exclusive\n    /// access to the list by holding a lock or by holding the innermost\n    /// critical section on the list.\n    #[inline]\n    #[cfg(not(Py_LIMITED_API))]\n    #[deny(unsafe_op_in_unsafe_fn)]\n    unsafe fn next_unchecked(\n        index: &mut Index,\n        length: &mut Length,\n        list: &Bound<'py, PyList>,\n    ) -> Option<Bound<'py, PyAny>> {\n        let length = length.0.min(list.len());\n        let my_index = index.0;\n\n        if index.0 < length {\n            let item = unsafe { list.get_item_unchecked(my_index) };\n            index.0 += 1;\n            Some(item)\n        } else {\n            None\n        }\n    }\n\n    #[cfg(Py_LIMITED_API)]\n    fn next(\n        index: &mut Index,\n        length: &mut Length,\n        list: &Bound<'py, PyList>,\n    ) -> Option<Bound<'py, PyAny>> {\n        let length = length.0.min(list.len());\n        let my_index = index.0;\n\n        if index.0 < length {\n            let item = list.get_item(my_index).expect(\"get-item failed\");\n            index.0 += 1;\n            Some(item)\n        } else {\n            None\n        }\n    }\n\n    #[inline]\n    #[cfg(not(feature = \"nightly\"))]\n    fn nth(\n        index: &mut Index,\n        length: &mut Length,\n        list: &Bound<'py, PyList>,\n        n: usize,\n    ) -> Option<Bound<'py, PyAny>> {\n        let length = length.0.min(list.len());\n        let target_index = index.0 + n;\n        if target_index < length {\n            let item = {\n                #[cfg(Py_LIMITED_API)]\n                {\n                    list.get_item(target_index).expect(\"get-item failed\")\n                }\n\n                #[cfg(not(Py_LIMITED_API))]\n                {\n                    unsafe { list.get_item_unchecked(target_index) }\n                }\n            };\n            index.0 = target_index + 1;\n            Some(item)\n        } else {\n            None\n        }\n    }\n\n    /// # Safety\n    ///\n    /// On the free-threaded build, caller must verify they have exclusive\n    /// access to the list by holding a lock or by holding the innermost\n    /// critical section on the list.\n    #[inline]\n    #[cfg(not(Py_LIMITED_API))]\n    #[deny(unsafe_op_in_unsafe_fn)]\n    unsafe fn next_back_unchecked(\n        index: &mut Index,\n        length: &mut Length,\n        list: &Bound<'py, PyList>,\n    ) -> Option<Bound<'py, PyAny>> {\n        let current_length = length.0.min(list.len());\n\n        if index.0 < current_length {\n            let item = unsafe { list.get_item_unchecked(current_length - 1) };\n            length.0 = current_length - 1;\n            Some(item)\n        } else {\n            None\n        }\n    }\n\n    #[inline]\n    #[cfg(Py_LIMITED_API)]\n    fn next_back(\n        index: &mut Index,\n        length: &mut Length,\n        list: &Bound<'py, PyList>,\n    ) -> Option<Bound<'py, PyAny>> {\n        let current_length = (length.0).min(list.len());\n\n        if index.0 < current_length {\n            let item = list.get_item(current_length - 1).expect(\"get-item failed\");\n            length.0 = current_length - 1;\n            Some(item)\n        } else {\n            None\n        }\n    }\n\n    #[inline]\n    #[cfg(not(feature = \"nightly\"))]\n    fn nth_back(\n        index: &mut Index,\n        length: &mut Length,\n        list: &Bound<'py, PyList>,\n        n: usize,\n    ) -> Option<Bound<'py, PyAny>> {\n        let length_size = length.0.min(list.len());\n        if index.0 + n < length_size {\n            let target_index = length_size - n - 1;\n            let item = {\n                #[cfg(not(Py_LIMITED_API))]\n                {\n                    unsafe { list.get_item_unchecked(target_index) }\n                }\n\n                #[cfg(Py_LIMITED_API)]\n                {\n                    list.get_item(target_index).expect(\"get-item failed\")\n                }\n            };\n            length.0 = target_index;\n            Some(item)\n        } else {\n            None\n        }\n    }\n\n    #[allow(dead_code)]\n    fn with_critical_section<R>(\n        &mut self,\n        f: impl FnOnce(&mut Index, &mut Length, &Bound<'py, PyList>) -> R,\n    ) -> R {\n        let Self {\n            index,\n            length,\n            list,\n        } = self;\n        crate::sync::critical_section::with_critical_section(list, || f(index, length, list))\n    }\n}\n\nimpl<'py> Iterator for BoundListIterator<'py> {\n    type Item = Bound<'py, PyAny>;\n\n    #[inline]\n    fn next(&mut self) -> Option<Self::Item> {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            self.with_critical_section(|index, length, list| unsafe {\n                Self::next_unchecked(index, length, list)\n            })\n        }\n        #[cfg(Py_LIMITED_API)]\n        {\n            let Self {\n                index,\n                length,\n                list,\n            } = self;\n            Self::next(index, length, list)\n        }\n    }\n\n    #[inline]\n    #[cfg(not(feature = \"nightly\"))]\n    fn nth(&mut self, n: usize) -> Option<Self::Item> {\n        self.with_critical_section(|index, length, list| Self::nth(index, length, list, n))\n    }\n\n    #[inline]\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let len = self.len();\n        (len, Some(len))\n    }\n\n    #[inline]\n    fn count(self) -> usize\n    where\n        Self: Sized,\n    {\n        self.len()\n    }\n\n    #[inline]\n    fn last(mut self) -> Option<Self::Item>\n    where\n        Self: Sized,\n    {\n        self.next_back()\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn fold<B, F>(mut self, init: B, mut f: F) -> B\n    where\n        Self: Sized,\n        F: FnMut(B, Self::Item) -> B,\n    {\n        self.with_critical_section(|index, length, list| {\n            let mut accum = init;\n            while let Some(x) = unsafe { Self::next_unchecked(index, length, list) } {\n                accum = f(accum, x);\n            }\n            accum\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, feature = \"nightly\"))]\n    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R\n    where\n        Self: Sized,\n        F: FnMut(B, Self::Item) -> R,\n        R: std::ops::Try<Output = B>,\n    {\n        self.with_critical_section(|index, length, list| {\n            let mut accum = init;\n            while let Some(x) = unsafe { Self::next_unchecked(index, length, list) } {\n                accum = f(accum, x)?\n            }\n            R::from_output(accum)\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn all<F>(&mut self, mut f: F) -> bool\n    where\n        Self: Sized,\n        F: FnMut(Self::Item) -> bool,\n    {\n        self.with_critical_section(|index, length, list| {\n            while let Some(x) = unsafe { Self::next_unchecked(index, length, list) } {\n                if !f(x) {\n                    return false;\n                }\n            }\n            true\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn any<F>(&mut self, mut f: F) -> bool\n    where\n        Self: Sized,\n        F: FnMut(Self::Item) -> bool,\n    {\n        self.with_critical_section(|index, length, list| {\n            while let Some(x) = unsafe { Self::next_unchecked(index, length, list) } {\n                if f(x) {\n                    return true;\n                }\n            }\n            false\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>\n    where\n        Self: Sized,\n        P: FnMut(&Self::Item) -> bool,\n    {\n        self.with_critical_section(|index, length, list| {\n            while let Some(x) = unsafe { Self::next_unchecked(index, length, list) } {\n                if predicate(&x) {\n                    return Some(x);\n                }\n            }\n            None\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn find_map<B, F>(&mut self, mut f: F) -> Option<B>\n    where\n        Self: Sized,\n        F: FnMut(Self::Item) -> Option<B>,\n    {\n        self.with_critical_section(|index, length, list| {\n            while let Some(x) = unsafe { Self::next_unchecked(index, length, list) } {\n                if let found @ Some(_) = f(x) {\n                    return found;\n                }\n            }\n            None\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn position<P>(&mut self, mut predicate: P) -> Option<usize>\n    where\n        Self: Sized,\n        P: FnMut(Self::Item) -> bool,\n    {\n        self.with_critical_section(|index, length, list| {\n            let mut acc = 0;\n            while let Some(x) = unsafe { Self::next_unchecked(index, length, list) } {\n                if predicate(x) {\n                    return Some(acc);\n                }\n                acc += 1;\n            }\n            None\n        })\n    }\n\n    #[inline]\n    #[cfg(feature = \"nightly\")]\n    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {\n        self.with_critical_section(|index, length, list| {\n            let max_len = length.0.min(list.len());\n            let currently_at = index.0;\n            if currently_at >= max_len {\n                if n == 0 {\n                    return Ok(());\n                } else {\n                    return Err(unsafe { NonZero::new_unchecked(n) });\n                }\n            }\n\n            let items_left = max_len - currently_at;\n            if n <= items_left {\n                index.0 += n;\n                Ok(())\n            } else {\n                index.0 = max_len;\n                let remainder = n - items_left;\n                Err(unsafe { NonZero::new_unchecked(remainder) })\n            }\n        })\n    }\n}\n\nimpl DoubleEndedIterator for BoundListIterator<'_> {\n    #[inline]\n    fn next_back(&mut self) -> Option<Self::Item> {\n        #[cfg(not(Py_LIMITED_API))]\n        {\n            self.with_critical_section(|index, length, list| unsafe {\n                Self::next_back_unchecked(index, length, list)\n            })\n        }\n        #[cfg(Py_LIMITED_API)]\n        {\n            let Self {\n                index,\n                length,\n                list,\n            } = self;\n            Self::next_back(index, length, list)\n        }\n    }\n\n    #[inline]\n    #[cfg(not(feature = \"nightly\"))]\n    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {\n        self.with_critical_section(|index, length, list| Self::nth_back(index, length, list, n))\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, not(feature = \"nightly\")))]\n    fn rfold<B, F>(mut self, init: B, mut f: F) -> B\n    where\n        Self: Sized,\n        F: FnMut(B, Self::Item) -> B,\n    {\n        self.with_critical_section(|index, length, list| {\n            let mut accum = init;\n            while let Some(x) = unsafe { Self::next_back_unchecked(index, length, list) } {\n                accum = f(accum, x);\n            }\n            accum\n        })\n    }\n\n    #[inline]\n    #[cfg(all(Py_GIL_DISABLED, feature = \"nightly\"))]\n    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R\n    where\n        Self: Sized,\n        F: FnMut(B, Self::Item) -> R,\n        R: std::ops::Try<Output = B>,\n    {\n        self.with_critical_section(|index, length, list| {\n            let mut accum = init;\n            while let Some(x) = unsafe { Self::next_back_unchecked(index, length, list) } {\n                accum = f(accum, x)?\n            }\n            R::from_output(accum)\n        })\n    }\n\n    #[inline]\n    #[cfg(feature = \"nightly\")]\n    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {\n        self.with_critical_section(|index, length, list| {\n            let max_len = length.0.min(list.len());\n            let currently_at = index.0;\n            if currently_at >= max_len {\n                if n == 0 {\n                    return Ok(());\n                } else {\n                    return Err(unsafe { NonZero::new_unchecked(n) });\n                }\n            }\n\n            let items_left = max_len - currently_at;\n            if n <= items_left {\n                length.0 = max_len - n;\n                Ok(())\n            } else {\n                length.0 = currently_at;\n                let remainder = n - items_left;\n                Err(unsafe { NonZero::new_unchecked(remainder) })\n            }\n        })\n    }\n}\n\nimpl ExactSizeIterator for BoundListIterator<'_> {\n    fn len(&self) -> usize {\n        self.length.0.saturating_sub(self.index.0)\n    }\n}\n\nimpl FusedIterator for BoundListIterator<'_> {}\n\nimpl<'py> IntoIterator for Bound<'py, PyList> {\n    type Item = Bound<'py, PyAny>;\n    type IntoIter = BoundListIterator<'py>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        BoundListIterator::new(self)\n    }\n}\n\nimpl<'py> IntoIterator for &Bound<'py, PyList> {\n    type Item = Bound<'py, PyAny>;\n    type IntoIter = BoundListIterator<'py>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.iter()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::any::PyAnyMethods;\n    use crate::types::list::PyListMethods;\n    use crate::types::sequence::PySequenceMethods;\n    use crate::types::{PyList, PyTuple};\n    use crate::{IntoPyObject, PyResult, Python};\n    #[cfg(feature = \"nightly\")]\n    use std::num::NonZero;\n\n    #[test]\n    fn test_new() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [2, 3, 5, 7]).unwrap();\n            assert_eq!(2, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert_eq!(3, list.get_item(1).unwrap().extract::<i32>().unwrap());\n            assert_eq!(5, list.get_item(2).unwrap().extract::<i32>().unwrap());\n            assert_eq!(7, list.get_item(3).unwrap().extract::<i32>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_len() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [1, 2, 3, 4]).unwrap();\n            assert_eq!(4, list.len());\n        });\n    }\n\n    #[test]\n    fn test_get_item() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [2, 3, 5, 7]).unwrap();\n            assert_eq!(2, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert_eq!(3, list.get_item(1).unwrap().extract::<i32>().unwrap());\n            assert_eq!(5, list.get_item(2).unwrap().extract::<i32>().unwrap());\n            assert_eq!(7, list.get_item(3).unwrap().extract::<i32>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_get_slice() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [2, 3, 5, 7]).unwrap();\n            let slice = list.get_slice(1, 3);\n            assert_eq!(2, slice.len());\n            let slice = list.get_slice(1, 7);\n            assert_eq!(3, slice.len());\n        });\n    }\n\n    #[test]\n    fn test_set_item() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [2, 3, 5, 7]).unwrap();\n            let val = 42i32.into_pyobject(py).unwrap();\n            let val2 = 42i32.into_pyobject(py).unwrap();\n            assert_eq!(2, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            list.set_item(0, val).unwrap();\n            assert_eq!(42, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(list.set_item(10, val2).is_err());\n        });\n    }\n\n    #[test]\n    fn test_set_item_refcnt() {\n        Python::attach(|py| {\n            let obj = py.eval(c\"object()\", None, None).unwrap();\n            let cnt;\n            {\n                let v = vec![2];\n                let ob = v.into_pyobject(py).unwrap();\n                let list = ob.cast::<PyList>().unwrap();\n                cnt = obj._get_refcnt();\n                list.set_item(0, &obj).unwrap();\n            }\n\n            assert_eq!(cnt, obj._get_refcnt());\n        });\n    }\n\n    #[test]\n    fn test_insert() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [2, 3, 5, 7]).unwrap();\n            let val = 42i32.into_pyobject(py).unwrap();\n            let val2 = 43i32.into_pyobject(py).unwrap();\n            assert_eq!(4, list.len());\n            assert_eq!(2, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            list.insert(0, val).unwrap();\n            list.insert(1000, val2).unwrap();\n            assert_eq!(6, list.len());\n            assert_eq!(42, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert_eq!(2, list.get_item(1).unwrap().extract::<i32>().unwrap());\n            assert_eq!(43, list.get_item(5).unwrap().extract::<i32>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_insert_refcnt() {\n        Python::attach(|py| {\n            let cnt;\n            let obj = py.eval(c\"object()\", None, None).unwrap();\n            {\n                let list = PyList::empty(py);\n                cnt = obj._get_refcnt();\n                list.insert(0, &obj).unwrap();\n            }\n\n            assert_eq!(cnt, obj._get_refcnt());\n        });\n    }\n\n    #[test]\n    fn test_append() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [2]).unwrap();\n            list.append(3).unwrap();\n            assert_eq!(2, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert_eq!(3, list.get_item(1).unwrap().extract::<i32>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_append_refcnt() {\n        Python::attach(|py| {\n            let cnt;\n            let obj = py.eval(c\"object()\", None, None).unwrap();\n            {\n                let list = PyList::empty(py);\n                cnt = obj._get_refcnt();\n                list.append(&obj).unwrap();\n            }\n            assert_eq!(cnt, obj._get_refcnt());\n        });\n    }\n\n    #[test]\n    fn test_iter() {\n        Python::attach(|py| {\n            let v = vec![2, 3, 5, 7];\n            let list = PyList::new(py, &v).unwrap();\n            let mut idx = 0;\n            for el in list {\n                assert_eq!(v[idx], el.extract::<i32>().unwrap());\n                idx += 1;\n            }\n            assert_eq!(idx, v.len());\n        });\n    }\n\n    #[test]\n    fn test_iter_size_hint() {\n        Python::attach(|py| {\n            let v = vec![2, 3, 5, 7];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter();\n            assert_eq!(iter.size_hint(), (v.len(), Some(v.len())));\n            iter.next();\n            assert_eq!(iter.size_hint(), (v.len() - 1, Some(v.len() - 1)));\n\n            // Exhaust iterator.\n            for _ in &mut iter {}\n\n            assert_eq!(iter.size_hint(), (0, Some(0)));\n        });\n    }\n\n    #[test]\n    fn test_iter_rev() {\n        Python::attach(|py| {\n            let v = vec![2, 3, 5, 7];\n            let ob = v.into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter().rev();\n\n            assert_eq!(iter.size_hint(), (4, Some(4)));\n\n            assert_eq!(iter.next().unwrap().extract::<i32>().unwrap(), 7);\n            assert_eq!(iter.size_hint(), (3, Some(3)));\n\n            assert_eq!(iter.next().unwrap().extract::<i32>().unwrap(), 5);\n            assert_eq!(iter.size_hint(), (2, Some(2)));\n\n            assert_eq!(iter.next().unwrap().extract::<i32>().unwrap(), 3);\n            assert_eq!(iter.size_hint(), (1, Some(1)));\n\n            assert_eq!(iter.next().unwrap().extract::<i32>().unwrap(), 2);\n            assert_eq!(iter.size_hint(), (0, Some(0)));\n\n            assert!(iter.next().is_none());\n            assert!(iter.next().is_none());\n        });\n    }\n\n    #[test]\n    fn test_iter_all() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [true, true, true]).unwrap();\n            assert!(list.iter().all(|x| x.extract::<bool>().unwrap()));\n\n            let list = PyList::new(py, [true, false, true]).unwrap();\n            assert!(!list.iter().all(|x| x.extract::<bool>().unwrap()));\n        });\n    }\n\n    #[test]\n    fn test_iter_any() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [true, true, true]).unwrap();\n            assert!(list.iter().any(|x| x.extract::<bool>().unwrap()));\n\n            let list = PyList::new(py, [true, false, true]).unwrap();\n            assert!(list.iter().any(|x| x.extract::<bool>().unwrap()));\n\n            let list = PyList::new(py, [false, false, false]).unwrap();\n            assert!(!list.iter().any(|x| x.extract::<bool>().unwrap()));\n        });\n    }\n\n    #[test]\n    fn test_iter_find() {\n        Python::attach(|py: Python<'_>| {\n            let list = PyList::new(py, [\"hello\", \"world\"]).unwrap();\n            assert_eq!(\n                Some(\"world\".to_string()),\n                list.iter()\n                    .find(|v| v.extract::<String>().unwrap() == \"world\")\n                    .map(|v| v.extract::<String>().unwrap())\n            );\n            assert_eq!(\n                None,\n                list.iter()\n                    .find(|v| v.extract::<String>().unwrap() == \"foobar\")\n                    .map(|v| v.extract::<String>().unwrap())\n            );\n        });\n    }\n\n    #[test]\n    fn test_iter_position() {\n        Python::attach(|py: Python<'_>| {\n            let list = PyList::new(py, [\"hello\", \"world\"]).unwrap();\n            assert_eq!(\n                Some(1),\n                list.iter()\n                    .position(|v| v.extract::<String>().unwrap() == \"world\")\n            );\n            assert_eq!(\n                None,\n                list.iter()\n                    .position(|v| v.extract::<String>().unwrap() == \"foobar\")\n            );\n        });\n    }\n\n    #[test]\n    fn test_iter_fold() {\n        Python::attach(|py: Python<'_>| {\n            let list = PyList::new(py, [1, 2, 3]).unwrap();\n            let sum = list\n                .iter()\n                .fold(0, |acc, v| acc + v.extract::<usize>().unwrap());\n            assert_eq!(sum, 6);\n        });\n    }\n\n    #[test]\n    fn test_iter_fold_out_of_bounds() {\n        Python::attach(|py: Python<'_>| {\n            let list = PyList::new(py, [1, 2, 3]).unwrap();\n            let sum = list.iter().fold(0, |_, _| {\n                // clear the list to create a pathological fold operation\n                // that mutates the list as it processes it\n                for _ in 0..3 {\n                    list.del_item(0).unwrap();\n                }\n                -5\n            });\n            assert_eq!(sum, -5);\n            assert_eq!(list.len(), 0);\n        });\n    }\n\n    #[test]\n    fn test_iter_rfold() {\n        Python::attach(|py: Python<'_>| {\n            let list = PyList::new(py, [1, 2, 3]).unwrap();\n            let sum = list\n                .iter()\n                .rfold(0, |acc, v| acc + v.extract::<usize>().unwrap());\n            assert_eq!(sum, 6);\n        });\n    }\n\n    #[test]\n    fn test_iter_try_fold() {\n        Python::attach(|py: Python<'_>| {\n            let list = PyList::new(py, [1, 2, 3]).unwrap();\n            let sum = list\n                .iter()\n                .try_fold(0, |acc, v| PyResult::Ok(acc + v.extract::<usize>()?))\n                .unwrap();\n            assert_eq!(sum, 6);\n\n            let list = PyList::new(py, [\"foo\", \"bar\"]).unwrap();\n            assert!(list\n                .iter()\n                .try_fold(0, |acc, v| PyResult::Ok(acc + v.extract::<usize>()?))\n                .is_err());\n        });\n    }\n\n    #[test]\n    fn test_iter_try_rfold() {\n        Python::attach(|py: Python<'_>| {\n            let list = PyList::new(py, [1, 2, 3]).unwrap();\n            let sum = list\n                .iter()\n                .try_rfold(0, |acc, v| PyResult::Ok(acc + v.extract::<usize>()?))\n                .unwrap();\n            assert_eq!(sum, 6);\n\n            let list = PyList::new(py, [\"foo\", \"bar\"]).unwrap();\n            assert!(list\n                .iter()\n                .try_rfold(0, |acc, v| PyResult::Ok(acc + v.extract::<usize>()?))\n                .is_err());\n        });\n    }\n\n    #[test]\n    fn test_into_iter() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [1, 2, 3, 4]).unwrap();\n            for (i, item) in list.iter().enumerate() {\n                assert_eq!((i + 1) as i32, item.extract::<i32>().unwrap());\n            }\n        });\n    }\n\n    #[test]\n    fn test_into_iter_bound() {\n        use crate::types::any::PyAnyMethods;\n\n        Python::attach(|py| {\n            let list = PyList::new(py, [1, 2, 3, 4]).unwrap();\n            let mut items = vec![];\n            for item in &list {\n                items.push(item.extract::<i32>().unwrap());\n            }\n            assert_eq!(items, vec![1, 2, 3, 4]);\n        });\n    }\n\n    #[test]\n    fn test_as_sequence() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [1, 2, 3, 4]).unwrap();\n\n            assert_eq!(list.as_sequence().len().unwrap(), 4);\n            assert_eq!(\n                list.as_sequence()\n                    .get_item(1)\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                2\n            );\n        });\n    }\n\n    #[test]\n    fn test_into_sequence() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [1, 2, 3, 4]).unwrap();\n\n            let sequence = list.into_sequence();\n\n            assert_eq!(sequence.len().unwrap(), 4);\n            assert_eq!(sequence.get_item(1).unwrap().extract::<i32>().unwrap(), 2);\n        });\n    }\n\n    #[test]\n    fn test_extract() {\n        Python::attach(|py| {\n            let v = vec![2, 3, 5, 7];\n            let list = PyList::new(py, &v).unwrap();\n            let v2 = list.as_any().extract::<Vec<i32>>().unwrap();\n            assert_eq!(v, v2);\n        });\n    }\n\n    #[test]\n    fn test_sort() {\n        Python::attach(|py| {\n            let v = vec![7, 3, 2, 5];\n            let list = PyList::new(py, &v).unwrap();\n            assert_eq!(7, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert_eq!(3, list.get_item(1).unwrap().extract::<i32>().unwrap());\n            assert_eq!(2, list.get_item(2).unwrap().extract::<i32>().unwrap());\n            assert_eq!(5, list.get_item(3).unwrap().extract::<i32>().unwrap());\n            list.sort().unwrap();\n            assert_eq!(2, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert_eq!(3, list.get_item(1).unwrap().extract::<i32>().unwrap());\n            assert_eq!(5, list.get_item(2).unwrap().extract::<i32>().unwrap());\n            assert_eq!(7, list.get_item(3).unwrap().extract::<i32>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_reverse() {\n        Python::attach(|py| {\n            let v = vec![2, 3, 5, 7];\n            let list = PyList::new(py, &v).unwrap();\n            assert_eq!(2, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert_eq!(3, list.get_item(1).unwrap().extract::<i32>().unwrap());\n            assert_eq!(5, list.get_item(2).unwrap().extract::<i32>().unwrap());\n            assert_eq!(7, list.get_item(3).unwrap().extract::<i32>().unwrap());\n            list.reverse().unwrap();\n            assert_eq!(7, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert_eq!(5, list.get_item(1).unwrap().extract::<i32>().unwrap());\n            assert_eq!(3, list.get_item(2).unwrap().extract::<i32>().unwrap());\n            assert_eq!(2, list.get_item(3).unwrap().extract::<i32>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_array_into_pyobject() {\n        Python::attach(|py| {\n            let array = [1, 2].into_pyobject(py).unwrap();\n            let list = array.cast::<PyList>().unwrap();\n            assert_eq!(1, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert_eq!(2, list.get_item(1).unwrap().extract::<i32>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_list_get_item_invalid_index() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [2, 3, 5, 7]).unwrap();\n            let obj = list.get_item(5);\n            assert!(obj.is_err());\n            assert_eq!(\n                obj.unwrap_err().to_string(),\n                \"IndexError: list index out of range\"\n            );\n        });\n    }\n\n    #[test]\n    fn test_list_get_item_sanity() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [2, 3, 5, 7]).unwrap();\n            let obj = list.get_item(0);\n            assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 2);\n        });\n    }\n\n    #[cfg(not(Py_LIMITED_API))]\n    #[test]\n    fn test_list_get_item_unchecked_sanity() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [2, 3, 5, 7]).unwrap();\n            let obj = unsafe { list.get_item_unchecked(0) };\n            assert_eq!(obj.extract::<i32>().unwrap(), 2);\n        });\n    }\n\n    #[test]\n    fn test_list_del_item() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [1, 1, 2, 3, 5, 8]).unwrap();\n            assert!(list.del_item(10).is_err());\n            assert_eq!(1, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(list.del_item(0).is_ok());\n            assert_eq!(1, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(list.del_item(0).is_ok());\n            assert_eq!(2, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(list.del_item(0).is_ok());\n            assert_eq!(3, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(list.del_item(0).is_ok());\n            assert_eq!(5, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(list.del_item(0).is_ok());\n            assert_eq!(8, list.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(list.del_item(0).is_ok());\n            assert_eq!(0, list.len());\n            assert!(list.del_item(0).is_err());\n        });\n    }\n\n    #[test]\n    fn test_list_set_slice() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [1, 1, 2, 3, 5, 8]).unwrap();\n            let ins = PyList::new(py, [7, 4]).unwrap();\n            list.set_slice(1, 4, &ins).unwrap();\n            assert_eq!([1, 7, 4, 5, 8], list.extract::<[i32; 5]>().unwrap());\n            list.set_slice(3, 100, &PyList::empty(py)).unwrap();\n            assert_eq!([1, 7, 4], list.extract::<[i32; 3]>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_list_del_slice() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [1, 1, 2, 3, 5, 8]).unwrap();\n            list.del_slice(1, 4).unwrap();\n            assert_eq!([1, 5, 8], list.extract::<[i32; 3]>().unwrap());\n            list.del_slice(1, 100).unwrap();\n            assert_eq!([1], list.extract::<[i32; 1]>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_list_contains() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [1, 1, 2, 3, 5, 8]).unwrap();\n            assert_eq!(6, list.len());\n\n            let bad_needle = 7i32.into_pyobject(py).unwrap();\n            assert!(!list.contains(&bad_needle).unwrap());\n\n            let good_needle = 8i32.into_pyobject(py).unwrap();\n            assert!(list.contains(&good_needle).unwrap());\n\n            let type_coerced_needle = 8f32.into_pyobject(py).unwrap();\n            assert!(list.contains(&type_coerced_needle).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_list_index() {\n        Python::attach(|py| {\n            let list = PyList::new(py, [1, 1, 2, 3, 5, 8]).unwrap();\n            assert_eq!(0, list.index(1i32).unwrap());\n            assert_eq!(2, list.index(2i32).unwrap());\n            assert_eq!(3, list.index(3i32).unwrap());\n            assert_eq!(4, list.index(5i32).unwrap());\n            assert_eq!(5, list.index(8i32).unwrap());\n            assert!(list.index(42i32).is_err());\n        });\n    }\n\n    use std::ops::Range;\n\n    // An iterator that lies about its `size_hint` implementation.\n    // See https://github.com/PyO3/pyo3/issues/2118\n    struct FaultyIter(Range<usize>, usize);\n\n    impl Iterator for FaultyIter {\n        type Item = usize;\n\n        fn next(&mut self) -> Option<Self::Item> {\n            self.0.next()\n        }\n\n        fn size_hint(&self) -> (usize, Option<usize>) {\n            (self.1, Some(self.1))\n        }\n    }\n\n    #[test]\n    #[should_panic(\n        expected = \"Attempted to create PyList but `elements` was smaller than reported by its `size_hint` implementation.\"\n    )]\n    fn too_short_iterator() {\n        Python::attach(|py| {\n            let iter = FaultyIter(0..35, 73);\n            let _list = PyList::new(py, iter).unwrap();\n        })\n    }\n\n    #[test]\n    #[should_panic(\n        expected = \"out of range integral type conversion attempted on `elements.len()`\"\n    )]\n    fn overflowing_size() {\n        Python::attach(|py| {\n            let iter = FaultyIter(0..0, usize::MAX);\n\n            let _list = PyList::new(py, iter).unwrap();\n        })\n    }\n\n    #[test]\n    #[cfg(panic = \"unwind\")]\n    fn bad_intopyobject_doesnt_cause_leaks() {\n        use crate::types::PyInt;\n        use std::convert::Infallible;\n        use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};\n        static NEEDS_DESTRUCTING_COUNT: AtomicUsize = AtomicUsize::new(0);\n\n        struct Bad(usize);\n\n        impl Drop for Bad {\n            fn drop(&mut self) {\n                NEEDS_DESTRUCTING_COUNT.fetch_sub(1, SeqCst);\n            }\n        }\n\n        impl<'py> IntoPyObject<'py> for Bad {\n            type Target = PyInt;\n            type Output = crate::Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                // This panic should not lead to a memory leak\n                assert_ne!(self.0, 42);\n                self.0.into_pyobject(py)\n            }\n        }\n\n        struct FaultyIter(Range<usize>, usize);\n\n        impl Iterator for FaultyIter {\n            type Item = Bad;\n\n            fn next(&mut self) -> Option<Self::Item> {\n                self.0.next().map(|i| {\n                    NEEDS_DESTRUCTING_COUNT.fetch_add(1, SeqCst);\n                    Bad(i)\n                })\n            }\n\n            fn size_hint(&self) -> (usize, Option<usize>) {\n                (self.1, Some(self.1))\n            }\n        }\n\n        Python::attach(|py| {\n            std::panic::catch_unwind(|| {\n                let iter = FaultyIter(0..50, 50);\n                let _list = PyList::new(py, iter).unwrap();\n            })\n            .unwrap_err();\n        });\n\n        assert_eq!(\n            NEEDS_DESTRUCTING_COUNT.load(SeqCst),\n            0,\n            \"Some destructors did not run\"\n        );\n    }\n\n    #[test]\n    fn test_list_to_tuple() {\n        Python::attach(|py| {\n            let list = PyList::new(py, vec![1, 2, 3]).unwrap();\n            let tuple = list.to_tuple();\n            let tuple_expected = PyTuple::new(py, vec![1, 2, 3]).unwrap();\n            assert!(tuple.eq(tuple_expected).unwrap());\n        })\n    }\n\n    #[test]\n    fn test_iter_nth() {\n        Python::attach(|py| {\n            let v = vec![6, 7, 8, 9, 10];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter();\n            iter.next();\n            assert_eq!(iter.nth(1).unwrap().extract::<i32>().unwrap(), 8);\n            assert_eq!(iter.nth(1).unwrap().extract::<i32>().unwrap(), 10);\n            assert!(iter.nth(1).is_none());\n\n            let v: Vec<i32> = vec![];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter();\n            iter.next();\n            assert!(iter.nth(1).is_none());\n\n            let v = vec![1, 2, 3];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter();\n            assert!(iter.nth(10).is_none());\n\n            let v = vec![6, 7, 8, 9, 10];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n            let mut iter = list.iter();\n            assert_eq!(iter.next().unwrap().extract::<i32>().unwrap(), 6);\n            assert_eq!(iter.nth(2).unwrap().extract::<i32>().unwrap(), 9);\n            assert_eq!(iter.next().unwrap().extract::<i32>().unwrap(), 10);\n\n            let mut iter = list.iter();\n            assert_eq!(iter.nth_back(1).unwrap().extract::<i32>().unwrap(), 9);\n            assert_eq!(iter.nth(2).unwrap().extract::<i32>().unwrap(), 8);\n            assert!(iter.next().is_none());\n        });\n    }\n\n    #[test]\n    fn test_iter_nth_back() {\n        Python::attach(|py| {\n            let v = vec![1, 2, 3, 4, 5];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter();\n            assert_eq!(iter.nth_back(0).unwrap().extract::<i32>().unwrap(), 5);\n            assert_eq!(iter.nth_back(1).unwrap().extract::<i32>().unwrap(), 3);\n            assert!(iter.nth_back(2).is_none());\n\n            let v: Vec<i32> = vec![];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter();\n            assert!(iter.nth_back(0).is_none());\n            assert!(iter.nth_back(1).is_none());\n\n            let v = vec![1, 2, 3];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter();\n            assert!(iter.nth_back(5).is_none());\n\n            let v = vec![1, 2, 3, 4, 5];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter();\n            iter.next_back(); // Consume the last element\n            assert_eq!(iter.nth_back(1).unwrap().extract::<i32>().unwrap(), 3);\n            assert_eq!(iter.next_back().unwrap().extract::<i32>().unwrap(), 2);\n            assert_eq!(iter.nth_back(0).unwrap().extract::<i32>().unwrap(), 1);\n\n            let v = vec![1, 2, 3, 4, 5];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter();\n            assert_eq!(iter.nth_back(1).unwrap().extract::<i32>().unwrap(), 4);\n            assert_eq!(iter.nth_back(2).unwrap().extract::<i32>().unwrap(), 1);\n\n            let mut iter2 = list.iter();\n            iter2.next_back();\n            assert_eq!(iter2.nth_back(1).unwrap().extract::<i32>().unwrap(), 3);\n            assert_eq!(iter2.next_back().unwrap().extract::<i32>().unwrap(), 2);\n\n            let mut iter3 = list.iter();\n            iter3.nth(1);\n            assert_eq!(iter3.nth_back(2).unwrap().extract::<i32>().unwrap(), 3);\n            assert!(iter3.nth_back(0).is_none());\n        });\n    }\n\n    #[cfg(feature = \"nightly\")]\n    #[test]\n    fn test_iter_advance_by() {\n        Python::attach(|py| {\n            let v = vec![1, 2, 3, 4, 5];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter();\n            assert_eq!(iter.advance_by(2), Ok(()));\n            assert_eq!(iter.next().unwrap().extract::<i32>().unwrap(), 3);\n            assert_eq!(iter.advance_by(0), Ok(()));\n            assert_eq!(iter.advance_by(100), Err(NonZero::new(98).unwrap()));\n\n            let mut iter2 = list.iter();\n            assert_eq!(iter2.advance_by(6), Err(NonZero::new(1).unwrap()));\n\n            let mut iter3 = list.iter();\n            assert_eq!(iter3.advance_by(5), Ok(()));\n\n            let mut iter4 = list.iter();\n            assert_eq!(iter4.advance_by(0), Ok(()));\n            assert_eq!(iter4.next().unwrap().extract::<i32>().unwrap(), 1);\n        })\n    }\n\n    #[cfg(feature = \"nightly\")]\n    #[test]\n    fn test_iter_advance_back_by() {\n        Python::attach(|py| {\n            let v = vec![1, 2, 3, 4, 5];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let list = ob.cast::<PyList>().unwrap();\n\n            let mut iter = list.iter();\n            assert_eq!(iter.advance_back_by(2), Ok(()));\n            assert_eq!(iter.next_back().unwrap().extract::<i32>().unwrap(), 3);\n            assert_eq!(iter.advance_back_by(0), Ok(()));\n            assert_eq!(iter.advance_back_by(100), Err(NonZero::new(98).unwrap()));\n\n            let mut iter2 = list.iter();\n            assert_eq!(iter2.advance_back_by(6), Err(NonZero::new(1).unwrap()));\n\n            let mut iter3 = list.iter();\n            assert_eq!(iter3.advance_back_by(5), Ok(()));\n\n            let mut iter4 = list.iter();\n            assert_eq!(iter4.advance_back_by(0), Ok(()));\n            assert_eq!(iter4.next_back().unwrap().extract::<i32>().unwrap(), 5);\n        })\n    }\n\n    #[test]\n    fn test_iter_last() {\n        Python::attach(|py| {\n            let list = PyList::new(py, vec![1, 2, 3]).unwrap();\n            let last = list.iter().last();\n            assert_eq!(last.unwrap().extract::<i32>().unwrap(), 3);\n        })\n    }\n\n    #[test]\n    fn test_iter_count() {\n        Python::attach(|py| {\n            let list = PyList::new(py, vec![1, 2, 3]).unwrap();\n            assert_eq!(list.iter().count(), 3);\n        })\n    }\n\n    #[test]\n    fn test_new_from_non_exact_iter() {\n        Python::attach(|py| {\n            let iter = (0..5)\n                .filter(|_| true) // Filter does not implement ExactSizeIterator\n                .map(|item| item.into_pyobject(py).unwrap());\n\n            assert!(\n                matches!(iter.size_hint(), (0, _)),\n                \"size_hint lower bound should be 0 because we do not now the final size after filter\"\n            );\n\n            let list = PyList::new(py, iter).unwrap();\n            assert_eq!(\n                list.len(),\n                5,\n                \"list should contain all elements even though size_hint is 0\"\n            );\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/mapping.rs",
    "content": "use crate::conversion::IntoPyObject;\nuse crate::err::PyResult;\nuse crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_identifier, PyStaticExpr};\nuse crate::instance::Bound;\nuse crate::py_result_ext::PyResultExt;\nuse crate::sync::PyOnceLock;\nuse crate::type_object::PyTypeInfo;\nuse crate::types::any::PyAnyMethods;\nuse crate::types::{PyAny, PyDict, PyList, PyType, PyTypeMethods};\nuse crate::{ffi, Py, Python};\n\n/// Represents a reference to a Python object supporting the mapping protocol.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyMapping>`][crate::Py] or [`Bound<'py, PyMapping>`][Bound].\n///\n/// For APIs available on mapping objects, see the [`PyMappingMethods`] trait which is implemented for\n/// [`Bound<'py, PyMapping>`][Bound].\n#[repr(transparent)]\npub struct PyMapping(PyAny);\n\npyobject_native_type_named!(PyMapping);\n\nunsafe impl PyTypeInfo for PyMapping {\n    const NAME: &'static str = \"Mapping\";\n    const MODULE: Option<&'static str> = Some(\"collections.abc\");\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const TYPE_HINT: PyStaticExpr = type_hint_identifier!(\"collections.abc\", \"Mapping\");\n\n    #[inline]\n    #[allow(clippy::redundant_closure_call)]\n    fn type_object_raw(py: Python<'_>) -> *mut ffi::PyTypeObject {\n        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        TYPE.import(py, \"collections.abc\", \"Mapping\")\n            .unwrap()\n            .as_type_ptr()\n    }\n\n    #[inline]\n    fn is_type_of(object: &Bound<'_, PyAny>) -> bool {\n        // Using `is_instance` for `collections.abc.Mapping` is slow, so provide\n        // optimized case dict as a well-known mapping\n        PyDict::is_type_of(object)\n            || object\n                .is_instance(&Self::type_object(object.py()).into_any())\n                .unwrap_or_else(|err| {\n                    err.write_unraisable(object.py(), Some(object));\n                    false\n                })\n    }\n}\n\nimpl PyMapping {\n    /// Register a pyclass as a subclass of `collections.abc.Mapping` (from the Python standard\n    /// library). This is equivalent to `collections.abc.Mapping.register(T)` in Python.\n    /// This registration is required for a pyclass to be castable from `PyAny` to `PyMapping`.\n    pub fn register<T: PyTypeInfo>(py: Python<'_>) -> PyResult<()> {\n        let ty = T::type_object(py);\n        Self::type_object(py).call_method1(\"register\", (ty,))?;\n        Ok(())\n    }\n}\n\n/// Implementation of functionality for [`PyMapping`].\n///\n/// These methods are defined for the `Bound<'py, PyMapping>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyMapping\")]\npub trait PyMappingMethods<'py>: crate::sealed::Sealed {\n    /// Returns the number of objects in the mapping.\n    ///\n    /// This is equivalent to the Python expression `len(self)`.\n    fn len(&self) -> PyResult<usize>;\n\n    /// Returns whether the mapping is empty.\n    fn is_empty(&self) -> PyResult<bool>;\n\n    /// Determines if the mapping contains the specified key.\n    ///\n    /// This is equivalent to the Python expression `key in self`.\n    fn contains<K>(&self, key: K) -> PyResult<bool>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Gets the item in self with key `key`.\n    ///\n    /// Returns an `Err` if the item with specified key is not found, usually `KeyError`.\n    ///\n    /// This is equivalent to the Python expression `self[key]`.\n    fn get_item<K>(&self, key: K) -> PyResult<Bound<'py, PyAny>>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Sets the item in self with key `key`.\n    ///\n    /// This is equivalent to the Python expression `self[key] = value`.\n    fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>,\n        V: IntoPyObject<'py>;\n\n    /// Deletes the item with key `key`.\n    ///\n    /// This is equivalent to the Python statement `del self[key]`.\n    fn del_item<K>(&self, key: K) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Returns a list containing all keys in the mapping.\n    fn keys(&self) -> PyResult<Bound<'py, PyList>>;\n\n    /// Returns a list containing all values in the mapping.\n    fn values(&self) -> PyResult<Bound<'py, PyList>>;\n\n    /// Returns a list of all (key, value) pairs in the mapping.\n    fn items(&self) -> PyResult<Bound<'py, PyList>>;\n}\n\nimpl<'py> PyMappingMethods<'py> for Bound<'py, PyMapping> {\n    #[inline]\n    fn len(&self) -> PyResult<usize> {\n        let v = unsafe { ffi::PyMapping_Size(self.as_ptr()) };\n        crate::err::error_on_minusone(self.py(), v)?;\n        Ok(v as usize)\n    }\n\n    #[inline]\n    fn is_empty(&self) -> PyResult<bool> {\n        self.len().map(|l| l == 0)\n    }\n\n    fn contains<K>(&self, key: K) -> PyResult<bool>\n    where\n        K: IntoPyObject<'py>,\n    {\n        PyAnyMethods::contains(&**self, key)\n    }\n\n    #[inline]\n    fn get_item<K>(&self, key: K) -> PyResult<Bound<'py, PyAny>>\n    where\n        K: IntoPyObject<'py>,\n    {\n        PyAnyMethods::get_item(&**self, key)\n    }\n\n    #[inline]\n    fn set_item<K, V>(&self, key: K, value: V) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>,\n        V: IntoPyObject<'py>,\n    {\n        PyAnyMethods::set_item(&**self, key, value)\n    }\n\n    #[inline]\n    fn del_item<K>(&self, key: K) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>,\n    {\n        PyAnyMethods::del_item(&**self, key)\n    }\n\n    #[inline]\n    fn keys(&self) -> PyResult<Bound<'py, PyList>> {\n        unsafe {\n            ffi::PyMapping_Keys(self.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    #[inline]\n    fn values(&self) -> PyResult<Bound<'py, PyList>> {\n        unsafe {\n            ffi::PyMapping_Values(self.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    #[inline]\n    fn items(&self) -> PyResult<Bound<'py, PyList>> {\n        unsafe {\n            ffi::PyMapping_Items(self.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::collections::HashMap;\n\n    use crate::{exceptions::PyKeyError, types::PyTuple};\n\n    use super::*;\n    use crate::conversion::IntoPyObject;\n\n    #[test]\n    fn test_len() {\n        Python::attach(|py| {\n            let mut v = HashMap::<i32, i32>::new();\n            let ob = (&v).into_pyobject(py).unwrap();\n            let mapping = ob.cast::<PyMapping>().unwrap();\n            assert_eq!(0, mapping.len().unwrap());\n            assert!(mapping.is_empty().unwrap());\n\n            v.insert(7, 32);\n            let ob = v.into_pyobject(py).unwrap();\n            let mapping2 = ob.cast::<PyMapping>().unwrap();\n            assert_eq!(1, mapping2.len().unwrap());\n            assert!(!mapping2.is_empty().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_contains() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(\"key0\", 1234);\n            let ob = v.into_pyobject(py).unwrap();\n            let mapping = ob.cast::<PyMapping>().unwrap();\n            mapping.set_item(\"key1\", \"foo\").unwrap();\n\n            assert!(mapping.contains(\"key0\").unwrap());\n            assert!(mapping.contains(\"key1\").unwrap());\n            assert!(!mapping.contains(\"key2\").unwrap());\n        });\n    }\n\n    #[test]\n    fn test_get_item() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            let ob = v.into_pyobject(py).unwrap();\n            let mapping = ob.cast::<PyMapping>().unwrap();\n            assert_eq!(\n                32,\n                mapping.get_item(7i32).unwrap().extract::<i32>().unwrap()\n            );\n            assert!(mapping\n                .get_item(8i32)\n                .unwrap_err()\n                .is_instance_of::<PyKeyError>(py));\n        });\n    }\n\n    #[test]\n    fn test_set_item() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            let ob = v.into_pyobject(py).unwrap();\n            let mapping = ob.cast::<PyMapping>().unwrap();\n            assert!(mapping.set_item(7i32, 42i32).is_ok()); // change\n            assert!(mapping.set_item(8i32, 123i32).is_ok()); // insert\n            assert_eq!(\n                42i32,\n                mapping.get_item(7i32).unwrap().extract::<i32>().unwrap()\n            );\n            assert_eq!(\n                123i32,\n                mapping.get_item(8i32).unwrap().extract::<i32>().unwrap()\n            );\n        });\n    }\n\n    #[test]\n    fn test_del_item() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            let ob = v.into_pyobject(py).unwrap();\n            let mapping = ob.cast::<PyMapping>().unwrap();\n            assert!(mapping.del_item(7i32).is_ok());\n            assert_eq!(0, mapping.len().unwrap());\n            assert!(mapping\n                .get_item(7i32)\n                .unwrap_err()\n                .is_instance_of::<PyKeyError>(py));\n        });\n    }\n\n    #[test]\n    fn test_items() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let ob = v.into_pyobject(py).unwrap();\n            let mapping = ob.cast::<PyMapping>().unwrap();\n            // Can't just compare against a vector of tuples since we don't have a guaranteed ordering.\n            let mut key_sum = 0;\n            let mut value_sum = 0;\n            for el in mapping.items().unwrap().try_iter().unwrap() {\n                let tuple = el.unwrap().cast_into::<PyTuple>().unwrap();\n                key_sum += tuple.get_item(0).unwrap().extract::<i32>().unwrap();\n                value_sum += tuple.get_item(1).unwrap().extract::<i32>().unwrap();\n            }\n            assert_eq!(7 + 8 + 9, key_sum);\n            assert_eq!(32 + 42 + 123, value_sum);\n        });\n    }\n\n    #[test]\n    fn test_keys() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let ob = v.into_pyobject(py).unwrap();\n            let mapping = ob.cast::<PyMapping>().unwrap();\n            // Can't just compare against a vector of tuples since we don't have a guaranteed ordering.\n            let mut key_sum = 0;\n            for el in mapping.keys().unwrap().try_iter().unwrap() {\n                key_sum += el.unwrap().extract::<i32>().unwrap();\n            }\n            assert_eq!(7 + 8 + 9, key_sum);\n        });\n    }\n\n    #[test]\n    fn test_values() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let ob = v.into_pyobject(py).unwrap();\n            let mapping = ob.cast::<PyMapping>().unwrap();\n            // Can't just compare against a vector of tuples since we don't have a guaranteed ordering.\n            let mut values_sum = 0;\n            for el in mapping.values().unwrap().try_iter().unwrap() {\n                values_sum += el.unwrap().extract::<i32>().unwrap();\n            }\n            assert_eq!(32 + 42 + 123, values_sum);\n        });\n    }\n\n    #[test]\n    fn test_type_object() {\n        Python::attach(|py| {\n            let abc = PyMapping::type_object(py);\n            assert!(PyDict::new(py).is_instance(&abc).unwrap());\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/mappingproxy.rs",
    "content": "// Copyright (c) 2017-present PyO3 Project and Contributors\n\nuse super::PyMapping;\nuse crate::err::PyResult;\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::instance::Bound;\nuse crate::types::any::PyAnyMethods;\nuse crate::types::{PyAny, PyIterator, PyList};\nuse crate::{ffi, Python};\n\n/// Represents a Python `mappingproxy`.\n#[repr(transparent)]\npub struct PyMappingProxy(PyAny);\n\npyobject_native_type_core!(\n    PyMappingProxy,\n    pyobject_native_static_type_object!(ffi::PyDictProxy_Type),\n    \"types\",\n    \"MappingProxyType\"\n);\n\nimpl PyMappingProxy {\n    /// Creates a mappingproxy from an object.\n    pub fn new<'py>(\n        py: Python<'py>,\n        elements: &Bound<'py, PyMapping>,\n    ) -> Bound<'py, PyMappingProxy> {\n        unsafe {\n            ffi::PyDictProxy_New(elements.as_ptr())\n                .assume_owned(py)\n                .cast_into_unchecked()\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyMappingProxy`].\n///\n/// These methods are defined for the `Bound<'py, PyMappingProxy>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyMappingProxy\")]\npub trait PyMappingProxyMethods<'py, 'a>: crate::sealed::Sealed {\n    /// Checks if the mappingproxy is empty, i.e. `len(self) == 0`.\n    fn is_empty(&self) -> PyResult<bool>;\n\n    /// Returns a list containing all keys in the mapping.\n    fn keys(&self) -> PyResult<Bound<'py, PyList>>;\n\n    /// Returns a list containing all values in the mapping.\n    fn values(&self) -> PyResult<Bound<'py, PyList>>;\n\n    /// Returns a list of tuples of all (key, value) pairs in the mapping.\n    fn items(&self) -> PyResult<Bound<'py, PyList>>;\n\n    /// Returns `self` cast as a `PyMapping`.\n    fn as_mapping(&self) -> &Bound<'py, PyMapping>;\n\n    /// Takes an object and returns an iterator for it. Returns an error if the object is not\n    /// iterable.\n    fn try_iter(&'a self) -> PyResult<BoundMappingProxyIterator<'py, 'a>>;\n}\n\nimpl<'py, 'a> PyMappingProxyMethods<'py, 'a> for Bound<'py, PyMappingProxy> {\n    fn is_empty(&self) -> PyResult<bool> {\n        Ok(self.len()? == 0)\n    }\n\n    #[inline]\n    fn keys(&self) -> PyResult<Bound<'py, PyList>> {\n        unsafe {\n            Ok(ffi::PyMapping_Keys(self.as_ptr())\n                .assume_owned_or_err(self.py())?\n                .cast_into_unchecked())\n        }\n    }\n\n    #[inline]\n    fn values(&self) -> PyResult<Bound<'py, PyList>> {\n        unsafe {\n            Ok(ffi::PyMapping_Values(self.as_ptr())\n                .assume_owned_or_err(self.py())?\n                .cast_into_unchecked())\n        }\n    }\n\n    #[inline]\n    fn items(&self) -> PyResult<Bound<'py, PyList>> {\n        unsafe {\n            Ok(ffi::PyMapping_Items(self.as_ptr())\n                .assume_owned_or_err(self.py())?\n                .cast_into_unchecked())\n        }\n    }\n\n    fn as_mapping(&self) -> &Bound<'py, PyMapping> {\n        unsafe { self.cast_unchecked() }\n    }\n\n    fn try_iter(&'a self) -> PyResult<BoundMappingProxyIterator<'py, 'a>> {\n        Ok(BoundMappingProxyIterator {\n            iterator: PyIterator::from_object(self)?,\n            mappingproxy: self,\n        })\n    }\n}\n\npub struct BoundMappingProxyIterator<'py, 'a> {\n    iterator: Bound<'py, PyIterator>,\n    mappingproxy: &'a Bound<'py, PyMappingProxy>,\n}\n\nimpl<'py> Iterator for BoundMappingProxyIterator<'py, '_> {\n    type Item = PyResult<(Bound<'py, PyAny>, Bound<'py, PyAny>)>;\n\n    #[inline]\n    fn next(&mut self) -> Option<Self::Item> {\n        self.iterator.next().map(|key| match key {\n            Ok(key) => match self.mappingproxy.get_item(&key) {\n                Ok(value) => Ok((key, value)),\n                Err(e) => Err(e),\n            },\n            Err(e) => Err(e),\n        })\n    }\n}\n\n#[cfg(test)]\nmod tests {\n\n    use super::*;\n    use crate::types::dict::*;\n    use crate::Python;\n    use crate::{\n        exceptions::PyKeyError,\n        types::{PyInt, PyTuple},\n    };\n    use std::collections::{BTreeMap, HashMap};\n\n    #[test]\n    fn test_new() {\n        Python::attach(|py| {\n            let pydict = [(7, 32)].into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, pydict.as_mapping());\n            mappingproxy.get_item(7i32).unwrap();\n            assert_eq!(\n                32,\n                mappingproxy\n                    .get_item(7i32)\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n            );\n            assert!(mappingproxy\n                .get_item(8i32)\n                .unwrap_err()\n                .is_instance_of::<PyKeyError>(py));\n        });\n    }\n\n    #[test]\n    fn test_len() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            let dict = v.clone().into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n            assert_eq!(mappingproxy.len().unwrap(), 0);\n            v.insert(7, 32);\n            let dict2 = v.clone().into_py_dict(py).unwrap();\n            let mp2 = PyMappingProxy::new(py, dict2.as_mapping());\n            assert_eq!(mp2.len().unwrap(), 1);\n        });\n    }\n\n    #[test]\n    fn test_contains() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            let dict = v.clone().into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n            assert!(mappingproxy.contains(7i32).unwrap());\n            assert!(!mappingproxy.contains(8i32).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_get_item() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            let dict = v.clone().into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n            assert_eq!(\n                32,\n                mappingproxy\n                    .get_item(7i32)\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap()\n            );\n            assert!(mappingproxy\n                .get_item(8i32)\n                .unwrap_err()\n                .is_instance_of::<PyKeyError>(py));\n        });\n    }\n\n    #[test]\n    fn test_set_item_refcnt() {\n        Python::attach(|py| {\n            let cnt;\n            {\n                let none = py.None();\n                cnt = none._get_refcnt(py);\n                let dict = [(10, none)].into_py_dict(py).unwrap();\n                let _mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n            }\n            {\n                assert_eq!(cnt, py.None()._get_refcnt(py));\n            }\n        });\n    }\n\n    #[test]\n    fn test_isempty() {\n        Python::attach(|py| {\n            let map: HashMap<usize, usize> = HashMap::new();\n            let dict = map.into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n            assert!(mappingproxy.is_empty().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_keys() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let dict = v.into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n            // Can't just compare against a vector of tuples since we don't have a guaranteed ordering.\n            let mut key_sum = 0;\n            for el in mappingproxy.keys().unwrap().try_iter().unwrap() {\n                key_sum += el.unwrap().extract::<i32>().unwrap();\n            }\n            assert_eq!(7 + 8 + 9, key_sum);\n        });\n    }\n\n    #[test]\n    fn test_values() {\n        Python::attach(|py| {\n            let mut v: HashMap<i32, i32> = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let dict = v.into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n            // Can't just compare against a vector of tuples since we don't have a guaranteed ordering.\n            let mut values_sum = 0;\n            for el in mappingproxy.values().unwrap().try_iter().unwrap() {\n                values_sum += el.unwrap().extract::<i32>().unwrap();\n            }\n            assert_eq!(32 + 42 + 123, values_sum);\n        });\n    }\n\n    #[test]\n    fn test_items() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let dict = v.into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n            // Can't just compare against a vector of tuples since we don't have a guaranteed ordering.\n            let mut key_sum = 0;\n            let mut value_sum = 0;\n            for res in mappingproxy.items().unwrap().try_iter().unwrap() {\n                let el = res.unwrap();\n                let tuple = el.cast::<PyTuple>().unwrap();\n                key_sum += tuple.get_item(0).unwrap().extract::<i32>().unwrap();\n                value_sum += tuple.get_item(1).unwrap().extract::<i32>().unwrap();\n            }\n            assert_eq!(7 + 8 + 9, key_sum);\n            assert_eq!(32 + 42 + 123, value_sum);\n        });\n    }\n\n    #[test]\n    fn test_iter() {\n        Python::attach(|py| {\n            let mut v = HashMap::new();\n            v.insert(7, 32);\n            v.insert(8, 42);\n            v.insert(9, 123);\n            let dict = v.into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n            let mut key_sum = 0;\n            let mut value_sum = 0;\n            for res in mappingproxy.try_iter().unwrap() {\n                let (key, value) = res.unwrap();\n                key_sum += key.extract::<i32>().unwrap();\n                value_sum += value.extract::<i32>().unwrap();\n            }\n            assert_eq!(7 + 8 + 9, key_sum);\n            assert_eq!(32 + 42 + 123, value_sum);\n        });\n    }\n\n    #[test]\n    fn test_hashmap_into_python() {\n        Python::attach(|py| {\n            let mut map = HashMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let dict = map.clone().into_py_dict(py).unwrap();\n            let py_map = PyMappingProxy::new(py, dict.as_mapping());\n\n            assert_eq!(py_map.len().unwrap(), 1);\n            assert_eq!(py_map.get_item(1).unwrap().extract::<i32>().unwrap(), 1);\n        });\n    }\n\n    #[test]\n    fn test_hashmap_into_mappingproxy() {\n        Python::attach(|py| {\n            let mut map = HashMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let dict = map.clone().into_py_dict(py).unwrap();\n            let py_map = PyMappingProxy::new(py, dict.as_mapping());\n\n            assert_eq!(py_map.len().unwrap(), 1);\n            assert_eq!(py_map.get_item(1).unwrap().extract::<i32>().unwrap(), 1);\n        });\n    }\n\n    #[test]\n    fn test_btreemap_into_py() {\n        Python::attach(|py| {\n            let mut map = BTreeMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let dict = map.clone().into_py_dict(py).unwrap();\n            let py_map = PyMappingProxy::new(py, dict.as_mapping());\n\n            assert_eq!(py_map.len().unwrap(), 1);\n            assert_eq!(py_map.get_item(1).unwrap().extract::<i32>().unwrap(), 1);\n        });\n    }\n\n    #[test]\n    fn test_btreemap_into_mappingproxy() {\n        Python::attach(|py| {\n            let mut map = BTreeMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let dict = map.clone().into_py_dict(py).unwrap();\n            let py_map = PyMappingProxy::new(py, dict.as_mapping());\n\n            assert_eq!(py_map.len().unwrap(), 1);\n            assert_eq!(py_map.get_item(1).unwrap().extract::<i32>().unwrap(), 1);\n        });\n    }\n\n    #[test]\n    fn test_vec_into_mappingproxy() {\n        Python::attach(|py| {\n            let vec = vec![(\"a\", 1), (\"b\", 2), (\"c\", 3)];\n            let dict = vec.clone().into_py_dict(py).unwrap();\n            let py_map = PyMappingProxy::new(py, dict.as_mapping());\n\n            assert_eq!(py_map.len().unwrap(), 3);\n            assert_eq!(py_map.get_item(\"b\").unwrap().extract::<i32>().unwrap(), 2);\n        });\n    }\n\n    #[test]\n    fn test_slice_into_mappingproxy() {\n        Python::attach(|py| {\n            let arr = [(\"a\", 1), (\"b\", 2), (\"c\", 3)];\n\n            let dict = arr.into_py_dict(py).unwrap();\n            let py_map = PyMappingProxy::new(py, dict.as_mapping());\n\n            assert_eq!(py_map.len().unwrap(), 3);\n            assert_eq!(py_map.get_item(\"b\").unwrap().extract::<i32>().unwrap(), 2);\n        });\n    }\n\n    #[test]\n    fn mappingproxy_as_mapping() {\n        Python::attach(|py| {\n            let mut map = HashMap::<i32, i32>::new();\n            map.insert(1, 1);\n\n            let dict = map.clone().into_py_dict(py).unwrap();\n            let py_map = PyMappingProxy::new(py, dict.as_mapping());\n\n            assert_eq!(py_map.as_mapping().len().unwrap(), 1);\n            assert_eq!(\n                py_map\n                    .as_mapping()\n                    .get_item(1)\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                1\n            );\n        });\n    }\n\n    #[cfg(not(any(PyPy, GraalPy)))]\n    fn abc_mappingproxy(py: Python<'_>) -> Bound<'_, PyMappingProxy> {\n        let mut map = HashMap::<&'static str, i32>::new();\n        map.insert(\"a\", 1);\n        map.insert(\"b\", 2);\n        map.insert(\"c\", 3);\n        let dict = map.clone().into_py_dict(py).unwrap();\n        PyMappingProxy::new(py, dict.as_mapping())\n    }\n\n    #[test]\n    #[cfg(not(any(PyPy, GraalPy)))]\n    fn mappingproxy_keys_view() {\n        Python::attach(|py| {\n            let mappingproxy = abc_mappingproxy(py);\n            let keys = mappingproxy.call_method0(\"keys\").unwrap();\n            assert!(keys.is_instance(&py.get_type::<PyDictKeys>()).unwrap());\n        })\n    }\n\n    #[test]\n    #[cfg(not(any(PyPy, GraalPy)))]\n    fn mappingproxy_values_view() {\n        Python::attach(|py| {\n            let mappingproxy = abc_mappingproxy(py);\n            let values = mappingproxy.call_method0(\"values\").unwrap();\n            assert!(values.is_instance(&py.get_type::<PyDictValues>()).unwrap());\n        })\n    }\n\n    #[test]\n    #[cfg(not(any(PyPy, GraalPy)))]\n    fn mappingproxy_items_view() {\n        Python::attach(|py| {\n            let mappingproxy = abc_mappingproxy(py);\n            let items = mappingproxy.call_method0(\"items\").unwrap();\n            assert!(items.is_instance(&py.get_type::<PyDictItems>()).unwrap());\n        })\n    }\n\n    #[test]\n    fn get_value_from_mappingproxy_of_strings() {\n        Python::attach(|py: Python<'_>| {\n            let mut map = HashMap::new();\n            map.insert(\"first key\".to_string(), \"first value\".to_string());\n            map.insert(\"second key\".to_string(), \"second value\".to_string());\n            map.insert(\"third key\".to_string(), \"third value\".to_string());\n\n            let dict = map.clone().into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n\n            assert_eq!(\n                map.into_iter().collect::<Vec<(String, String)>>(),\n                mappingproxy\n                    .try_iter()\n                    .unwrap()\n                    .map(|object| {\n                        let tuple = object.unwrap();\n                        (\n                            tuple.0.extract::<String>().unwrap(),\n                            tuple.1.extract::<String>().unwrap(),\n                        )\n                    })\n                    .collect::<Vec<(String, String)>>()\n            );\n        })\n    }\n\n    #[test]\n    fn get_value_from_mappingproxy_of_integers() {\n        Python::attach(|py: Python<'_>| {\n            const LEN: usize = 10_000;\n            let items: Vec<(usize, usize)> = (1..LEN).map(|i| (i, i - 1)).collect();\n\n            let dict = items.clone().into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n\n            assert_eq!(\n                items,\n                mappingproxy\n                    .clone()\n                    .try_iter()\n                    .unwrap()\n                    .map(|object| {\n                        let tuple = object.unwrap();\n                        (\n                            tuple.0.cast::<PyInt>().unwrap().extract::<usize>().unwrap(),\n                            tuple.1.cast::<PyInt>().unwrap().extract::<usize>().unwrap(),\n                        )\n                    })\n                    .collect::<Vec<(usize, usize)>>()\n            );\n            for index in 1..LEN {\n                assert_eq!(\n                    mappingproxy\n                        .clone()\n                        .get_item(index)\n                        .unwrap()\n                        .extract::<usize>()\n                        .unwrap(),\n                    index - 1\n                );\n            }\n        })\n    }\n\n    #[test]\n    fn iter_mappingproxy_nosegv() {\n        Python::attach(|py| {\n            const LEN: usize = 1_000;\n            let items = (0..LEN as u64).map(|i| (i, i * 2));\n\n            let dict = items.clone().into_py_dict(py).unwrap();\n            let mappingproxy = PyMappingProxy::new(py, dict.as_mapping());\n\n            let mut sum = 0;\n            for result in mappingproxy.try_iter().unwrap() {\n                let (k, _v) = result.unwrap();\n                let i: u64 = k.extract().unwrap();\n                sum += i;\n            }\n            assert_eq!(sum, 499_500);\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/memoryview.rs",
    "content": "use crate::err::PyResult;\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::py_result_ext::PyResultExt;\nuse crate::{ffi, Bound, PyAny};\n\n/// Represents a Python `memoryview`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyMemoryView>`][crate::Py] or [`Bound<'py, PyMemoryView>`][Bound].\n#[repr(transparent)]\npub struct PyMemoryView(PyAny);\n\npyobject_native_type_core!(PyMemoryView, pyobject_native_static_type_object!(ffi::PyMemoryView_Type), \"builtins\", \"memoryview\", #checkfunction=ffi::PyMemoryView_Check);\n\nimpl PyMemoryView {\n    /// Creates a new Python `memoryview` object from another Python object that\n    /// implements the buffer protocol.\n    pub fn from<'py>(src: &Bound<'py, PyAny>) -> PyResult<Bound<'py, Self>> {\n        unsafe {\n            ffi::PyMemoryView_FromObject(src.as_ptr())\n                .assume_owned_or_err(src.py())\n                .cast_into_unchecked()\n        }\n    }\n}\n\nimpl<'py> TryFrom<&Bound<'py, PyAny>> for Bound<'py, PyMemoryView> {\n    type Error = crate::PyErr;\n\n    /// Creates a new Python `memoryview` object from another Python object that\n    /// implements the buffer protocol.\n    fn try_from(value: &Bound<'py, PyAny>) -> Result<Self, Self::Error> {\n        PyMemoryView::from(value)\n    }\n}\n"
  },
  {
    "path": "src/types/mod.rs",
    "content": "//! Various types defined by the Python interpreter such as `int`, `str` and `tuple`.\n\npub use self::any::{PyAny, PyAnyMethods};\npub use self::boolobject::{PyBool, PyBoolMethods};\npub use self::bytearray::{PyByteArray, PyByteArrayMethods};\npub use self::bytes::{PyBytes, PyBytesMethods};\npub use self::capsule::{CapsuleName, PyCapsule, PyCapsuleMethods};\npub use self::code::{PyCode, PyCodeInput, PyCodeMethods};\npub use self::complex::{PyComplex, PyComplexMethods};\npub use self::datetime::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo, PyTzInfoAccess};\n#[cfg(not(Py_LIMITED_API))]\npub use self::datetime::{PyDateAccess, PyDeltaAccess, PyTimeAccess};\npub use self::dict::{IntoPyDict, PyDict, PyDictMethods};\n#[cfg(not(any(PyPy, GraalPy)))]\npub use self::dict::{PyDictItems, PyDictKeys, PyDictValues};\npub use self::ellipsis::PyEllipsis;\npub use self::float::{PyFloat, PyFloatMethods};\n#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]\npub use self::frame::{PyFrame, PyFrameMethods};\npub use self::frozenset::{PyFrozenSet, PyFrozenSetBuilder, PyFrozenSetMethods};\npub use self::function::PyCFunction;\n#[cfg(not(Py_LIMITED_API))]\npub use self::function::PyFunction;\n#[cfg(Py_3_9)]\npub use self::genericalias::PyGenericAlias;\npub use self::iterator::PyIterator;\n#[cfg(all(not(PyPy), Py_3_10))]\npub use self::iterator::PySendResult;\npub use self::list::{PyList, PyListMethods};\npub use self::mapping::{PyMapping, PyMappingMethods};\npub use self::mappingproxy::PyMappingProxy;\npub use self::memoryview::PyMemoryView;\npub use self::module::{PyModule, PyModuleMethods};\n#[cfg(all(not(Py_LIMITED_API), Py_3_13))]\npub use self::mutex::{PyMutex, PyMutexGuard};\npub use self::none::PyNone;\npub use self::notimplemented::PyNotImplemented;\npub use self::num::PyInt;\npub use self::pysuper::PySuper;\npub use self::range::{PyRange, PyRangeMethods};\npub use self::sequence::{PySequence, PySequenceMethods};\npub use self::set::{PySet, PySetMethods};\npub use self::slice::{PySlice, PySliceIndices, PySliceMethods};\n#[cfg(not(Py_LIMITED_API))]\npub use self::string::PyStringData;\npub use self::string::{PyString, PyStringMethods};\npub use self::traceback::{PyTraceback, PyTracebackMethods};\npub use self::tuple::{PyTuple, PyTupleMethods};\npub use self::typeobject::{PyType, PyTypeMethods};\npub use self::weakref::{PyWeakref, PyWeakrefMethods, PyWeakrefProxy, PyWeakrefReference};\n\n/// Iteration over Python collections.\n///\n/// When working with a Python collection, one approach is to convert it to a Rust collection such\n/// as `Vec` or `HashMap`. However this is a relatively expensive operation. If you just want to\n/// visit all their items, consider iterating over the collections directly:\n///\n/// # Examples\n///\n/// ```rust\n/// use pyo3::prelude::*;\n/// use pyo3::types::PyDict;\n/// use pyo3::ffi::c_str;\n///\n/// # pub fn main() -> PyResult<()> {\n/// Python::attach(|py| {\n///     let dict = py.eval(c\"{'a':'b', 'c':'d'}\", None, None)?.cast_into::<PyDict>()?;\n///\n///     for (key, value) in &dict {\n///         println!(\"key: {}, value: {}\", key, value);\n///     }\n///\n///     Ok(())\n/// })\n/// # }\n///  ```\n///\n/// If PyO3 detects that the collection is mutated during iteration, it will panic.\n///\n/// These iterators use Python's C-API directly. However in certain cases, like when compiling for\n/// the Limited API and PyPy, the underlying structures are opaque and that may not be possible.\n/// In these cases the iterators are implemented by forwarding to [`PyIterator`].\npub mod iter {\n    pub use super::dict::BoundDictIterator;\n    pub use super::frozenset::BoundFrozenSetIterator;\n    pub use super::list::BoundListIterator;\n    pub use super::set::BoundSetIterator;\n    pub use super::tuple::{BorrowedTupleIterator, BoundTupleIterator};\n}\n\n/// Python objects that have a base type.\n///\n/// This marks types that can be upcast into a [`PyAny`] and used in its place.\n/// This essentially includes every Python object except [`PyAny`] itself.\n///\n/// This is used to provide the [`Deref<Target = Bound<'_, PyAny>>`](std::ops::Deref)\n/// implementations for [`Bound<'_, T>`](crate::Bound).\n///\n/// Users should not need to implement this trait directly. It's implementation\n/// is provided by the [`#[pyclass]`](macro@crate::pyclass) attribute.\n///\n/// ## Note\n/// This is needed because the compiler currently tries to figure out all the\n/// types in a deref-chain before starting to look for applicable method calls.\n/// So we need to prevent [`Bound<'_, PyAny`](crate::Bound) dereferencing to\n/// itself in order to avoid running into the recursion limit. This trait is\n/// used to exclude this from our blanket implementation. See [this Rust\n/// issue][1] for more details. If the compiler limitation gets resolved, this\n/// trait will be removed.\n///\n/// [1]: https://github.com/rust-lang/rust/issues/19509\npub trait DerefToPyAny {\n    // Empty.\n}\n\n// Implementations core to all native types except for PyAny (because they don't\n// make sense on PyAny / have different implementations).\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! pyobject_native_type_named (\n    ($name:ty $(;$generics:ident)*) => {\n        impl $crate::types::DerefToPyAny for $name {}\n    };\n);\n\n/// Helper for defining the `$typeobject` argument for other macros in this module.\n///\n/// # Safety\n///\n/// - `$typeobject` must be a known `static mut PyTypeObject`\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! pyobject_native_static_type_object(\n    ($typeobject:expr) => {\n        |_py| &raw mut $typeobject\n    };\n);\n\n/// Adds a TYPE_HINT constant if the `experimental-inspect`  feature is enabled.\n#[cfg(not(feature = \"experimental-inspect\"))]\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! pyobject_type_info_type_hint(\n    ($module:expr, $name:expr) => {};\n);\n\n#[cfg(feature = \"experimental-inspect\")]\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! pyobject_type_info_type_hint(\n    ($module:expr, $name:expr) => {\n        const TYPE_HINT: $crate::inspect::PyStaticExpr = $crate::type_hint_identifier!($module, $name);\n    };\n);\n\n/// Implements the `PyTypeInfo` trait for a native Python type.\n///\n/// # Safety\n///\n/// - `$typeobject` must be a function that produces a valid `*mut PyTypeObject`\n/// - `$checkfunction` must be a function that accepts arbitrary `*mut PyObject` and returns true /\n///   false according to whether the object is an instance of the type from `$typeobject`\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! pyobject_native_type_info(\n    ($name:ty, $typeobject:expr, $type_hint_module:expr, $type_hint_name:expr, $module:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {\n        // SAFETY: macro caller has upheld the safety contracts\n        unsafe impl<$($generics,)*> $crate::type_object::PyTypeInfo for $name {\n            const NAME: &'static str = stringify!($name);\n            const MODULE: ::std::option::Option<&'static str> = $module;\n            $crate::pyobject_type_info_type_hint!($type_hint_module, $type_hint_name);\n\n            #[inline]\n            #[allow(clippy::redundant_closure_call)]\n            fn type_object_raw(py: $crate::Python<'_>) -> *mut $crate::ffi::PyTypeObject {\n                $typeobject(py)\n            }\n\n            $(\n                #[inline]\n                fn is_type_of(obj: &$crate::Bound<'_, $crate::PyAny>) -> bool {\n                    #[allow(unused_unsafe, reason = \"not all `$checkfunction` are unsafe fn\")]\n                    // SAFETY: `$checkfunction` is being called with a valid `PyObject` pointer\n                    unsafe { $checkfunction(obj.as_ptr()) > 0 }\n                }\n            )?\n        }\n\n        impl $name {\n            #[doc(hidden)]\n            pub const _PYO3_DEF: $crate::impl_::pymodule::AddTypeToModule<Self> = $crate::impl_::pymodule::AddTypeToModule::new();\n\n            #[allow(dead_code)]\n            #[doc(hidden)]\n            pub const _PYO3_INTROSPECTION_ID: &'static str = concat!(stringify!($module), stringify!($name));\n        }\n    };\n);\n\n/// Declares all of the boilerplate for Python types.\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! pyobject_native_type_core {\n    ($name:ty, $typeobject:expr, $type_hint_module:expr, $type_hint_name:expr, #module=$module:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {\n        $crate::pyobject_native_type_named!($name $(;$generics)*);\n        $crate::pyobject_native_type_info!($name, $typeobject, $type_hint_module, $type_hint_name, $module $(, #checkfunction=$checkfunction)? $(;$generics)*);\n    };\n    ($name:ty, $typeobject:expr, $type_hint_module:expr, $type_hint_name:expr, #module=$module:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {\n        $crate::pyobject_native_type_core!($name, $typeobject, $type_hint_module, $type_hint_name, #module=$module $(, #checkfunction=$checkfunction)? $(;$generics)*);\n    };\n    ($name:ty, $typeobject:expr, $type_hint_module:expr, $type_hint_name:expr $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {\n        $crate::pyobject_native_type_core!($name, $typeobject, $type_hint_module, $type_hint_name, #module=::std::option::Option::Some(\"builtins\") $(, #checkfunction=$checkfunction)? $(;$generics)*);\n    };\n}\n\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! pyobject_subclassable_native_type {\n    ($name:ty, $layout:path $(;$generics:ident)*) => {\n        #[cfg(not(Py_LIMITED_API))]\n        impl<$($generics,)*> $crate::impl_::pyclass::PyClassBaseType for $name {\n            type LayoutAsBase = $crate::impl_::pycell::PyClassObjectBase<$layout>;\n            type BaseNativeType = $name;\n            type Initializer = $crate::impl_::pyclass_init::PyNativeTypeInitializer<Self>;\n            type PyClassMutability = $crate::pycell::impl_::ImmutableClass;\n            type Layout<T: $crate::impl_::pyclass::PyClassImpl> = $crate::impl_::pycell::PyStaticClassObject<T>;\n        }\n\n        #[cfg(all(Py_3_12, Py_LIMITED_API))]\n        impl<$($generics,)*> $crate::impl_::pyclass::PyClassBaseType for $name {\n            type LayoutAsBase = $crate::impl_::pycell::PyVariableClassObjectBase;\n            type BaseNativeType = Self;\n            type Initializer = $crate::impl_::pyclass_init::PyNativeTypeInitializer<Self>;\n            type PyClassMutability = $crate::pycell::impl_::ImmutableClass;\n            type Layout<T: $crate::impl_::pyclass::PyClassImpl> = $crate::impl_::pycell::PyVariableClassObject<T>;\n        }\n    }\n}\n\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! pyobject_native_type_sized {\n    ($name:ty, $layout:path $(;$generics:ident)*) => {\n        unsafe impl $crate::type_object::PyLayout<$name> for $layout {}\n        impl $crate::type_object::PySizedLayout<$name> for $layout {}\n    };\n}\n\n/// Declares all of the boilerplate for Python types which can be inherited from (because the exact\n/// Python layout is known).\n#[doc(hidden)]\n#[macro_export]\nmacro_rules! pyobject_native_type {\n    ($name:ty, $layout:path, $typeobject:expr, $type_hint_module:expr, $type_hint_name:expr $(, #module=$module:expr)? $(, #checkfunction=$checkfunction:path)? $(;$generics:ident)*) => {\n        $crate::pyobject_native_type_core!($name, $typeobject, $type_hint_module, $type_hint_name $(, #module=$module)? $(, #checkfunction=$checkfunction)? $(;$generics)*);\n        // To prevent inheriting native types with ABI3\n        #[cfg(not(Py_LIMITED_API))]\n        $crate::pyobject_native_type_sized!($name, $layout $(;$generics)*);\n    };\n}\n\npub(crate) mod any;\npub(crate) mod boolobject;\npub(crate) mod bytearray;\npub(crate) mod bytes;\npub(crate) mod capsule;\nmod code;\npub(crate) mod complex;\npub(crate) mod datetime;\npub(crate) mod dict;\nmod ellipsis;\npub(crate) mod float;\n#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]\nmod frame;\npub(crate) mod frozenset;\nmod function;\n#[cfg(Py_3_9)]\npub(crate) mod genericalias;\npub(crate) mod iterator;\npub(crate) mod list;\npub(crate) mod mapping;\npub(crate) mod mappingproxy;\nmod memoryview;\npub(crate) mod module;\n#[cfg(all(not(Py_LIMITED_API), Py_3_13))]\nmod mutex;\nmod none;\nmod notimplemented;\nmod num;\nmod pysuper;\npub(crate) mod range;\npub(crate) mod sequence;\npub(crate) mod set;\npub(crate) mod slice;\npub(crate) mod string;\npub(crate) mod traceback;\npub(crate) mod tuple;\npub(crate) mod typeobject;\npub(crate) mod weakref;\n"
  },
  {
    "path": "src/types/module.rs",
    "content": "use crate::err::{PyErr, PyResult};\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::impl_::callback::IntoPyCallbackOutput;\nuse crate::py_result_ext::PyResultExt;\nuse crate::pyclass::PyClass;\nuse crate::types::{\n    any::PyAnyMethods, list::PyListMethods, string::PyStringMethods, PyAny, PyCFunction, PyDict,\n    PyList, PyString,\n};\nuse crate::{\n    exceptions, ffi, Borrowed, Bound, BoundObject, IntoPyObject, IntoPyObjectExt, Py, Python,\n};\nuse std::borrow::Cow;\n#[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]\nuse std::ffi::c_int;\nuse std::ffi::CStr;\nuse std::str;\n\n/// Represents a Python [`module`][1] object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyModule>`][crate::Py] or [`Bound<'py, PyModule>`][Bound].\n///\n/// For APIs available on `module` objects, see the [`PyModuleMethods`] trait which is implemented for\n/// [`Bound<'py, PyModule>`][Bound].\n///\n/// As with all other Python objects, modules are first class citizens.\n/// This means they can be passed to or returned from functions,\n/// created dynamically, assigned to variables and so forth.\n///\n/// [1]: https://docs.python.org/3/tutorial/modules.html\n#[repr(transparent)]\npub struct PyModule(PyAny);\n\npyobject_native_type_core!(PyModule, pyobject_native_static_type_object!(ffi::PyModule_Type), \"types\", \"ModuleType\", #checkfunction=ffi::PyModule_Check);\n\nimpl PyModule {\n    /// Creates a new module object with the `__name__` attribute set to `name`.  When creating\n    /// a submodule pass the full path as the name such as `top_level.name`.\n    ///\n    /// # Examples\n    ///\n    /// ``` rust\n    /// use pyo3::prelude::*;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let module = PyModule::new(py, \"my_module\")?;\n    ///\n    ///     assert_eq!(module.name()?, \"my_module\");\n    ///     Ok(())\n    /// })?;\n    /// # Ok(())}\n    ///  ```\n    pub fn new<'py>(py: Python<'py>, name: &str) -> PyResult<Bound<'py, PyModule>> {\n        let name = PyString::new(py, name);\n        let module = unsafe {\n            ffi::PyModule_NewObject(name.as_ptr())\n                .assume_owned_or_err(py)?\n                .cast_into_unchecked()\n        };\n\n        // By default, PyO3 assumes modules do not use the GIL for thread safety.\n        module.gil_used(false)?;\n\n        Ok(module)\n    }\n\n    /// Imports the Python module with the specified name.\n    ///\n    /// # Examples\n    ///\n    /// ```no_run\n    /// # fn main() {\n    /// use pyo3::prelude::*;\n    ///\n    /// Python::attach(|py| {\n    ///     let module = PyModule::import(py, \"antigravity\").expect(\"No flying for you.\");\n    /// });\n    /// # }\n    ///  ```\n    ///\n    /// This is equivalent to the following Python expression:\n    /// ```python\n    /// import antigravity\n    /// ```\n    ///\n    /// If you want to import a class, you can store a reference to it with\n    /// [`PyOnceLock::import`][crate::sync::PyOnceLock::import].\n    pub fn import<'py, N>(py: Python<'py>, name: N) -> PyResult<Bound<'py, PyModule>>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n    {\n        let name = name.into_pyobject_or_pyerr(py)?;\n        unsafe {\n            ffi::PyImport_Import(name.as_ptr())\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n        }\n    }\n\n    /// Creates and loads a module named `module_name`,\n    /// containing the Python code passed to `code`\n    /// and pretending to live at `file_name`.\n    ///\n    /// If `file_name` is empty, it will be set to `<string>`.\n    ///\n    /// <div class=\"information\">\n    ///     <div class=\"tooltip compile_fail\" style=\"\">&#x26a0; &#xfe0f;</div>\n    /// </div><div class=\"example-wrap\" style=\"display:inline-block\"><pre class=\"compile_fail\" style=\"white-space:normal;font:inherit;\">\n    //\n    ///  <strong>Warning</strong>: This will compile and execute code. <strong>Never</strong> pass untrusted code to this function!\n    ///\n    /// </pre></div>\n    ///\n    /// # Errors\n    ///\n    /// Returns `PyErr` if:\n    /// - `code` is not syntactically correct Python.\n    /// - Any Python exceptions are raised while initializing the module.\n    /// - Any of the arguments cannot be converted to [`CString`][std::ffi::CString]s.\n    ///\n    /// # Example: bundle in a file at compile time with [`include_str!`][std::include_str]:\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::ffi::c_str;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// // This path is resolved relative to this file.\n    /// let code = c_str!(include_str!(\"../../assets/script.py\"));\n    ///\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     PyModule::from_code(py, code, c\"example.py\", c\"example\")?;\n    ///     Ok(())\n    /// })?;\n    /// # Ok(())\n    /// # }\n    /// ```\n    ///\n    /// # Example: Load a file at runtime with [`std::fs::read_to_string`].\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::ffi::c_str;\n    /// use std::ffi::CString;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// # #[cfg(not(target_arch = \"wasm32\"))]  // node fs doesn't see this file, maybe cwd wrong?\n    /// # {\n    /// // This path is resolved by however the platform resolves paths,\n    /// // which also makes this less portable. Consider using `include_str`\n    /// // if you just want to bundle a script with your module.\n    /// let code = std::fs::read_to_string(\"assets/script.py\")?;\n    ///\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     PyModule::from_code(py, CString::new(code)?.as_c_str(), c\"example.py\", c\"example\")?;\n    ///     Ok(())\n    /// })?;\n    /// # }\n    /// # Ok(())\n    /// # }\n    /// ```\n    pub fn from_code<'py>(\n        py: Python<'py>,\n        code: &CStr,\n        file_name: &CStr,\n        module_name: &CStr,\n    ) -> PyResult<Bound<'py, PyModule>> {\n        let file_name = if file_name.is_empty() {\n            c\"<string>\"\n        } else {\n            file_name\n        };\n        unsafe {\n            let code = ffi::Py_CompileString(code.as_ptr(), file_name.as_ptr(), ffi::Py_file_input)\n                .assume_owned_or_err(py)?;\n\n            ffi::PyImport_ExecCodeModuleEx(module_name.as_ptr(), code.as_ptr(), file_name.as_ptr())\n                .assume_owned_or_err(py)\n                .cast_into()\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyModule`].\n///\n/// These methods are defined for the `Bound<'py, PyModule>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyModule\")]\npub trait PyModuleMethods<'py>: crate::sealed::Sealed {\n    /// Returns the module's `__dict__` attribute, which contains the module's symbol table.\n    fn dict(&self) -> Bound<'py, PyDict>;\n\n    /// Returns the index (the `__all__` attribute) of the module,\n    /// creating one if needed.\n    ///\n    /// `__all__` declares the items that will be imported with `from my_module import *`.\n    fn index(&self) -> PyResult<Bound<'py, PyList>>;\n\n    /// Returns the name (the `__name__` attribute) of the module.\n    ///\n    /// May fail if the module does not have a `__name__` attribute.\n    fn name(&self) -> PyResult<Bound<'py, PyString>>;\n\n    /// Returns the filename (the `__file__` attribute) of the module.\n    ///\n    /// May fail if the module does not have a `__file__` attribute.\n    fn filename(&self) -> PyResult<Bound<'py, PyString>>;\n\n    /// Adds an attribute to the module.\n    ///\n    /// For adding classes, functions or modules, prefer to use [`PyModuleMethods::add_class`],\n    /// [`PyModuleMethods::add_function`] or [`PyModuleMethods::add_submodule`] instead,\n    /// respectively.\n    ///\n    /// # Examples\n    ///\n    /// ```rust,no_run\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pymodule]\n    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {\n    ///     module.add(\"c\", 299_792_458)?;\n    ///     Ok(())\n    /// }\n    /// ```\n    ///\n    /// Python code can then do the following:\n    ///\n    /// ```python\n    /// from my_module import c\n    ///\n    /// print(\"c is\", c)\n    /// ```\n    ///\n    /// This will result in the following output:\n    ///\n    /// ```text\n    /// c is 299792458\n    /// ```\n    fn add<N, V>(&self, name: N, value: V) -> PyResult<()>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n        V: IntoPyObject<'py>;\n\n    /// Adds a new class to the module.\n    ///\n    /// Notice that this method does not take an argument.\n    /// Instead, this method is *generic*, and requires us to use the\n    /// \"turbofish\" syntax to specify the class we want to add.\n    ///\n    /// # Examples\n    ///\n    /// ```rust,no_run\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyclass]\n    /// struct Foo { /* fields omitted */ }\n    ///\n    /// #[pymodule]\n    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {\n    ///     module.add_class::<Foo>()?;\n    ///     Ok(())\n    /// }\n    ///  ```\n    ///\n    /// Python code can see this class as such:\n    /// ```python\n    /// from my_module import Foo\n    ///\n    /// print(\"Foo is\", Foo)\n    /// ```\n    ///\n    /// This will result in the following output:\n    /// ```text\n    /// Foo is <class 'builtins.Foo'>\n    /// ```\n    ///\n    /// Note that as we haven't defined a [constructor][1], Python code can't actually\n    /// make an *instance* of `Foo` (or *get* one for that matter, as we haven't exported\n    /// anything that can return instances of `Foo`).\n    ///\n    #[doc = concat!(\"[1]: https://pyo3.rs/v\", env!(\"CARGO_PKG_VERSION\"), \"/class.html#constructor\")]\n    fn add_class<T>(&self) -> PyResult<()>\n    where\n        T: PyClass;\n\n    /// Adds a function or a (sub)module to a module, using the functions name as name.\n    ///\n    /// Prefer to use [`PyModuleMethods::add_function`] and/or [`PyModuleMethods::add_submodule`]\n    /// instead.\n    fn add_wrapped<T>(&self, wrapper: &impl Fn(Python<'py>) -> T) -> PyResult<()>\n    where\n        T: IntoPyCallbackOutput<'py, Py<PyAny>>;\n\n    /// Adds a submodule to a module.\n    ///\n    /// This is especially useful for creating module hierarchies.\n    ///\n    /// Note that this doesn't define a *package*, so this won't allow Python code\n    /// to directly import submodules by using\n    /// <span style=\"white-space: pre\">`from my_module import submodule`</span>.\n    /// For more information, see [#759][1] and [#1517][2].\n    ///\n    /// # Examples\n    ///\n    /// ```rust,no_run\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pymodule]\n    /// fn my_module(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> {\n    ///     let submodule = PyModule::new(py, \"submodule\")?;\n    ///     submodule.add(\"super_useful_constant\", \"important\")?;\n    ///\n    ///     module.add_submodule(&submodule)?;\n    ///     Ok(())\n    /// }\n    /// ```\n    ///\n    /// Python code can then do the following:\n    ///\n    /// ```python\n    /// import my_module\n    ///\n    /// print(\"super_useful_constant is\", my_module.submodule.super_useful_constant)\n    /// ```\n    ///\n    /// This will result in the following output:\n    ///\n    /// ```text\n    /// super_useful_constant is important\n    /// ```\n    ///\n    /// [1]: https://github.com/PyO3/pyo3/issues/759\n    /// [2]: https://github.com/PyO3/pyo3/issues/1517#issuecomment-808664021\n    fn add_submodule(&self, module: &Bound<'_, PyModule>) -> PyResult<()>;\n\n    /// Add a function to a module.\n    ///\n    /// Note that this also requires the [`wrap_pyfunction!`][2] macro\n    /// to wrap a function annotated with [`#[pyfunction]`][1].\n    ///\n    /// ```rust,no_run\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyfunction]\n    /// fn say_hello() {\n    ///     println!(\"Hello world!\")\n    /// }\n    /// #[pymodule]\n    /// fn my_module(module: &Bound<'_, PyModule>) -> PyResult<()> {\n    ///     module.add_function(wrap_pyfunction!(say_hello, module)?)\n    /// }\n    /// ```\n    ///\n    /// Python code can then do the following:\n    ///\n    /// ```python\n    /// from my_module import say_hello\n    ///\n    /// say_hello()\n    /// ```\n    ///\n    /// This will result in the following output:\n    ///\n    /// ```text\n    /// Hello world!\n    /// ```\n    ///\n    /// [1]: crate::prelude::pyfunction\n    /// [2]: crate::wrap_pyfunction\n    fn add_function(&self, fun: Bound<'_, PyCFunction>) -> PyResult<()>;\n\n    /// Declare whether or not this module supports running with the GIL disabled\n    ///\n    /// Since PyO3 0.28, PyO3 defaults to assuming that modules do not require the\n    /// GIL for thread safety. Call this function with `true` to opt-out of supporting\n    /// free-threaded Python.\n    ///\n    /// This function sets the [`Py_MOD_GIL`\n    /// slot](https://docs.python.org/3/c-api/module.html#c.Py_mod_gil) on the\n    /// module object.\n    ///\n    /// # Examples\n    ///\n    /// ```rust,no_run\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pymodule]\n    /// fn my_module(py: Python<'_>, module: &Bound<'_, PyModule>) -> PyResult<()> {\n    ///     let submodule = PyModule::new(py, \"submodule\")?;\n    ///     submodule.gil_used(true)?;\n    ///     module.add_submodule(&submodule)?;\n    ///     Ok(())\n    /// }\n    /// ```\n    ///\n    /// The resulting module will print a `RuntimeWarning` and re-enable the\n    /// GIL when Python imports it on the free-threaded build.\n    ///\n    /// This is a no-op on the GIL-enabled build.\n    fn gil_used(&self, gil_used: bool) -> PyResult<()>;\n}\n\nimpl<'py> PyModuleMethods<'py> for Bound<'py, PyModule> {\n    fn dict(&self) -> Bound<'py, PyDict> {\n        unsafe {\n            // PyModule_GetDict returns borrowed ptr; must make owned for safety (see #890).\n            ffi::PyModule_GetDict(self.as_ptr())\n                .assume_borrowed(self.py())\n                .to_owned()\n                .cast_into_unchecked()\n        }\n    }\n\n    fn index(&self) -> PyResult<Bound<'py, PyList>> {\n        let __all__ = __all__(self.py());\n        match self.getattr(__all__) {\n            Ok(idx) => idx.cast_into().map_err(PyErr::from),\n            Err(err) => {\n                if err.is_instance_of::<exceptions::PyAttributeError>(self.py()) {\n                    let l = PyList::empty(self.py());\n                    self.setattr(__all__, &l)?;\n                    Ok(l)\n                } else {\n                    Err(err)\n                }\n            }\n        }\n    }\n\n    fn name(&self) -> PyResult<Bound<'py, PyString>> {\n        #[cfg(not(PyPy))]\n        {\n            unsafe {\n                ffi::PyModule_GetNameObject(self.as_ptr())\n                    .assume_owned_or_err(self.py())\n                    .cast_into_unchecked()\n            }\n        }\n\n        #[cfg(PyPy)]\n        {\n            self.dict()\n                .get_item(\"__name__\")\n                .map_err(|_| exceptions::PyAttributeError::new_err(\"__name__\"))?\n                .cast_into()\n                .map_err(PyErr::from)\n        }\n    }\n\n    fn filename(&self) -> PyResult<Bound<'py, PyString>> {\n        #[cfg(not(PyPy))]\n        unsafe {\n            ffi::PyModule_GetFilenameObject(self.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n\n        #[cfg(PyPy)]\n        {\n            self.dict()\n                .get_item(\"__file__\")\n                .map_err(|_| exceptions::PyAttributeError::new_err(\"__file__\"))?\n                .cast_into()\n                .map_err(PyErr::from)\n        }\n    }\n\n    fn add<N, V>(&self, name: N, value: V) -> PyResult<()>\n    where\n        N: IntoPyObject<'py, Target = PyString>,\n        V: IntoPyObject<'py>,\n    {\n        fn inner(\n            module: &Bound<'_, PyModule>,\n            name: Borrowed<'_, '_, PyString>,\n            value: Borrowed<'_, '_, PyAny>,\n        ) -> PyResult<()> {\n            module\n                .index()?\n                .append(name)\n                .expect(\"could not append __name__ to __all__\");\n            module.setattr(name, value)\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            name.into_pyobject_or_pyerr(py)?.as_borrowed(),\n            value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn add_class<T>(&self) -> PyResult<()>\n    where\n        T: PyClass,\n    {\n        let py = self.py();\n        self.add(\n            <T as PyClass>::NAME,\n            T::lazy_type_object().get_or_try_init(py)?,\n        )\n    }\n\n    fn add_wrapped<T>(&self, wrapper: &impl Fn(Python<'py>) -> T) -> PyResult<()>\n    where\n        T: IntoPyCallbackOutput<'py, Py<PyAny>>,\n    {\n        fn inner(module: &Bound<'_, PyModule>, object: Bound<'_, PyAny>) -> PyResult<()> {\n            let name = object.getattr(__name__(module.py()))?;\n            module.add(name.cast_into::<PyString>()?, object)\n        }\n\n        let py = self.py();\n        inner(self, wrapper(py).convert(py)?.into_bound(py))\n    }\n\n    fn add_submodule(&self, module: &Bound<'_, PyModule>) -> PyResult<()> {\n        let name = module.name()?;\n        let name = name.to_cow()?;\n        let name = match name.rsplit_once('.') {\n            Some((_, name)) => Cow::from(name),\n            None => name,\n        };\n        self.add(name, module)\n    }\n\n    fn add_function(&self, fun: Bound<'_, PyCFunction>) -> PyResult<()> {\n        let name = fun.getattr(__name__(self.py()))?;\n        self.add(name.cast_into::<PyString>()?, fun)\n    }\n\n    #[cfg_attr(any(Py_LIMITED_API, not(Py_GIL_DISABLED)), allow(unused_variables))]\n    fn gil_used(&self, gil_used: bool) -> PyResult<()> {\n        #[cfg(all(not(Py_LIMITED_API), Py_GIL_DISABLED))]\n        {\n            let gil_used = match gil_used {\n                true => ffi::Py_MOD_GIL_USED,\n                false => ffi::Py_MOD_GIL_NOT_USED,\n            };\n            match unsafe { ffi::PyUnstable_Module_SetGIL(self.as_ptr(), gil_used) } {\n                c_int::MIN..=-1 => Err(PyErr::fetch(self.py())),\n                0..=c_int::MAX => Ok(()),\n            }\n        }\n        #[cfg(any(Py_LIMITED_API, not(Py_GIL_DISABLED)))]\n        Ok(())\n    }\n}\n\nfn __all__(py: Python<'_>) -> &Bound<'_, PyString> {\n    intern!(py, \"__all__\")\n}\n\nfn __name__(py: Python<'_>) -> &Bound<'_, PyString> {\n    intern!(py, \"__name__\")\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::{\n        types::{module::PyModuleMethods, PyModule},\n        Python,\n    };\n\n    #[test]\n    fn module_import_and_name() {\n        Python::attach(|py| {\n            let builtins = PyModule::import(py, \"builtins\").unwrap();\n            assert_eq!(builtins.name().unwrap(), \"builtins\");\n        })\n    }\n\n    #[test]\n    fn module_filename() {\n        use crate::types::string::PyStringMethods;\n        Python::attach(|py| {\n            let site = PyModule::import(py, \"site\").unwrap();\n            assert!(site\n                .filename()\n                .unwrap()\n                .to_cow()\n                .unwrap()\n                .ends_with(\"site.py\"));\n        })\n    }\n\n    #[test]\n    fn module_from_code_empty_file() {\n        Python::attach(|py| {\n            let builtins = PyModule::from_code(py, c\"\", c\"\", c\"\").unwrap();\n            assert_eq!(builtins.filename().unwrap(), \"<string>\");\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/mutex.rs",
    "content": "use std::cell::UnsafeCell;\nuse std::marker::PhantomData;\nuse std::ops::{Deref, DerefMut};\n#[cfg(panic = \"unwind\")]\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::{LockResult, PoisonError};\n#[cfg(panic = \"unwind\")]\nuse std::thread;\n\n// See std::sync::poison in the rust standard library.\n// This is more-or-less copied from there since it is not public.\n// this type detects a panic and poisons the wrapping mutex\nstruct Flag {\n    #[cfg(panic = \"unwind\")]\n    failed: AtomicBool,\n}\n\nimpl Flag {\n    #[inline]\n    const fn new() -> Flag {\n        Flag {\n            #[cfg(panic = \"unwind\")]\n            failed: AtomicBool::new(false),\n        }\n    }\n\n    /// Checks the flag for an unguarded borrow, where we only care about existing poison.\n    #[inline]\n    fn borrow(&self) -> LockResult<()> {\n        if self.get() {\n            Err(PoisonError::new(()))\n        } else {\n            Ok(())\n        }\n    }\n\n    /// Checks the flag for a guarded borrow, where we may also set poison when `done`.\n    #[inline]\n    fn guard(&self) -> LockResult<Guard> {\n        let ret = Guard {\n            #[cfg(panic = \"unwind\")]\n            panicking: thread::panicking(),\n        };\n        if self.get() {\n            Err(PoisonError::new(ret))\n        } else {\n            Ok(ret)\n        }\n    }\n\n    #[inline]\n    #[cfg(panic = \"unwind\")]\n    fn done(&self, guard: &Guard) {\n        if !guard.panicking && thread::panicking() {\n            self.failed.store(true, Ordering::Relaxed);\n        }\n    }\n\n    #[inline]\n    #[cfg(not(panic = \"unwind\"))]\n    fn done(&self, _guard: &Guard) {}\n\n    #[inline]\n    #[cfg(panic = \"unwind\")]\n    fn get(&self) -> bool {\n        self.failed.load(Ordering::Relaxed)\n    }\n\n    #[inline(always)]\n    #[cfg(not(panic = \"unwind\"))]\n    fn get(&self) -> bool {\n        false\n    }\n\n    #[inline]\n    fn clear(&self) {\n        #[cfg(panic = \"unwind\")]\n        self.failed.store(false, Ordering::Relaxed)\n    }\n}\n\n#[derive(Clone)]\npub(crate) struct Guard {\n    #[cfg(panic = \"unwind\")]\n    panicking: bool,\n}\n\n/// Wrapper for [`PyMutex`](https://docs.python.org/3/c-api/init.html#c.PyMutex), exposing an RAII guard interface.\n///\n/// Compared with `std::sync::Mutex` or `parking_lot::Mutex`, this is a very\n/// stripped-down locking primitive that only supports blocking lock and unlock\n/// operations and does not support `try_lock` or APIs that depend on\n/// `try_lock`.  For this reason, it is not possible to avoid the possibility of\n/// possibly blocking when calling `lock` and extreme care must be taken to avoid\n/// introducing a deadlock.\n///\n/// This type is most useful when arbitrary Python code might execute while the\n/// lock is held. On the GIL-enabled build, PyMutex will release the GIL if the\n/// thread is blocked on acquiring the lock. On the free-threaded build, threads\n/// blocked on acquiring a PyMutex will not prevent the garbage collector from\n/// running.\n///\n/// ## Poisoning\n///\n/// Like `std::sync::Mutex`, `PyMutex` implements poisoning. A mutex\n/// is considered poisoned whenever a thread panics while holding the mutex. Once\n/// a mutex is poisoned, all other threads are unable to access the data by\n/// default as it is likely to be tainted (some invariant is not being held).\n///\n/// This means that the `lock` method returns a `Result` which indicated whether\n/// the mutex has been poisoned or not. Must usage will simple `unwrap()` these\n/// results, propagating panics among threads to ensure a possible invalid\n/// invariant is not being observed.\n///\n/// A poisoned mutex, however, does not prevent all access to the underlying\n/// data. The `PoisonError` type has an `into_inner` method which will return\n/// the guard that would have otherwise been returned on a successful lock. This\n/// allows access to the data, despite the lock being poisoned.\npub struct PyMutex<T: ?Sized> {\n    pub(crate) mutex: UnsafeCell<crate::ffi::PyMutex>,\n    poison: Flag,\n    pub(crate) data: UnsafeCell<T>,\n}\n\n/// RAII guard to handle releasing a PyMutex lock.\n///\n/// The lock is released when `PyMutexGuard` is dropped.\npub struct PyMutexGuard<'a, T: ?Sized> {\n    inner: &'a PyMutex<T>,\n    poison: Guard,\n    // this is equivalent to impl !Send, which we can't do\n    // because negative trait bounds aren't supported yet\n    _phantom: PhantomData<*const ()>,\n}\n\n/// `T` must be `Sync` for a [`PyMutexGuard<T>`] to be `Sync`\n/// because it is possible to get a `&T` from `&MutexGuard` (via `Deref`).\nunsafe impl<T: ?Sized + Sync> Sync for PyMutexGuard<'_, T> {}\n\n/// `T` must be `Send` for a [`PyMutex`] to be `Send` because it is possible to acquire\n/// the owned `T` from the `PyMutex` via [`into_inner`].\n///\n/// [`into_inner`]: PyMutex::into_inner\nunsafe impl<T: ?Sized + Send> Send for PyMutex<T> {}\n\n/// `T` must be `Send` for [`PyMutex`] to be `Sync`.\n/// This ensures that the protected data can be accessed safely from multiple threads\n/// without causing data races or other unsafe behavior.\n///\n/// [`PyMutex<T>`] provides mutable access to `T` to one thread at a time. However, it's essential\n/// for `T` to be `Send` because it's not safe for non-`Send` structures to be accessed in\n/// this manner. For instance, consider [`Rc`], a non-atomic reference counted smart pointer,\n/// which is not `Send`. With `Rc`, we can have multiple copies pointing to the same heap\n/// allocation with a non-atomic reference count. If we were to use `Mutex<Rc<_>>`, it would\n/// only protect one instance of `Rc` from shared access, leaving other copies vulnerable\n/// to potential data races.\n///\n/// Also note that it is not necessary for `T` to be `Sync` as `&T` is only made available\n/// to one thread at a time if `T` is not `Sync`.\n///\n/// [`Rc`]: std::rc::Rc\nunsafe impl<T: ?Sized + Send> Sync for PyMutex<T> {}\n\nimpl<T> PyMutex<T> {\n    /// Acquire the mutex, blocking the current thread until it is able to do so.\n    pub fn lock(&self) -> LockResult<PyMutexGuard<'_, T>> {\n        unsafe { crate::ffi::PyMutex_Lock(UnsafeCell::raw_get(&self.mutex)) };\n        PyMutexGuard::new(self)\n    }\n\n    /// Create a new mutex in an unlocked state ready for use.\n    pub const fn new(value: T) -> Self {\n        Self {\n            mutex: UnsafeCell::new(crate::ffi::PyMutex::new()),\n            data: UnsafeCell::new(value),\n            poison: Flag::new(),\n        }\n    }\n\n    /// Check if the mutex is locked.\n    ///\n    /// Note that this is only useful for debugging or test purposes and should\n    /// not be used to make concurrency control decisions, as the lock state may\n    /// change immediately after the check.\n    #[cfg(Py_3_14)]\n    pub fn is_locked(&self) -> bool {\n        let ret = unsafe { crate::ffi::PyMutex_IsLocked(UnsafeCell::raw_get(&self.mutex)) };\n        ret != 0\n    }\n\n    /// Consumes this mutex, returning the underlying data.\n    ///\n    /// # Errors\n    ///\n    /// If another user of this mutex panicked while holding the mutex, then\n    /// this call will return an error containing the underlying data\n    /// instead.\n    pub fn into_inner(self) -> LockResult<T>\n    where\n        T: Sized,\n    {\n        let data = self.data.into_inner();\n        map_result(self.poison.borrow(), |()| data)\n    }\n\n    /// Clear the poisoned state from a mutex.\n    ///\n    /// If the mutex is poisoned, it will remain poisoned until this function is called. This\n    /// allows recovering from a poisoned state and marking that it has recovered. For example, if\n    /// the value is overwritten by a known-good value, then the mutex can be marked as\n    /// un-poisoned. Or possibly, the value could be inspected to determine if it is in a\n    /// consistent state, and if so the poison is removed.\n    pub fn clear_poison(&self) {\n        self.poison.clear();\n    }\n}\n\n#[cfg_attr(not(panic = \"unwind\"), allow(clippy::unnecessary_wraps))]\nfn map_result<T, U, F>(result: LockResult<T>, f: F) -> LockResult<U>\nwhere\n    F: FnOnce(T) -> U,\n{\n    match result {\n        Ok(t) => Ok(f(t)),\n        #[cfg(panic = \"unwind\")]\n        Err(e) => Err(PoisonError::new(f(e.into_inner()))),\n        #[cfg(not(panic = \"unwind\"))]\n        Err(_) => {\n            unreachable!();\n        }\n    }\n}\n\nimpl<'mutex, T: ?Sized> PyMutexGuard<'mutex, T> {\n    fn new(lock: &'mutex PyMutex<T>) -> LockResult<PyMutexGuard<'mutex, T>> {\n        map_result(lock.poison.guard(), |guard| PyMutexGuard {\n            inner: lock,\n            poison: guard,\n            _phantom: PhantomData,\n        })\n    }\n}\n\nimpl<'a, T: ?Sized> Drop for PyMutexGuard<'a, T> {\n    fn drop(&mut self) {\n        unsafe {\n            self.inner.poison.done(&self.poison);\n            crate::ffi::PyMutex_Unlock(UnsafeCell::raw_get(&self.inner.mutex))\n        };\n    }\n}\n\nimpl<'a, T> Deref for PyMutexGuard<'a, T> {\n    type Target = T;\n\n    fn deref(&self) -> &T {\n        // safety: cannot be null pointer because PyMutex::new always\n        // creates a valid PyMutex pointer\n        unsafe { &*self.inner.data.get() }\n    }\n}\n\nimpl<'a, T> DerefMut for PyMutexGuard<'a, T> {\n    fn deref_mut(&mut self) -> &mut T {\n        // safety: cannot be null pointer because PyMutex::new always\n        // creates a valid PyMutex pointer\n        unsafe { &mut *self.inner.data.get() }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use std::sync::{\n        atomic::{AtomicBool, Ordering},\n        Arc, Barrier,\n    };\n\n    use super::*;\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use crate::types::{PyAnyMethods, PyDict, PyDictMethods, PyNone};\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use crate::Py;\n    #[cfg(not(target_arch = \"wasm32\"))]\n    use crate::Python;\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    #[test]\n    fn test_pymutex() {\n        let mutex = Python::attach(|py| -> PyMutex<Py<PyDict>> {\n            let d = PyDict::new(py);\n            PyMutex::new(d.unbind())\n        });\n        #[cfg_attr(not(Py_3_14), allow(unused_variables))]\n        let mutex = Python::attach(|py| {\n            let mutex = py.detach(|| -> PyMutex<Py<PyDict>> {\n                std::thread::spawn(|| {\n                    let dict_guard = mutex.lock().unwrap();\n                    Python::attach(|py| {\n                        let dict = dict_guard.bind(py);\n                        dict.set_item(PyNone::get(py), PyNone::get(py)).unwrap();\n                    });\n                    #[cfg(Py_3_14)]\n                    assert!(mutex.is_locked());\n                    drop(dict_guard);\n                    #[cfg(Py_3_14)]\n                    assert!(!mutex.is_locked());\n                    mutex\n                })\n                .join()\n                .unwrap()\n            });\n\n            let dict_guard = mutex.lock().unwrap();\n            #[cfg(Py_3_14)]\n            assert!(mutex.is_locked());\n            let d = dict_guard.bind(py);\n\n            assert!(d\n                .get_item(PyNone::get(py))\n                .unwrap()\n                .unwrap()\n                .eq(PyNone::get(py))\n                .unwrap());\n            #[cfg(Py_3_14)]\n            assert!(mutex.is_locked());\n            drop(dict_guard);\n            #[cfg(Py_3_14)]\n            assert!(!mutex.is_locked());\n            mutex\n        });\n        #[cfg(Py_3_14)]\n        assert!(!mutex.is_locked());\n    }\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    #[test]\n    fn test_pymutex_blocks() {\n        let mutex = PyMutex::new(());\n        let first_thread_locked_once = AtomicBool::new(false);\n        let second_thread_locked_once = AtomicBool::new(false);\n        let finished = AtomicBool::new(false);\n        let barrier = Barrier::new(2);\n\n        std::thread::scope(|s| {\n            s.spawn(|| {\n                let guard = mutex.lock();\n                first_thread_locked_once.store(true, Ordering::SeqCst);\n                while !finished.load(Ordering::SeqCst) {\n                    if second_thread_locked_once.load(Ordering::SeqCst) {\n                        // Wait a little to guard against the unlikely event that\n                        // the other thread isn't blocked on acquiring the mutex yet.\n                        // If PyMutex had a try_lock implementation this would be\n                        // unnecessary\n                        std::thread::sleep(std::time::Duration::from_millis(10));\n                        // block (and hold the mutex) until the receiver actually receives something\n                        barrier.wait();\n                        finished.store(true, Ordering::SeqCst);\n                    }\n                }\n                drop(guard);\n            });\n\n            s.spawn(|| {\n                while !first_thread_locked_once.load(Ordering::SeqCst) {\n                    std::hint::spin_loop();\n                }\n                second_thread_locked_once.store(true, Ordering::SeqCst);\n                let guard = mutex.lock();\n                assert!(finished.load(Ordering::SeqCst));\n                drop(guard);\n            });\n\n            barrier.wait();\n        });\n    }\n\n    #[cfg(not(target_arch = \"wasm32\"))]\n    #[test]\n    fn test_recover_poison() {\n        let mutex = Python::attach(|py| -> PyMutex<Py<PyDict>> {\n            let d = PyDict::new(py);\n            d.set_item(\"hello\", \"world\").unwrap();\n            PyMutex::new(d.unbind())\n        });\n\n        let lock = Arc::new(mutex);\n        let lock2 = Arc::clone(&lock);\n\n        let _ = thread::spawn(move || {\n            let _guard = lock2.lock().unwrap();\n\n            // poison the mutex\n            panic!();\n        })\n        .join();\n\n        // by now the lock is poisoned, use into_inner to recover the value despite that\n        let guard = match lock.lock() {\n            Ok(_) => {\n                unreachable!();\n            }\n            Err(poisoned) => poisoned.into_inner(),\n        };\n\n        Python::attach(|py| {\n            assert!(\n                (*guard)\n                    .bind(py)\n                    .get_item(\"hello\")\n                    .unwrap()\n                    .unwrap()\n                    .extract::<&str>()\n                    .unwrap()\n                    == \"world\"\n            );\n        });\n\n        // now test recovering via PyMutex::into_inner\n        let mutex = PyMutex::new(0);\n        assert_eq!(mutex.into_inner().unwrap(), 0);\n\n        let mutex = PyMutex::new(0);\n        let _ = std::thread::scope(|s| {\n            s.spawn(|| {\n                let _guard = mutex.lock().unwrap();\n\n                // poison the mutex\n                panic!();\n            })\n            .join()\n        });\n\n        match mutex.into_inner() {\n            Ok(_) => {\n                unreachable!()\n            }\n            Err(e) => {\n                assert!(e.into_inner() == 0)\n            }\n        }\n\n        // now test recovering via PyMutex::clear_poison\n        let mutex = PyMutex::new(0);\n        let _ = std::thread::scope(|s| {\n            s.spawn(|| {\n                let _guard = mutex.lock().unwrap();\n\n                // poison the mutex\n                panic!();\n            })\n            .join()\n        });\n        mutex.clear_poison();\n        assert_eq!(*mutex.lock().unwrap(), 0);\n    }\n\n    #[test]\n    fn test_send_not_send() {\n        use crate::impl_::pyclass::{value_of, IsSend, IsSync};\n\n        assert!(!value_of!(IsSend, PyMutexGuard<'_, i32>));\n        assert!(value_of!(IsSync, PyMutexGuard<'_, i32>));\n\n        assert!(value_of!(IsSend, PyMutex<i32>));\n        assert!(value_of!(IsSync, PyMutex<i32>));\n    }\n}\n"
  },
  {
    "path": "src/types/none.rs",
    "content": "use crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{PyStaticConstant, PyStaticExpr};\nuse crate::{ffi, types::any::PyAnyMethods, Borrowed, Bound, PyAny, PyTypeInfo, Python};\n\n/// Represents the Python `None` object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyNone>`][crate::Py] or [`Bound<'py, PyNone>`][Bound].\n#[repr(transparent)]\npub struct PyNone(PyAny);\n\npyobject_native_type_named!(PyNone);\n\nimpl PyNone {\n    /// Returns the `None` object.\n    #[inline]\n    pub fn get(py: Python<'_>) -> Borrowed<'_, '_, PyNone> {\n        // SAFETY: `Py_None` is a global singleton which is known to be the None object\n        unsafe {\n            ffi::Py_None()\n                .assume_borrowed_unchecked(py)\n                .cast_unchecked()\n        }\n    }\n}\n\nunsafe impl PyTypeInfo for PyNone {\n    const NAME: &'static str = \"NoneType\";\n    const MODULE: Option<&'static str> = None;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const TYPE_HINT: PyStaticExpr = PyStaticExpr::Constant {\n        value: PyStaticConstant::None,\n    };\n\n    fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject {\n        unsafe { ffi::Py_TYPE(ffi::Py_None()) }\n    }\n\n    #[inline]\n    fn is_type_of(object: &Bound<'_, PyAny>) -> bool {\n        // NoneType is not usable as a base type\n        Self::is_exact_type_of(object)\n    }\n\n    #[inline]\n    fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool {\n        object.is(&**Self::get(object.py()))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::any::PyAnyMethods;\n    use crate::types::{PyDict, PyNone};\n    use crate::{PyTypeInfo, Python};\n\n    #[test]\n    fn test_none_is_itself() {\n        Python::attach(|py| {\n            assert!(PyNone::get(py).is_instance_of::<PyNone>());\n            assert!(PyNone::get(py).is_exact_instance_of::<PyNone>());\n        })\n    }\n\n    #[test]\n    fn test_none_type_object_consistent() {\n        Python::attach(|py| {\n            assert!(PyNone::get(py).get_type().is(PyNone::type_object(py)));\n        })\n    }\n\n    #[test]\n    fn test_none_is_none() {\n        Python::attach(|py| {\n            assert!(PyNone::get(py).cast::<PyNone>().unwrap().is_none());\n        })\n    }\n\n    #[test]\n    fn test_dict_is_not_none() {\n        Python::attach(|py| {\n            assert!(PyDict::new(py).cast::<PyNone>().is_err());\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/notimplemented.rs",
    "content": "#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_identifier, PyStaticExpr};\nuse crate::{\n    ffi, ffi_ptr_ext::FfiPtrExt, types::any::PyAnyMethods, Borrowed, Bound, PyAny, PyTypeInfo,\n    Python,\n};\n\n/// Represents the Python `NotImplemented` object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyNotImplemented>`][crate::Py] or [`Bound<'py, PyNotImplemented>`][Bound].\n#[repr(transparent)]\npub struct PyNotImplemented(PyAny);\n\npyobject_native_type_named!(PyNotImplemented);\n\nimpl PyNotImplemented {\n    /// Returns the `NotImplemented` object.\n    #[inline]\n    pub fn get(py: Python<'_>) -> Borrowed<'_, '_, PyNotImplemented> {\n        // SAFETY: `Py_NotImplemented` is a global singleton which is known to be the NotImplemented object\n        unsafe {\n            ffi::Py_NotImplemented()\n                .assume_borrowed_unchecked(py)\n                .cast_unchecked()\n        }\n    }\n}\n\nunsafe impl PyTypeInfo for PyNotImplemented {\n    const NAME: &'static str = \"NotImplementedType\";\n    const MODULE: Option<&'static str> = None;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const TYPE_HINT: PyStaticExpr = type_hint_identifier!(\"types\", \"NotImplementedType\");\n\n    fn type_object_raw(_py: Python<'_>) -> *mut ffi::PyTypeObject {\n        unsafe { ffi::Py_TYPE(ffi::Py_NotImplemented()) }\n    }\n\n    #[inline]\n    fn is_type_of(object: &Bound<'_, PyAny>) -> bool {\n        // NotImplementedType is not usable as a base type\n        Self::is_exact_type_of(object)\n    }\n\n    #[inline]\n    fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool {\n        object.is(&**Self::get(object.py()))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::any::PyAnyMethods;\n    use crate::types::{PyDict, PyNotImplemented};\n    use crate::{PyTypeInfo, Python};\n\n    #[test]\n    fn test_notimplemented_is_itself() {\n        Python::attach(|py| {\n            assert!(PyNotImplemented::get(py).is_instance_of::<PyNotImplemented>());\n            assert!(PyNotImplemented::get(py).is_exact_instance_of::<PyNotImplemented>());\n        })\n    }\n\n    #[test]\n    fn test_notimplemented_type_object_consistent() {\n        Python::attach(|py| {\n            assert!(PyNotImplemented::get(py)\n                .get_type()\n                .is(PyNotImplemented::type_object(py)));\n        })\n    }\n\n    #[test]\n    fn test_dict_is_not_notimplemented() {\n        Python::attach(|py| {\n            assert!(PyDict::new(py).cast::<PyNotImplemented>().is_err());\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/num.rs",
    "content": "use super::any::PyAnyMethods;\nuse crate::{ffi, instance::Bound, IntoPyObject, PyAny, Python};\nuse std::convert::Infallible;\n\n/// Represents a Python `int` object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyInt>`][crate::Py] or [`Bound<'py, PyInt>`][crate::Bound].\n///\n/// You can usually avoid directly working with this type by using\n/// [`IntoPyObject`] and [`extract`](super::PyAnyMethods::extract)\n/// with the primitive Rust integer types.\n#[repr(transparent)]\npub struct PyInt(PyAny);\n\npyobject_native_type_core!(PyInt, pyobject_native_static_type_object!(ffi::PyLong_Type), \"builtins\", \"int\", #checkfunction=ffi::PyLong_Check);\n\nimpl PyInt {\n    /// Creates a new Python int object.\n    ///\n    /// Panics if out of memory.\n    pub fn new<'a, T>(py: Python<'a>, i: T) -> Bound<'a, PyInt>\n    where\n        T: IntoPyObject<'a, Target = PyInt, Output = Bound<'a, PyInt>, Error = Infallible>,\n    {\n        match T::into_pyobject(i, py) {\n            Ok(v) => v,\n            Err(never) => match never {},\n        }\n    }\n}\n\nmacro_rules! int_compare {\n    ($rust_type: ty) => {\n        impl PartialEq<$rust_type> for Bound<'_, PyInt> {\n            #[inline]\n            fn eq(&self, other: &$rust_type) -> bool {\n                if let Ok(value) = self.extract::<$rust_type>() {\n                    value == *other\n                } else {\n                    false\n                }\n            }\n        }\n        impl PartialEq<Bound<'_, PyInt>> for $rust_type {\n            #[inline]\n            fn eq(&self, other: &Bound<'_, PyInt>) -> bool {\n                if let Ok(value) = other.extract::<$rust_type>() {\n                    value == *self\n                } else {\n                    false\n                }\n            }\n        }\n    };\n}\n\nint_compare!(i8);\nint_compare!(u8);\nint_compare!(i16);\nint_compare!(u16);\nint_compare!(i32);\nint_compare!(u32);\nint_compare!(i64);\nint_compare!(u64);\nint_compare!(i128);\nint_compare!(u128);\nint_compare!(isize);\nint_compare!(usize);\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::{IntoPyObject, Python};\n\n    #[test]\n    fn test_partial_eq() {\n        Python::attach(|py| {\n            let v_i8 = 123i8;\n            let v_u8 = 123i8;\n            let v_i16 = 123i16;\n            let v_u16 = 123u16;\n            let v_i32 = 123i32;\n            let v_u32 = 123u32;\n            let v_i64 = 123i64;\n            let v_u64 = 123u64;\n            let v_i128 = 123i128;\n            let v_u128 = 123u128;\n            let v_isize = 123isize;\n            let v_usize = 123usize;\n            let obj = 123_i64.into_pyobject(py).unwrap();\n            assert_eq!(v_i8, obj);\n            assert_eq!(obj, v_i8);\n\n            assert_eq!(v_u8, obj);\n            assert_eq!(obj, v_u8);\n\n            assert_eq!(v_i16, obj);\n            assert_eq!(obj, v_i16);\n\n            assert_eq!(v_u16, obj);\n            assert_eq!(obj, v_u16);\n\n            assert_eq!(v_i32, obj);\n            assert_eq!(obj, v_i32);\n\n            assert_eq!(v_u32, obj);\n            assert_eq!(obj, v_u32);\n\n            assert_eq!(v_i64, obj);\n            assert_eq!(obj, v_i64);\n\n            assert_eq!(v_u64, obj);\n            assert_eq!(obj, v_u64);\n\n            assert_eq!(v_i128, obj);\n            assert_eq!(obj, v_i128);\n\n            assert_eq!(v_u128, obj);\n            assert_eq!(obj, v_u128);\n\n            assert_eq!(v_isize, obj);\n            assert_eq!(obj, v_isize);\n\n            assert_eq!(v_usize, obj);\n            assert_eq!(obj, v_usize);\n\n            let big_num = (u8::MAX as u16) + 1;\n            let big_obj = big_num.into_pyobject(py).unwrap();\n\n            for x in 0u8..=u8::MAX {\n                assert_ne!(x, big_obj);\n                assert_ne!(big_obj, x);\n            }\n        });\n    }\n\n    #[test]\n    fn test_display_int() {\n        Python::attach(|py| {\n            let s = PyInt::new(py, 42u8);\n            assert_eq!(format!(\"{s}\"), \"42\");\n\n            let s = PyInt::new(py, 43i32);\n            assert_eq!(format!(\"{s}\"), \"43\");\n\n            let s = PyInt::new(py, 44usize);\n            assert_eq!(format!(\"{s}\"), \"44\");\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/pysuper.rs",
    "content": "use crate::instance::Bound;\nuse crate::types::any::PyAnyMethods;\nuse crate::types::PyType;\nuse crate::PyTypeInfo;\nuse crate::{PyAny, PyResult};\n\n/// Represents a Python `super` object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PySuper>`][crate::Py] or [`Bound<'py, PySuper>`][Bound].\n#[repr(transparent)]\npub struct PySuper(PyAny);\n\n#[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\npyobject_native_type_core!(\n    PySuper,\n    pyobject_native_static_type_object!(crate::ffi::PySuper_Type),\n    \"builtins\",\n    \"super\"\n);\n\n#[cfg(any(Py_LIMITED_API, PyPy, GraalPy))]\npyobject_native_type_core!(\n    PySuper,\n    |py| {\n        use crate::sync::PyOnceLock;\n        use crate::types::{PyType, PyTypeMethods};\n        use crate::Py;\n        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        TYPE.import(py, \"builtins\", \"super\").unwrap().as_type_ptr()\n    },\n    \"builtins\",\n    \"super\"\n);\n\nimpl PySuper {\n    /// Constructs a new super object. More read about super object: [docs](https://docs.python.org/3/library/functions.html#super)\n    ///\n    /// # Examples\n    ///\n    /// ```rust,no_run\n    /// use pyo3::prelude::*;\n    ///\n    /// #[pyclass(subclass)]\n    /// struct BaseClass {\n    ///     val1: usize,\n    /// }\n    ///\n    /// #[pymethods]\n    /// impl BaseClass {\n    ///     #[new]\n    ///     fn new() -> Self {\n    ///         BaseClass { val1: 10 }\n    ///     }\n    ///\n    ///     pub fn method(&self) -> usize {\n    ///         self.val1\n    ///     }\n    /// }\n    ///\n    /// #[pyclass(extends=BaseClass)]\n    /// struct SubClass {}\n    ///\n    /// #[pymethods]\n    /// impl SubClass {\n    ///     #[new]\n    ///     fn new() -> (Self, BaseClass) {\n    ///         (SubClass {}, BaseClass::new())\n    ///     }\n    ///\n    ///     fn method<'py>(self_: &Bound<'py, Self>) -> PyResult<Bound<'py, PyAny>> {\n    ///         let super_ = self_.py_super()?;\n    ///         super_.call_method(\"method\", (), None)\n    ///     }\n    /// }\n    /// ```\n    pub fn new<'py>(\n        ty: &Bound<'py, PyType>,\n        obj: &Bound<'py, PyAny>,\n    ) -> PyResult<Bound<'py, PySuper>> {\n        PySuper::type_object(ty.py()).call1((ty, obj)).map(|any| {\n            // Safety: super() always returns instance of super\n            unsafe { any.cast_into_unchecked() }\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/range.rs",
    "content": "use crate::sealed::Sealed;\nuse crate::types::PyAnyMethods;\nuse crate::{ffi, Bound, PyAny, PyResult, PyTypeInfo, Python};\n\n/// Represents a Python `range`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyRange>`][crate::Py] or [`Bound<'py, PyRange>`][Bound].\n///\n/// For APIs available on `range` objects, see the [`PyRangeMethods`] trait which is implemented for\n/// [`Bound<'py, PyRange>`][Bound].\n#[repr(transparent)]\npub struct PyRange(PyAny);\n\npyobject_native_type_core!(PyRange, pyobject_native_static_type_object!(ffi::PyRange_Type), \"builtins\", \"range\", #checkfunction=ffi::PyRange_Check);\n\nimpl<'py> PyRange {\n    /// Creates a new Python `range` object with a default step of 1.\n    pub fn new(py: Python<'py>, start: isize, stop: isize) -> PyResult<Bound<'py, Self>> {\n        Self::new_with_step(py, start, stop, 1)\n    }\n\n    /// Creates a new Python `range` object with a specified step.\n    pub fn new_with_step(\n        py: Python<'py>,\n        start: isize,\n        stop: isize,\n        step: isize,\n    ) -> PyResult<Bound<'py, Self>> {\n        unsafe {\n            Ok(Self::type_object(py)\n                .call1((start, stop, step))?\n                .cast_into_unchecked())\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyRange`].\n///\n/// These methods are defined for the `Bound<'py, PyRange>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyRange\")]\npub trait PyRangeMethods<'py>: Sealed {\n    /// Returns the start of the range.\n    fn start(&self) -> PyResult<isize>;\n\n    /// Returns the exclusive end of the range.\n    fn stop(&self) -> PyResult<isize>;\n\n    /// Returns the step of the range.\n    fn step(&self) -> PyResult<isize>;\n}\n\nimpl<'py> PyRangeMethods<'py> for Bound<'py, PyRange> {\n    fn start(&self) -> PyResult<isize> {\n        self.getattr(intern!(self.py(), \"start\"))?.extract()\n    }\n\n    fn stop(&self) -> PyResult<isize> {\n        self.getattr(intern!(self.py(), \"stop\"))?.extract()\n    }\n\n    fn step(&self) -> PyResult<isize> {\n        self.getattr(intern!(self.py(), \"step\"))?.extract()\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_py_range_new() {\n        Python::attach(|py| {\n            let range = PyRange::new(py, isize::MIN, isize::MAX).unwrap();\n            assert_eq!(range.start().unwrap(), isize::MIN);\n            assert_eq!(range.stop().unwrap(), isize::MAX);\n            assert_eq!(range.step().unwrap(), 1);\n        });\n    }\n\n    #[test]\n    fn test_py_range_new_with_step() {\n        Python::attach(|py| {\n            let range = PyRange::new_with_step(py, 1, 10, 2).unwrap();\n            assert_eq!(range.start().unwrap(), 1);\n            assert_eq!(range.stop().unwrap(), 10);\n            assert_eq!(range.step().unwrap(), 2);\n        });\n    }\n}\n"
  },
  {
    "path": "src/types/sequence.rs",
    "content": "use crate::err::{self, PyErr, PyResult};\nuse crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_identifier, PyStaticExpr};\nuse crate::instance::Bound;\nuse crate::internal_tricks::get_ssize_index;\nuse crate::py_result_ext::PyResultExt;\nuse crate::sync::PyOnceLock;\nuse crate::type_object::PyTypeInfo;\nuse crate::types::{any::PyAnyMethods, PyAny, PyList, PyTuple, PyType, PyTypeMethods};\nuse crate::{ffi, Borrowed, BoundObject, IntoPyObject, IntoPyObjectExt, Py, Python};\n\n/// Represents a reference to a Python object supporting the sequence protocol.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PySequence>`][crate::Py] or [`Bound<'py, PySequence>`][Bound].\n///\n/// For APIs available on sequence objects, see the [`PySequenceMethods`] trait which is implemented for\n/// [`Bound<'py, PySequence>`][Bound].\n#[repr(transparent)]\npub struct PySequence(PyAny);\n\npyobject_native_type_named!(PySequence);\n\nunsafe impl PyTypeInfo for PySequence {\n    const NAME: &'static str = \"Sequence\";\n    const MODULE: Option<&'static str> = Some(\"collections.abc\");\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const TYPE_HINT: PyStaticExpr = type_hint_identifier!(\"collections.abc\", \"Sequence\");\n\n    #[inline]\n    fn type_object_raw(py: Python<'_>) -> *mut ffi::PyTypeObject {\n        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        TYPE.import(py, \"collections.abc\", \"Sequence\")\n            .unwrap()\n            .as_type_ptr()\n    }\n\n    #[inline]\n    fn is_type_of(object: &Bound<'_, PyAny>) -> bool {\n        // Using `is_instance` for `collections.abc.Sequence` is slow, so provide\n        // optimized cases for list and tuples as common well-known sequences\n        PyList::is_type_of(object)\n            || PyTuple::is_type_of(object)\n            || object\n                .is_instance(&Self::type_object(object.py()).into_any())\n                .unwrap_or_else(|err| {\n                    err.write_unraisable(object.py(), Some(object));\n                    false\n                })\n    }\n}\n\nimpl PySequence {\n    /// Register a pyclass as a subclass of `collections.abc.Sequence` (from the Python standard\n    /// library). This is equivalent to `collections.abc.Sequence.register(T)` in Python.\n    /// This registration is required for a pyclass to be castable from `PyAny` to `PySequence`.\n    pub fn register<T: PyTypeInfo>(py: Python<'_>) -> PyResult<()> {\n        let ty = T::type_object(py);\n        Self::type_object(py).call_method1(\"register\", (ty,))?;\n        Ok(())\n    }\n}\n\n/// Implementation of functionality for [`PySequence`].\n///\n/// These methods are defined for the `Bound<'py, PySequence>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PySequence\")]\npub trait PySequenceMethods<'py>: crate::sealed::Sealed {\n    /// Returns the number of objects in sequence.\n    ///\n    /// This is equivalent to the Python expression `len(self)`.\n    fn len(&self) -> PyResult<usize>;\n\n    /// Returns whether the sequence is empty.\n    fn is_empty(&self) -> PyResult<bool>;\n\n    /// Returns the concatenation of `self` and `other`.\n    ///\n    /// This is equivalent to the Python expression `self + other`.\n    fn concat(&self, other: &Bound<'_, PySequence>) -> PyResult<Bound<'py, PySequence>>;\n\n    /// Returns the result of repeating a sequence object `count` times.\n    ///\n    /// This is equivalent to the Python expression `self * count`.\n    fn repeat(&self, count: usize) -> PyResult<Bound<'py, PySequence>>;\n\n    /// Concatenates `self` and `other`, in place if possible.\n    ///\n    /// This is equivalent to the Python expression `self.__iadd__(other)`.\n    ///\n    /// The Python statement `self += other` is syntactic sugar for `self =\n    /// self.__iadd__(other)`.  `__iadd__` should modify and return `self` if\n    /// possible, but create and return a new object if not.\n    fn in_place_concat(&self, other: &Bound<'_, PySequence>) -> PyResult<Bound<'py, PySequence>>;\n\n    /// Repeats the sequence object `count` times and updates `self`, if possible.\n    ///\n    /// This is equivalent to the Python expression `self.__imul__(other)`.\n    ///\n    /// The Python statement `self *= other` is syntactic sugar for `self =\n    /// self.__imul__(other)`.  `__imul__` should modify and return `self` if\n    /// possible, but create and return a new object if not.\n    fn in_place_repeat(&self, count: usize) -> PyResult<Bound<'py, PySequence>>;\n\n    /// Returns the `index`th element of the Sequence.\n    ///\n    /// This is equivalent to the Python expression `self[index]` without support of negative indices.\n    fn get_item(&self, index: usize) -> PyResult<Bound<'py, PyAny>>;\n\n    /// Returns the slice of sequence object between `begin` and `end`.\n    ///\n    /// This is equivalent to the Python expression `self[begin:end]`.\n    fn get_slice(&self, begin: usize, end: usize) -> PyResult<Bound<'py, PySequence>>;\n\n    /// Assigns object `item` to the `i`th element of self.\n    ///\n    /// This is equivalent to the Python statement `self[i] = v`.\n    fn set_item<I>(&self, i: usize, item: I) -> PyResult<()>\n    where\n        I: IntoPyObject<'py>;\n\n    /// Deletes the `i`th element of self.\n    ///\n    /// This is equivalent to the Python statement `del self[i]`.\n    fn del_item(&self, i: usize) -> PyResult<()>;\n\n    /// Assigns the sequence `v` to the slice of `self` from `i1` to `i2`.\n    ///\n    /// This is equivalent to the Python statement `self[i1:i2] = v`.\n    fn set_slice(&self, i1: usize, i2: usize, v: &Bound<'_, PyAny>) -> PyResult<()>;\n\n    /// Deletes the slice from `i1` to `i2` from `self`.\n    ///\n    /// This is equivalent to the Python statement `del self[i1:i2]`.\n    fn del_slice(&self, i1: usize, i2: usize) -> PyResult<()>;\n\n    /// Returns the number of occurrences of `value` in self, that is, return the\n    /// number of keys for which `self[key] == value`.\n    #[cfg(not(PyPy))]\n    fn count<V>(&self, value: V) -> PyResult<usize>\n    where\n        V: IntoPyObject<'py>;\n\n    /// Determines if self contains `value`.\n    ///\n    /// This is equivalent to the Python expression `value in self`.\n    fn contains<V>(&self, value: V) -> PyResult<bool>\n    where\n        V: IntoPyObject<'py>;\n\n    /// Returns the first index `i` for which `self[i] == value`.\n    ///\n    /// This is equivalent to the Python expression `self.index(value)`.\n    fn index<V>(&self, value: V) -> PyResult<usize>\n    where\n        V: IntoPyObject<'py>;\n\n    /// Returns a fresh list based on the Sequence.\n    fn to_list(&self) -> PyResult<Bound<'py, PyList>>;\n\n    /// Returns a fresh tuple based on the Sequence.\n    fn to_tuple(&self) -> PyResult<Bound<'py, PyTuple>>;\n}\n\nimpl<'py> PySequenceMethods<'py> for Bound<'py, PySequence> {\n    #[inline]\n    fn len(&self) -> PyResult<usize> {\n        let v = unsafe { ffi::PySequence_Size(self.as_ptr()) };\n        crate::err::error_on_minusone(self.py(), v)?;\n        Ok(v as usize)\n    }\n\n    #[inline]\n    fn is_empty(&self) -> PyResult<bool> {\n        self.len().map(|l| l == 0)\n    }\n\n    #[inline]\n    fn concat(&self, other: &Bound<'_, PySequence>) -> PyResult<Bound<'py, PySequence>> {\n        unsafe {\n            ffi::PySequence_Concat(self.as_ptr(), other.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    #[inline]\n    fn repeat(&self, count: usize) -> PyResult<Bound<'py, PySequence>> {\n        unsafe {\n            ffi::PySequence_Repeat(self.as_ptr(), get_ssize_index(count))\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    #[inline]\n    fn in_place_concat(&self, other: &Bound<'_, PySequence>) -> PyResult<Bound<'py, PySequence>> {\n        unsafe {\n            ffi::PySequence_InPlaceConcat(self.as_ptr(), other.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    #[inline]\n    fn in_place_repeat(&self, count: usize) -> PyResult<Bound<'py, PySequence>> {\n        unsafe {\n            ffi::PySequence_InPlaceRepeat(self.as_ptr(), get_ssize_index(count))\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    #[inline]\n    fn get_item(&self, index: usize) -> PyResult<Bound<'py, PyAny>> {\n        unsafe {\n            ffi::PySequence_GetItem(self.as_ptr(), get_ssize_index(index))\n                .assume_owned_or_err(self.py())\n        }\n    }\n\n    #[inline]\n    fn get_slice(&self, begin: usize, end: usize) -> PyResult<Bound<'py, PySequence>> {\n        unsafe {\n            ffi::PySequence_GetSlice(self.as_ptr(), get_ssize_index(begin), get_ssize_index(end))\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    #[inline]\n    fn set_item<I>(&self, i: usize, item: I) -> PyResult<()>\n    where\n        I: IntoPyObject<'py>,\n    {\n        fn inner(\n            seq: &Bound<'_, PySequence>,\n            i: usize,\n            item: Borrowed<'_, '_, PyAny>,\n        ) -> PyResult<()> {\n            err::error_on_minusone(seq.py(), unsafe {\n                ffi::PySequence_SetItem(seq.as_ptr(), get_ssize_index(i), item.as_ptr())\n            })\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            i,\n            item.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    #[inline]\n    fn del_item(&self, i: usize) -> PyResult<()> {\n        err::error_on_minusone(self.py(), unsafe {\n            ffi::PySequence_DelItem(self.as_ptr(), get_ssize_index(i))\n        })\n    }\n\n    #[inline]\n    fn set_slice(&self, i1: usize, i2: usize, v: &Bound<'_, PyAny>) -> PyResult<()> {\n        err::error_on_minusone(self.py(), unsafe {\n            ffi::PySequence_SetSlice(\n                self.as_ptr(),\n                get_ssize_index(i1),\n                get_ssize_index(i2),\n                v.as_ptr(),\n            )\n        })\n    }\n\n    #[inline]\n    fn del_slice(&self, i1: usize, i2: usize) -> PyResult<()> {\n        err::error_on_minusone(self.py(), unsafe {\n            ffi::PySequence_DelSlice(self.as_ptr(), get_ssize_index(i1), get_ssize_index(i2))\n        })\n    }\n\n    #[inline]\n    #[cfg(not(PyPy))]\n    fn count<V>(&self, value: V) -> PyResult<usize>\n    where\n        V: IntoPyObject<'py>,\n    {\n        fn inner(seq: &Bound<'_, PySequence>, value: Borrowed<'_, '_, PyAny>) -> PyResult<usize> {\n            let r = unsafe { ffi::PySequence_Count(seq.as_ptr(), value.as_ptr()) };\n            crate::err::error_on_minusone(seq.py(), r)?;\n            Ok(r as usize)\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    #[inline]\n    fn contains<V>(&self, value: V) -> PyResult<bool>\n    where\n        V: IntoPyObject<'py>,\n    {\n        fn inner(seq: &Bound<'_, PySequence>, value: Borrowed<'_, '_, PyAny>) -> PyResult<bool> {\n            let r = unsafe { ffi::PySequence_Contains(seq.as_ptr(), value.as_ptr()) };\n            match r {\n                0 => Ok(false),\n                1 => Ok(true),\n                _ => Err(PyErr::fetch(seq.py())),\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    #[inline]\n    fn index<V>(&self, value: V) -> PyResult<usize>\n    where\n        V: IntoPyObject<'py>,\n    {\n        fn inner(seq: &Bound<'_, PySequence>, value: Borrowed<'_, '_, PyAny>) -> PyResult<usize> {\n            let r = unsafe { ffi::PySequence_Index(seq.as_ptr(), value.as_ptr()) };\n            crate::err::error_on_minusone(seq.py(), r)?;\n            Ok(r as usize)\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            value.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    #[inline]\n    fn to_list(&self) -> PyResult<Bound<'py, PyList>> {\n        unsafe {\n            ffi::PySequence_List(self.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    #[inline]\n    fn to_tuple(&self) -> PyResult<Bound<'py, PyTuple>> {\n        unsafe {\n            ffi::PySequence_Tuple(self.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked()\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::{PyAnyMethods, PyList, PySequence, PySequenceMethods, PyTuple};\n    use crate::{IntoPyObject, Py, PyAny, PyTypeInfo, Python};\n    use std::ptr;\n\n    fn get_object() -> Py<PyAny> {\n        // Convenience function for getting a single unique object\n        Python::attach(|py| {\n            let obj = py.eval(c\"object()\", None, None).unwrap();\n\n            obj.into_pyobject(py).unwrap().unbind()\n        })\n    }\n\n    #[test]\n    fn test_numbers_are_not_sequences() {\n        Python::attach(|py| {\n            let v = 42i32;\n            assert!(v.into_pyobject(py).unwrap().cast::<PySequence>().is_err());\n        });\n    }\n\n    #[test]\n    fn test_strings_are_sequences() {\n        Python::attach(|py| {\n            let v = \"London Calling\";\n            assert!(v.into_pyobject(py).unwrap().cast::<PySequence>().is_ok());\n        });\n    }\n\n    #[test]\n    fn test_seq_empty() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert_eq!(0, seq.len().unwrap());\n\n            let needle = 7i32.into_pyobject(py).unwrap();\n            assert!(!seq.contains(&needle).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_seq_is_empty() {\n        Python::attach(|py| {\n            let list = vec![1].into_pyobject(py).unwrap();\n            let seq = list.cast::<PySequence>().unwrap();\n            assert!(!seq.is_empty().unwrap());\n            let vec: Vec<u32> = Vec::new();\n            let empty_list = vec.into_pyobject(py).unwrap();\n            let empty_seq = empty_list.cast::<PySequence>().unwrap();\n            assert!(empty_seq.is_empty().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_seq_contains() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert_eq!(6, seq.len().unwrap());\n\n            let bad_needle = 7i32.into_pyobject(py).unwrap();\n            assert!(!seq.contains(&bad_needle).unwrap());\n\n            let good_needle = 8i32.into_pyobject(py).unwrap();\n            assert!(seq.contains(&good_needle).unwrap());\n\n            let type_coerced_needle = 8f32.into_pyobject(py).unwrap();\n            assert!(seq.contains(&type_coerced_needle).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_seq_get_item() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert_eq!(1, seq.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert_eq!(1, seq.get_item(1).unwrap().extract::<i32>().unwrap());\n            assert_eq!(2, seq.get_item(2).unwrap().extract::<i32>().unwrap());\n            assert_eq!(3, seq.get_item(3).unwrap().extract::<i32>().unwrap());\n            assert_eq!(5, seq.get_item(4).unwrap().extract::<i32>().unwrap());\n            assert_eq!(8, seq.get_item(5).unwrap().extract::<i32>().unwrap());\n            assert!(seq.get_item(10).is_err());\n        });\n    }\n\n    #[test]\n    fn test_seq_del_item() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert!(seq.del_item(10).is_err());\n            assert_eq!(1, seq.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(seq.del_item(0).is_ok());\n            assert_eq!(1, seq.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(seq.del_item(0).is_ok());\n            assert_eq!(2, seq.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(seq.del_item(0).is_ok());\n            assert_eq!(3, seq.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(seq.del_item(0).is_ok());\n            assert_eq!(5, seq.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(seq.del_item(0).is_ok());\n            assert_eq!(8, seq.get_item(0).unwrap().extract::<i32>().unwrap());\n            assert!(seq.del_item(0).is_ok());\n            assert_eq!(0, seq.len().unwrap());\n            assert!(seq.del_item(0).is_err());\n        });\n    }\n\n    #[test]\n    fn test_seq_set_item() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 2];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert_eq!(2, seq.get_item(1).unwrap().extract::<i32>().unwrap());\n            assert!(seq.set_item(1, 10).is_ok());\n            assert_eq!(10, seq.get_item(1).unwrap().extract::<i32>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_seq_set_item_refcnt() {\n        let obj = get_object();\n\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 2];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert!(seq.set_item(1, &obj).is_ok());\n            assert!(ptr::eq(seq.get_item(1).unwrap().as_ptr(), obj.as_ptr()));\n        });\n\n        Python::attach(move |py| {\n            assert_eq!(1, obj._get_refcnt(py));\n        });\n    }\n\n    #[test]\n    fn test_seq_get_slice() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert_eq!(\n                [1, 2, 3],\n                seq.get_slice(1, 4).unwrap().extract::<[i32; 3]>().unwrap()\n            );\n            assert_eq!(\n                [3, 5, 8],\n                seq.get_slice(3, 100)\n                    .unwrap()\n                    .extract::<[i32; 3]>()\n                    .unwrap()\n            );\n        });\n    }\n\n    #[test]\n    fn test_set_slice() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];\n            let w: Vec<i32> = vec![7, 4];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            let ins = w.into_pyobject(py).unwrap();\n            seq.set_slice(1, 4, &ins).unwrap();\n            assert_eq!([1, 7, 4, 5, 8], seq.extract::<[i32; 5]>().unwrap());\n            seq.set_slice(3, 100, &PyList::empty(py)).unwrap();\n            assert_eq!([1, 7, 4], seq.extract::<[i32; 3]>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_del_slice() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            seq.del_slice(1, 4).unwrap();\n            assert_eq!([1, 5, 8], seq.extract::<[i32; 3]>().unwrap());\n            seq.del_slice(1, 100).unwrap();\n            assert_eq!([1], seq.extract::<[i32; 1]>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_seq_index() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert_eq!(0, seq.index(1i32).unwrap());\n            assert_eq!(2, seq.index(2i32).unwrap());\n            assert_eq!(3, seq.index(3i32).unwrap());\n            assert_eq!(4, seq.index(5i32).unwrap());\n            assert_eq!(5, seq.index(8i32).unwrap());\n            assert!(seq.index(42i32).is_err());\n        });\n    }\n\n    #[test]\n    #[cfg(not(any(PyPy, GraalPy)))]\n    fn test_seq_count() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert_eq!(2, seq.count(1i32).unwrap());\n            assert_eq!(1, seq.count(2i32).unwrap());\n            assert_eq!(1, seq.count(3i32).unwrap());\n            assert_eq!(1, seq.count(5i32).unwrap());\n            assert_eq!(1, seq.count(8i32).unwrap());\n            assert_eq!(0, seq.count(42i32).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_seq_iter() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 1, 2, 3, 5, 8];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            let mut idx = 0;\n            for el in seq.try_iter().unwrap() {\n                assert_eq!(v[idx], el.unwrap().extract::<i32>().unwrap());\n                idx += 1;\n            }\n            assert_eq!(idx, v.len());\n        });\n    }\n\n    #[test]\n    fn test_seq_strings() {\n        Python::attach(|py| {\n            let v = vec![\"It\", \"was\", \"the\", \"worst\", \"of\", \"times\"];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n\n            let bad_needle = \"blurst\".into_pyobject(py).unwrap();\n            assert!(!seq.contains(bad_needle).unwrap());\n\n            let good_needle = \"worst\".into_pyobject(py).unwrap();\n            assert!(seq.contains(good_needle).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_seq_concat() {\n        Python::attach(|py| {\n            let v: Vec<i32> = vec![1, 2, 3];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            let concat_seq = seq.concat(seq).unwrap();\n            assert_eq!(6, concat_seq.len().unwrap());\n            let concat_v: Vec<i32> = vec![1, 2, 3, 1, 2, 3];\n            for (el, cc) in concat_seq.try_iter().unwrap().zip(concat_v) {\n                assert_eq!(cc, el.unwrap().extract::<i32>().unwrap());\n            }\n        });\n    }\n\n    #[test]\n    fn test_seq_concat_string() {\n        Python::attach(|py| {\n            let v = \"string\";\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            let concat_seq = seq.concat(seq).unwrap();\n            assert_eq!(12, concat_seq.len().unwrap());\n            let concat_v = \"stringstring\".to_owned();\n            for (el, cc) in seq.try_iter().unwrap().zip(concat_v.chars()) {\n                assert_eq!(cc, el.unwrap().extract::<char>().unwrap());\n            }\n        });\n    }\n\n    #[test]\n    fn test_seq_repeat() {\n        Python::attach(|py| {\n            let v = vec![\"foo\", \"bar\"];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            let repeat_seq = seq.repeat(3).unwrap();\n            assert_eq!(6, repeat_seq.len().unwrap());\n            let repeated = [\"foo\", \"bar\", \"foo\", \"bar\", \"foo\", \"bar\"];\n            for (el, rpt) in repeat_seq.try_iter().unwrap().zip(repeated.iter()) {\n                assert_eq!(*rpt, el.unwrap().extract::<String>().unwrap());\n            }\n        });\n    }\n\n    #[test]\n    fn test_seq_inplace() {\n        Python::attach(|py| {\n            let v = vec![\"foo\", \"bar\"];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            let rep_seq = seq.in_place_repeat(3).unwrap();\n            assert_eq!(6, seq.len().unwrap());\n            assert!(seq.is(&rep_seq));\n\n            let conc_seq = seq.in_place_concat(seq).unwrap();\n            assert_eq!(12, seq.len().unwrap());\n            assert!(seq.is(&conc_seq));\n        });\n    }\n\n    #[test]\n    fn test_list_coercion() {\n        Python::attach(|py| {\n            let v = vec![\"foo\", \"bar\"];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert!(seq\n                .to_list()\n                .unwrap()\n                .eq(PyList::new(py, &v).unwrap())\n                .unwrap());\n        });\n    }\n\n    #[test]\n    fn test_strings_coerce_to_lists() {\n        Python::attach(|py| {\n            let v = \"foo\";\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert!(seq\n                .to_list()\n                .unwrap()\n                .eq(PyList::new(py, [\"f\", \"o\", \"o\"]).unwrap())\n                .unwrap());\n        });\n    }\n\n    #[test]\n    fn test_tuple_coercion() {\n        Python::attach(|py| {\n            let v = (\"foo\", \"bar\");\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert!(seq\n                .to_tuple()\n                .unwrap()\n                .eq(PyTuple::new(py, [\"foo\", \"bar\"]).unwrap())\n                .unwrap());\n        });\n    }\n\n    #[test]\n    fn test_lists_coerce_to_tuples() {\n        Python::attach(|py| {\n            let v = vec![\"foo\", \"bar\"];\n            let ob = (&v).into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            assert!(seq\n                .to_tuple()\n                .unwrap()\n                .eq(PyTuple::new(py, &v).unwrap())\n                .unwrap());\n        });\n    }\n\n    #[test]\n    fn test_seq_cast_unchecked() {\n        Python::attach(|py| {\n            let v = vec![\"foo\", \"bar\"];\n            let ob = v.into_pyobject(py).unwrap();\n            let seq = ob.cast::<PySequence>().unwrap();\n            let type_ptr = seq.as_any();\n            let seq_from = unsafe { type_ptr.cast_unchecked::<PySequence>() };\n            assert!(seq_from.to_list().is_ok());\n        });\n    }\n\n    #[test]\n    fn test_type_object() {\n        Python::attach(|py| {\n            let abc = PySequence::type_object(py);\n            assert!(PyList::empty(py).is_instance(&abc).unwrap());\n            assert!(PyTuple::empty(py).is_instance(&abc).unwrap());\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/set.rs",
    "content": "use crate::types::PyIterator;\nuse crate::{\n    err::{self, PyErr, PyResult},\n    ffi_ptr_ext::FfiPtrExt,\n    instance::Bound,\n    py_result_ext::PyResultExt,\n};\nuse crate::{ffi, Borrowed, BoundObject, IntoPyObject, IntoPyObjectExt, PyAny, Python};\nuse std::ptr;\n\n/// Represents a Python `set`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PySet>`][crate::Py] or [`Bound<'py, PySet>`][Bound].\n///\n/// For APIs available on `set` objects, see the [`PySetMethods`] trait which is implemented for\n/// [`Bound<'py, PySet>`][Bound].\n#[repr(transparent)]\npub struct PySet(PyAny);\n\n#[cfg(not(any(PyPy, GraalPy)))]\npyobject_subclassable_native_type!(PySet, crate::ffi::PySetObject);\n\n#[cfg(not(any(PyPy, GraalPy)))]\npyobject_native_type!(\n    PySet,\n    ffi::PySetObject,\n    pyobject_native_static_type_object!(ffi::PySet_Type),\n    \"builtins\",\n    \"set\",\n    #checkfunction=ffi::PySet_Check\n);\n\n#[cfg(any(PyPy, GraalPy))]\npyobject_native_type_core!(\n    PySet,\n    pyobject_native_static_type_object!(ffi::PySet_Type),\n    \"builtins\",\n    \"set\",\n    #checkfunction=ffi::PySet_Check\n);\n\nimpl PySet {\n    /// Creates a new set with elements from the given slice.\n    ///\n    /// Returns an error if some element is not hashable.\n    #[inline]\n    pub fn new<'py, T>(\n        py: Python<'py>,\n        elements: impl IntoIterator<Item = T>,\n    ) -> PyResult<Bound<'py, PySet>>\n    where\n        T: IntoPyObject<'py>,\n    {\n        let set = Self::empty(py)?;\n        for e in elements {\n            set.add(e)?;\n        }\n        Ok(set)\n    }\n\n    /// Creates a new empty set.\n    pub fn empty(py: Python<'_>) -> PyResult<Bound<'_, PySet>> {\n        unsafe {\n            ffi::PySet_New(ptr::null_mut())\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n        }\n    }\n}\n\n/// Implementation of functionality for [`PySet`].\n///\n/// These methods are defined for the `Bound<'py, PySet>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PySet\")]\npub trait PySetMethods<'py>: crate::sealed::Sealed {\n    /// Removes all elements from the set.\n    fn clear(&self);\n\n    /// Returns the number of items in the set.\n    ///\n    /// This is equivalent to the Python expression `len(self)`.\n    fn len(&self) -> usize;\n\n    /// Checks if set is empty.\n    fn is_empty(&self) -> bool {\n        self.len() == 0\n    }\n\n    /// Determines if the set contains the specified key.\n    ///\n    /// This is equivalent to the Python expression `key in self`.\n    fn contains<K>(&self, key: K) -> PyResult<bool>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Removes the element from the set if it is present.\n    ///\n    /// Returns `true` if the element was present in the set.\n    fn discard<K>(&self, key: K) -> PyResult<bool>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Adds an element to the set.\n    fn add<K>(&self, key: K) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>;\n\n    /// Removes and returns an arbitrary element from the set.\n    fn pop(&self) -> Option<Bound<'py, PyAny>>;\n\n    /// Returns an iterator of values in this set.\n    ///\n    /// # Panics\n    ///\n    /// If PyO3 detects that the set is mutated during iteration, it will panic.\n    fn iter(&self) -> BoundSetIterator<'py>;\n}\n\nimpl<'py> PySetMethods<'py> for Bound<'py, PySet> {\n    #[inline]\n    fn clear(&self) {\n        unsafe {\n            ffi::PySet_Clear(self.as_ptr());\n        }\n    }\n\n    #[inline]\n    fn len(&self) -> usize {\n        unsafe { ffi::PySet_Size(self.as_ptr()) as usize }\n    }\n\n    fn contains<K>(&self, key: K) -> PyResult<bool>\n    where\n        K: IntoPyObject<'py>,\n    {\n        fn inner(set: &Bound<'_, PySet>, key: Borrowed<'_, '_, PyAny>) -> PyResult<bool> {\n            match unsafe { ffi::PySet_Contains(set.as_ptr(), key.as_ptr()) } {\n                1 => Ok(true),\n                0 => Ok(false),\n                _ => Err(PyErr::fetch(set.py())),\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn discard<K>(&self, key: K) -> PyResult<bool>\n    where\n        K: IntoPyObject<'py>,\n    {\n        fn inner(set: &Bound<'_, PySet>, key: Borrowed<'_, '_, PyAny>) -> PyResult<bool> {\n            match unsafe { ffi::PySet_Discard(set.as_ptr(), key.as_ptr()) } {\n                1 => Ok(true),\n                0 => Ok(false),\n                _ => Err(PyErr::fetch(set.py())),\n            }\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn add<K>(&self, key: K) -> PyResult<()>\n    where\n        K: IntoPyObject<'py>,\n    {\n        fn inner(set: &Bound<'_, PySet>, key: Borrowed<'_, '_, PyAny>) -> PyResult<()> {\n            err::error_on_minusone(set.py(), unsafe {\n                ffi::PySet_Add(set.as_ptr(), key.as_ptr())\n            })\n        }\n\n        let py = self.py();\n        inner(\n            self,\n            key.into_pyobject_or_pyerr(py)?.into_any().as_borrowed(),\n        )\n    }\n\n    fn pop(&self) -> Option<Bound<'py, PyAny>> {\n        let element = unsafe { ffi::PySet_Pop(self.as_ptr()).assume_owned_or_err(self.py()) };\n        element.ok()\n    }\n\n    fn iter(&self) -> BoundSetIterator<'py> {\n        BoundSetIterator::new(self.clone())\n    }\n}\n\nimpl<'py> IntoIterator for Bound<'py, PySet> {\n    type Item = Bound<'py, PyAny>;\n    type IntoIter = BoundSetIterator<'py>;\n\n    /// Returns an iterator of values in this set.\n    ///\n    /// # Panics\n    ///\n    /// If PyO3 detects that the set is mutated during iteration, it will panic.\n    fn into_iter(self) -> Self::IntoIter {\n        BoundSetIterator::new(self)\n    }\n}\n\nimpl<'py> IntoIterator for &Bound<'py, PySet> {\n    type Item = Bound<'py, PyAny>;\n    type IntoIter = BoundSetIterator<'py>;\n\n    /// Returns an iterator of values in this set.\n    ///\n    /// # Panics\n    ///\n    /// If PyO3 detects that the set is mutated during iteration, it will panic.\n    fn into_iter(self) -> Self::IntoIter {\n        self.iter()\n    }\n}\n\n/// PyO3 implementation of an iterator for a Python `set` object.\npub struct BoundSetIterator<'py>(Bound<'py, PyIterator>);\n\nimpl<'py> BoundSetIterator<'py> {\n    pub(super) fn new(set: Bound<'py, PySet>) -> Self {\n        Self(PyIterator::from_object(&set).expect(\"set should always be iterable\"))\n    }\n}\n\nimpl<'py> Iterator for BoundSetIterator<'py> {\n    type Item = Bound<'py, super::PyAny>;\n\n    /// Advances the iterator and returns the next value.\n    fn next(&mut self) -> Option<Self::Item> {\n        self.0\n            .next()\n            .map(|result| result.expect(\"set iteration should be infallible\"))\n    }\n\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let len = ExactSizeIterator::len(self);\n        (len, Some(len))\n    }\n\n    #[inline]\n    fn count(self) -> usize\n    where\n        Self: Sized,\n    {\n        self.len()\n    }\n}\n\nimpl ExactSizeIterator for BoundSetIterator<'_> {\n    fn len(&self) -> usize {\n        self.0.size_hint().0\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::PySet;\n    use crate::{\n        conversion::IntoPyObject,\n        types::{PyAnyMethods, PySetMethods},\n        Python,\n    };\n    use std::collections::HashSet;\n\n    #[test]\n    fn test_set_new() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1]).unwrap();\n            assert_eq!(1, set.len());\n\n            let v = vec![1];\n            assert!(PySet::new(py, &[v]).is_err());\n        });\n    }\n\n    #[test]\n    fn test_set_empty() {\n        Python::attach(|py| {\n            let set = PySet::empty(py).unwrap();\n            assert_eq!(0, set.len());\n            assert!(set.is_empty());\n        });\n    }\n\n    #[test]\n    fn test_set_len() {\n        Python::attach(|py| {\n            let mut v = HashSet::<i32>::new();\n            let ob = (&v).into_pyobject(py).unwrap();\n            let set = ob.cast::<PySet>().unwrap();\n            assert_eq!(0, set.len());\n            v.insert(7);\n            let ob = v.into_pyobject(py).unwrap();\n            let set2 = ob.cast::<PySet>().unwrap();\n            assert_eq!(1, set2.len());\n        });\n    }\n\n    #[test]\n    fn test_set_clear() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1]).unwrap();\n            assert_eq!(1, set.len());\n            set.clear();\n            assert_eq!(0, set.len());\n        });\n    }\n\n    #[test]\n    fn test_set_contains() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1]).unwrap();\n            assert!(set.contains(1).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_set_discard() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1]).unwrap();\n            assert!(!set.discard(2).unwrap());\n            assert_eq!(1, set.len());\n\n            assert!(set.discard(1).unwrap());\n            assert_eq!(0, set.len());\n            assert!(!set.discard(1).unwrap());\n\n            assert!(set.discard(vec![1, 2]).is_err());\n        });\n    }\n\n    #[test]\n    fn test_set_add() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1, 2]).unwrap();\n            set.add(1).unwrap(); // Add a duplicated element\n            assert!(set.contains(1).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_set_pop() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1]).unwrap();\n            let val = set.pop();\n            assert!(val.is_some());\n            let val2 = set.pop();\n            assert!(val2.is_none());\n            assert!(py\n                .eval(c\"print('Exception state should not be set.')\", None, None)\n                .is_ok());\n        });\n    }\n\n    #[test]\n    fn test_set_iter() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1]).unwrap();\n\n            for el in set {\n                assert_eq!(1i32, el.extract::<'_, i32>().unwrap());\n            }\n        });\n    }\n\n    #[test]\n    fn test_set_iter_bound() {\n        use crate::types::any::PyAnyMethods;\n\n        Python::attach(|py| {\n            let set = PySet::new(py, [1]).unwrap();\n\n            for el in &set {\n                assert_eq!(1i32, el.extract::<i32>().unwrap());\n            }\n        });\n    }\n\n    #[test]\n    #[should_panic]\n    fn test_set_iter_mutation() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1, 2, 3, 4, 5]).unwrap();\n\n            for _ in &set {\n                let _ = set.add(42);\n            }\n        });\n    }\n\n    #[test]\n    #[should_panic]\n    fn test_set_iter_mutation_same_len() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1, 2, 3, 4, 5]).unwrap();\n\n            for item in &set {\n                let item: i32 = item.extract().unwrap();\n                let _ = set.del_item(item);\n                let _ = set.add(item + 10);\n            }\n        });\n    }\n\n    #[test]\n    fn test_set_iter_size_hint() {\n        Python::attach(|py| {\n            let set = PySet::new(py, [1]).unwrap();\n            let mut iter = set.iter();\n\n            // Exact size\n            assert_eq!(iter.len(), 1);\n            assert_eq!(iter.size_hint(), (1, Some(1)));\n            iter.next();\n            assert_eq!(iter.len(), 0);\n            assert_eq!(iter.size_hint(), (0, Some(0)));\n        });\n    }\n\n    #[test]\n    fn test_iter_count() {\n        Python::attach(|py| {\n            let set = PySet::new(py, vec![1, 2, 3]).unwrap();\n            assert_eq!(set.iter().count(), 3);\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/slice.rs",
    "content": "use crate::err::{PyErr, PyResult};\nuse crate::ffi;\nuse crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::PyStaticExpr;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::types::{PyRange, PyRangeMethods};\nuse crate::{Bound, IntoPyObject, PyAny, Python};\nuse std::convert::Infallible;\n\n/// Represents a Python `slice`.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PySlice>`][crate::Py] or [`Bound<'py, PySlice>`][Bound].\n///\n/// For APIs available on `slice` objects, see the [`PySliceMethods`] trait which is implemented for\n/// [`Bound<'py, PySlice>`][Bound].\n///\n/// Only `isize` indices supported at the moment by the `PySlice` object.\n#[repr(transparent)]\npub struct PySlice(PyAny);\n\npyobject_native_type!(\n    PySlice,\n    ffi::PySliceObject,\n    pyobject_native_static_type_object!(ffi::PySlice_Type),\n    \"builtins\",\n    \"slice\",\n    #checkfunction=ffi::PySlice_Check\n);\n\n/// Return value from [`PySliceMethods::indices`].\n#[derive(Debug, Eq, PartialEq)]\npub struct PySliceIndices {\n    /// Start of the slice\n    ///\n    /// It can be -1 when the step is negative, otherwise it's non-negative.\n    pub start: isize,\n    /// End of the slice\n    ///\n    /// It can be -1 when the step is negative, otherwise it's non-negative.\n    pub stop: isize,\n    /// Increment to use when iterating the slice from `start` to `stop`.\n    pub step: isize,\n    /// The length of the slice calculated from the original input sequence.\n    pub slicelength: usize,\n}\n\nimpl PySliceIndices {\n    /// Creates a new `PySliceIndices`.\n    pub fn new(start: isize, stop: isize, step: isize) -> PySliceIndices {\n        PySliceIndices {\n            start,\n            stop,\n            step,\n            slicelength: 0,\n        }\n    }\n}\n\nimpl PySlice {\n    /// Constructs a new slice with the given elements.\n    pub fn new(py: Python<'_>, start: isize, stop: isize, step: isize) -> Bound<'_, PySlice> {\n        unsafe {\n            ffi::PySlice_New(\n                ffi::PyLong_FromSsize_t(start),\n                ffi::PyLong_FromSsize_t(stop),\n                ffi::PyLong_FromSsize_t(step),\n            )\n            .assume_owned(py)\n            .cast_into_unchecked()\n        }\n    }\n\n    /// Constructs a new full slice that is equivalent to `::`.\n    pub fn full(py: Python<'_>) -> Bound<'_, PySlice> {\n        unsafe {\n            ffi::PySlice_New(ffi::Py_None(), ffi::Py_None(), ffi::Py_None())\n                .assume_owned(py)\n                .cast_into_unchecked()\n        }\n    }\n}\n\n/// Implementation of functionality for [`PySlice`].\n///\n/// These methods are defined for the `Bound<'py, PyTuple>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PySlice\")]\npub trait PySliceMethods<'py>: crate::sealed::Sealed {\n    /// Retrieves the start, stop, and step indices from the slice object,\n    /// assuming a sequence of length `length`, and stores the length of the\n    /// slice in its `slicelength` member.\n    fn indices(&self, length: isize) -> PyResult<PySliceIndices>;\n}\n\nimpl<'py> PySliceMethods<'py> for Bound<'py, PySlice> {\n    fn indices(&self, length: isize) -> PyResult<PySliceIndices> {\n        unsafe {\n            let mut slicelength: isize = 0;\n            let mut start: isize = 0;\n            let mut stop: isize = 0;\n            let mut step: isize = 0;\n            let r = ffi::PySlice_GetIndicesEx(\n                self.as_ptr(),\n                length,\n                &mut start,\n                &mut stop,\n                &mut step,\n                &mut slicelength,\n            );\n            if r == 0 {\n                Ok(PySliceIndices {\n                    start,\n                    stop,\n                    step,\n                    // non-negative isize should always fit into usize\n                    slicelength: slicelength as _,\n                })\n            } else {\n                Err(PyErr::fetch(self.py()))\n            }\n        }\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for PySliceIndices {\n    type Target = PySlice;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PySlice::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PySlice::new(py, self.start, self.stop, self.step))\n    }\n}\n\nimpl<'py> IntoPyObject<'py> for &PySliceIndices {\n    type Target = PySlice;\n    type Output = Bound<'py, Self::Target>;\n    type Error = Infallible;\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const OUTPUT_TYPE: PyStaticExpr = PySlice::TYPE_HINT;\n\n    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n        Ok(PySlice::new(py, self.start, self.stop, self.step))\n    }\n}\n\nimpl<'py> TryFrom<Bound<'py, PyRange>> for Bound<'py, PySlice> {\n    type Error = PyErr;\n\n    fn try_from(range: Bound<'py, PyRange>) -> Result<Self, Self::Error> {\n        Ok(PySlice::new(\n            range.py(),\n            range.start()?,\n            range.stop()?,\n            range.step()?,\n        ))\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::types::PyAnyMethods as _;\n\n    #[test]\n    fn test_py_slice_new() {\n        Python::attach(|py| {\n            let slice = PySlice::new(py, isize::MIN, isize::MAX, 1);\n            assert_eq!(\n                slice.getattr(\"start\").unwrap().extract::<isize>().unwrap(),\n                isize::MIN\n            );\n            assert_eq!(\n                slice.getattr(\"stop\").unwrap().extract::<isize>().unwrap(),\n                isize::MAX\n            );\n            assert_eq!(\n                slice.getattr(\"step\").unwrap().extract::<isize>().unwrap(),\n                1\n            );\n        });\n    }\n\n    #[test]\n    fn test_py_slice_full() {\n        Python::attach(|py| {\n            let slice = PySlice::full(py);\n            assert!(slice.getattr(\"start\").unwrap().is_none(),);\n            assert!(slice.getattr(\"stop\").unwrap().is_none(),);\n            assert!(slice.getattr(\"step\").unwrap().is_none(),);\n            assert_eq!(\n                slice.indices(0).unwrap(),\n                PySliceIndices {\n                    start: 0,\n                    stop: 0,\n                    step: 1,\n                    slicelength: 0,\n                },\n            );\n            assert_eq!(\n                slice.indices(42).unwrap(),\n                PySliceIndices {\n                    start: 0,\n                    stop: 42,\n                    step: 1,\n                    slicelength: 42,\n                },\n            );\n        });\n    }\n\n    #[test]\n    fn test_py_slice_indices_new() {\n        let start = 0;\n        let stop = 0;\n        let step = 0;\n        assert_eq!(\n            PySliceIndices::new(start, stop, step),\n            PySliceIndices {\n                start,\n                stop,\n                step,\n                slicelength: 0\n            }\n        );\n\n        let start = 0;\n        let stop = 100;\n        let step = 10;\n        assert_eq!(\n            PySliceIndices::new(start, stop, step),\n            PySliceIndices {\n                start,\n                stop,\n                step,\n                slicelength: 0\n            }\n        );\n\n        let start = 0;\n        let stop = -10;\n        let step = -1;\n        assert_eq!(\n            PySliceIndices::new(start, stop, step),\n            PySliceIndices {\n                start,\n                stop,\n                step,\n                slicelength: 0\n            }\n        );\n\n        let start = 0;\n        let stop = -10;\n        let step = 20;\n        assert_eq!(\n            PySliceIndices::new(start, stop, step),\n            PySliceIndices {\n                start,\n                stop,\n                step,\n                slicelength: 0\n            }\n        );\n    }\n}\n"
  },
  {
    "path": "src/types/string.rs",
    "content": "#[cfg(not(Py_LIMITED_API))]\nuse crate::exceptions::PyUnicodeDecodeError;\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::instance::Borrowed;\nuse crate::py_result_ext::PyResultExt;\nuse crate::types::bytes::PyBytesMethods;\nuse crate::types::PyBytes;\nuse crate::{ffi, Bound, Py, PyAny, PyResult, Python};\nuse std::borrow::Cow;\nuse std::ffi::CStr;\nuse std::{fmt, str};\n\n/// Represents raw data backing a Python `str`.\n///\n/// Python internally stores strings in various representations. This enumeration\n/// represents those variations.\n#[cfg(not(Py_LIMITED_API))]\n#[derive(Clone, Copy, Debug, PartialEq, Eq)]\npub enum PyStringData<'a> {\n    /// UCS1 representation.\n    Ucs1(&'a [u8]),\n\n    /// UCS2 representation.\n    Ucs2(&'a [u16]),\n\n    /// UCS4 representation.\n    Ucs4(&'a [u32]),\n}\n\n#[cfg(not(Py_LIMITED_API))]\nimpl<'a> PyStringData<'a> {\n    /// Obtain the raw bytes backing this instance as a [u8] slice.\n    pub fn as_bytes(&self) -> &[u8] {\n        match self {\n            Self::Ucs1(s) => s,\n            Self::Ucs2(s) => unsafe {\n                std::slice::from_raw_parts(s.as_ptr().cast(), s.len() * self.value_width_bytes())\n            },\n            Self::Ucs4(s) => unsafe {\n                std::slice::from_raw_parts(s.as_ptr().cast(), s.len() * self.value_width_bytes())\n            },\n        }\n    }\n\n    /// Size in bytes of each value/item in the underlying slice.\n    #[inline]\n    pub fn value_width_bytes(&self) -> usize {\n        match self {\n            Self::Ucs1(_) => 1,\n            Self::Ucs2(_) => 2,\n            Self::Ucs4(_) => 4,\n        }\n    }\n\n    /// Convert the raw data to a Rust string.\n    ///\n    /// For UCS-1 / UTF-8, returns a borrow into the original slice. For UCS-2 and UCS-4,\n    /// returns an owned string.\n    ///\n    /// Returns [PyUnicodeDecodeError] if the string data isn't valid in its purported\n    /// storage format. This should only occur for strings that were created via Python\n    /// C APIs that skip input validation (like `PyUnicode_FromKindAndData`) and should\n    /// never occur for strings that were created from Python code.\n    pub fn to_string(self, py: Python<'_>) -> PyResult<Cow<'a, str>> {\n        match self {\n            Self::Ucs1(data) => match str::from_utf8(data) {\n                Ok(s) => Ok(Cow::Borrowed(s)),\n                Err(e) => Err(PyUnicodeDecodeError::new_utf8(py, data, e)?.into()),\n            },\n            Self::Ucs2(data) => match String::from_utf16(data) {\n                Ok(s) => Ok(Cow::Owned(s)),\n                Err(e) => {\n                    let mut message = e.to_string().as_bytes().to_vec();\n                    message.push(0);\n\n                    Err(PyUnicodeDecodeError::new(\n                        py,\n                        c\"utf-16\",\n                        self.as_bytes(),\n                        0..self.as_bytes().len(),\n                        CStr::from_bytes_with_nul(&message).unwrap(),\n                    )?\n                    .into())\n                }\n            },\n            Self::Ucs4(data) => match data.iter().map(|&c| std::char::from_u32(c)).collect() {\n                Some(s) => Ok(Cow::Owned(s)),\n                None => Err(PyUnicodeDecodeError::new(\n                    py,\n                    c\"utf-32\",\n                    self.as_bytes(),\n                    0..self.as_bytes().len(),\n                    c\"error converting utf-32\",\n                )?\n                .into()),\n            },\n        }\n    }\n\n    /// Convert the raw data to a Rust string, possibly with data loss.\n    ///\n    /// Invalid code points will be replaced with `U+FFFD REPLACEMENT CHARACTER`.\n    ///\n    /// Returns a borrow into original data, when possible, or owned data otherwise.\n    ///\n    /// The return value of this function should only disagree with [Self::to_string]\n    /// when that method would error.\n    pub fn to_string_lossy(self) -> Cow<'a, str> {\n        match self {\n            Self::Ucs1(data) => String::from_utf8_lossy(data),\n            Self::Ucs2(data) => Cow::Owned(String::from_utf16_lossy(data)),\n            Self::Ucs4(data) => Cow::Owned(\n                data.iter()\n                    .map(|&c| std::char::from_u32(c).unwrap_or('\\u{FFFD}'))\n                    .collect(),\n            ),\n        }\n    }\n}\n\n/// Represents a Python `string` (a Unicode string object).\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyString>`][crate::Py] or [`Bound<'py, PyString>`][Bound].\n///\n/// For APIs available on `str` objects, see the [`PyStringMethods`] trait which is implemented for\n/// [`Bound<'py, PyString>`][Bound].\n///\n/// # Equality\n///\n/// For convenience, [`Bound<'py, PyString>`] implements [`PartialEq<str>`] to allow comparing the\n/// data in the Python string to a Rust UTF-8 string slice.\n///\n/// This is not always the most appropriate way to compare Python strings, as Python string\n/// subclasses may have different equality semantics. In situations where subclasses overriding\n/// equality might be relevant, use [`PyAnyMethods::eq`](crate::types::any::PyAnyMethods::eq), at\n/// cost of the additional overhead of a Python method call.\n///\n/// ```rust\n/// # use pyo3::prelude::*;\n/// use pyo3::types::PyString;\n///\n/// # Python::attach(|py| {\n/// let py_string = PyString::new(py, \"foo\");\n/// // via PartialEq<str>\n/// assert_eq!(py_string, \"foo\");\n///\n/// // via Python equality\n/// assert!(py_string.as_any().eq(\"foo\").unwrap());\n/// # });\n/// ```\n#[repr(transparent)]\npub struct PyString(PyAny);\n\npyobject_native_type_core!(PyString, pyobject_native_static_type_object!(ffi::PyUnicode_Type), \"builtins\", \"str\", #checkfunction=ffi::PyUnicode_Check);\n\nimpl PyString {\n    /// Creates a new Python string object.\n    ///\n    /// Panics if out of memory.\n    pub fn new<'py>(py: Python<'py>, s: &str) -> Bound<'py, PyString> {\n        let ptr = s.as_ptr().cast();\n        let len = s.len() as ffi::Py_ssize_t;\n        unsafe {\n            ffi::PyUnicode_FromStringAndSize(ptr, len)\n                .assume_owned(py)\n                .cast_into_unchecked()\n        }\n    }\n\n    /// Creates a new Python string object from bytes.\n    ///\n    /// Returns PyMemoryError if out of memory.\n    /// Returns [PyUnicodeDecodeError] if the slice is not a valid UTF-8 string.\n    pub fn from_bytes<'py>(py: Python<'py>, s: &[u8]) -> PyResult<Bound<'py, PyString>> {\n        let ptr = s.as_ptr().cast();\n        let len = s.len() as ffi::Py_ssize_t;\n        unsafe {\n            ffi::PyUnicode_FromStringAndSize(ptr, len)\n                .assume_owned_or_err(py)\n                .cast_into_unchecked()\n        }\n    }\n\n    /// Intern the given string\n    ///\n    /// This will return a reference to the same Python string object if called repeatedly with the same string.\n    ///\n    /// Note that while this is more memory efficient than [`PyString::new`], it unconditionally allocates a\n    /// temporary Python string object and is thereby slower than [`PyString::new`].\n    ///\n    /// Panics if out of memory.\n    pub fn intern<'py>(py: Python<'py>, s: &str) -> Bound<'py, PyString> {\n        let ptr = s.as_ptr().cast();\n        let len = s.len() as ffi::Py_ssize_t;\n        unsafe {\n            let mut ob = ffi::PyUnicode_FromStringAndSize(ptr, len);\n            if !ob.is_null() {\n                ffi::PyUnicode_InternInPlace(&mut ob);\n            }\n            ob.assume_owned(py).cast_into_unchecked()\n        }\n    }\n\n    /// Attempts to create a Python string from a Python [bytes-like object].\n    ///\n    /// The `encoding` and `errors` parameters are optional:\n    /// - If `encoding` is `None`, the default encoding is used (UTF-8).\n    /// - If `errors` is `None`, the default error handling is used (\"strict\").\n    ///\n    /// See the [Python documentation on codecs] for more information.\n    ///\n    /// [bytes-like object]: (https://docs.python.org/3/glossary.html#term-bytes-like-object).\n    /// [Python documentation on codecs]: https://docs.python.org/3/library/codecs.html#standard-encodings\n    pub fn from_encoded_object<'py>(\n        src: &Bound<'py, PyAny>,\n        encoding: Option<&CStr>,\n        errors: Option<&CStr>,\n    ) -> PyResult<Bound<'py, PyString>> {\n        let encoding = encoding.map_or(std::ptr::null(), CStr::as_ptr);\n        let errors = errors.map_or(std::ptr::null(), CStr::as_ptr);\n        // Safety:\n        // - `src` is a valid Python object\n        // - `encoding` and `errors` are either null or valid C strings. `encoding` and `errors` are\n        //   documented as allowing null.\n        // - `ffi::PyUnicode_FromEncodedObject` returns a new `str` object, or sets an error.\n        unsafe {\n            ffi::PyUnicode_FromEncodedObject(src.as_ptr(), encoding, errors)\n                .assume_owned_or_err(src.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    /// Creates a Python string using a format string.\n    ///\n    /// This function is similar to [`format!`], but it returns a Python string object instead of a Rust string.\n    #[inline]\n    pub fn from_fmt<'py>(\n        py: Python<'py>,\n        args: fmt::Arguments<'_>,\n    ) -> PyResult<Bound<'py, PyString>> {\n        if let Some(static_string) = args.as_str() {\n            return Ok(PyString::new(py, static_string));\n        };\n\n        #[cfg(all(Py_3_14, not(Py_LIMITED_API)))]\n        {\n            use crate::fmt::PyUnicodeWriter;\n            use std::fmt::Write as _;\n\n            let mut writer = PyUnicodeWriter::new(py)?;\n            writer\n                .write_fmt(args)\n                .map_err(|_| writer.take_error().expect(\"expected error\"))?;\n            writer.into_py_string()\n        }\n\n        #[cfg(any(not(Py_3_14), Py_LIMITED_API))]\n        {\n            Ok(PyString::new(py, &format!(\"{args}\")))\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyString`].\n///\n/// These methods are defined for the `Bound<'py, PyString>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyString\")]\npub trait PyStringMethods<'py>: crate::sealed::Sealed {\n    /// Gets the Python string as a Rust UTF-8 string slice.\n    ///\n    /// Returns a `UnicodeEncodeError` if the input is not valid unicode\n    /// (containing unpaired surrogates).\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    fn to_str(&self) -> PyResult<&str>;\n\n    /// Converts the `PyString` into a Rust string, avoiding copying when possible.\n    ///\n    /// Returns a `UnicodeEncodeError` if the input is not valid unicode\n    /// (containing unpaired surrogates).\n    fn to_cow(&self) -> PyResult<Cow<'_, str>>;\n\n    /// Converts the `PyString` into a Rust string.\n    ///\n    /// Unpaired surrogates invalid UTF-8 sequences are\n    /// replaced with `U+FFFD REPLACEMENT CHARACTER`.\n    fn to_string_lossy(&self) -> Cow<'_, str>;\n\n    /// Encodes this string as a Python `bytes` object, using UTF-8 encoding.\n    fn encode_utf8(&self) -> PyResult<Bound<'py, PyBytes>>;\n\n    /// Obtains the raw data backing the Python string.\n    ///\n    /// If the Python string object was created through legacy APIs, its internal storage format\n    /// will be canonicalized before data is returned.\n    ///\n    /// # Safety\n    ///\n    /// This function implementation relies on manually decoding a C bitfield. In practice, this\n    /// works well on common little-endian architectures such as x86_64, where the bitfield has a\n    /// common representation (even if it is not part of the C spec). The PyO3 CI tests this API on\n    /// x86_64 platforms.\n    ///\n    /// By using this API, you accept responsibility for testing that PyStringData behaves as\n    /// expected on the targets where you plan to distribute your software.\n    #[cfg(not(any(Py_LIMITED_API, GraalPy, PyPy)))]\n    unsafe fn data(&self) -> PyResult<PyStringData<'_>>;\n}\n\nimpl<'py> PyStringMethods<'py> for Bound<'py, PyString> {\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    fn to_str(&self) -> PyResult<&str> {\n        self.as_borrowed().to_str()\n    }\n\n    fn to_cow(&self) -> PyResult<Cow<'_, str>> {\n        self.as_borrowed().to_cow()\n    }\n\n    fn to_string_lossy(&self) -> Cow<'_, str> {\n        self.as_borrowed().to_string_lossy()\n    }\n\n    fn encode_utf8(&self) -> PyResult<Bound<'py, PyBytes>> {\n        unsafe {\n            ffi::PyUnicode_AsUTF8String(self.as_ptr())\n                .assume_owned_or_err(self.py())\n                .cast_into_unchecked::<PyBytes>()\n        }\n    }\n\n    #[cfg(not(any(Py_LIMITED_API, GraalPy, PyPy)))]\n    unsafe fn data(&self) -> PyResult<PyStringData<'_>> {\n        unsafe { self.as_borrowed().data() }\n    }\n}\n\nimpl<'a> Borrowed<'a, '_, PyString> {\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    pub(crate) fn to_str(self) -> PyResult<&'a str> {\n        // PyUnicode_AsUTF8AndSize only available on limited API starting with 3.10.\n        let mut size: ffi::Py_ssize_t = 0;\n        let data: *const u8 =\n            unsafe { ffi::PyUnicode_AsUTF8AndSize(self.as_ptr(), &mut size).cast() };\n        if data.is_null() {\n            Err(crate::PyErr::fetch(self.py()))\n        } else {\n            Ok(unsafe {\n                std::str::from_utf8_unchecked(std::slice::from_raw_parts(data, size as usize))\n            })\n        }\n    }\n\n    pub(crate) fn to_cow(self) -> PyResult<Cow<'a, str>> {\n        // TODO: this method can probably be deprecated once Python 3.9 support is dropped,\n        // because all versions then support the more efficient `to_str`.\n        #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n        {\n            self.to_str().map(Cow::Borrowed)\n        }\n\n        #[cfg(not(any(Py_3_10, not(Py_LIMITED_API))))]\n        {\n            let bytes = self.encode_utf8()?;\n            Ok(Cow::Owned(\n                unsafe { str::from_utf8_unchecked(bytes.as_bytes()) }.to_owned(),\n            ))\n        }\n    }\n\n    fn to_string_lossy(self) -> Cow<'a, str> {\n        let ptr = self.as_ptr();\n        let py = self.py();\n\n        #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n        if let Ok(s) = self.to_str() {\n            return Cow::Borrowed(s);\n        }\n\n        let bytes = unsafe {\n            ffi::PyUnicode_AsEncodedString(ptr, c\"utf-8\".as_ptr(), c\"surrogatepass\".as_ptr())\n                .assume_owned(py)\n                .cast_into_unchecked::<PyBytes>()\n        };\n        Cow::Owned(String::from_utf8_lossy(bytes.as_bytes()).into_owned())\n    }\n\n    #[cfg(not(any(Py_LIMITED_API, GraalPy, PyPy)))]\n    unsafe fn data(self) -> PyResult<PyStringData<'a>> {\n        unsafe {\n            let ptr = self.as_ptr();\n\n            #[cfg(not(Py_3_12))]\n            #[allow(deprecated)]\n            {\n                let ready = ffi::PyUnicode_READY(ptr);\n                if ready != 0 {\n                    // Exception was created on failure.\n                    return Err(crate::PyErr::fetch(self.py()));\n                }\n            }\n\n            // The string should be in its canonical form after calling `PyUnicode_READY()`.\n            // And non-canonical form not possible after Python 3.12. So it should be safe\n            // to call these APIs.\n            let length = ffi::PyUnicode_GET_LENGTH(ptr) as usize;\n            let raw_data = ffi::PyUnicode_DATA(ptr);\n            let kind = ffi::PyUnicode_KIND(ptr);\n\n            match kind {\n                ffi::PyUnicode_1BYTE_KIND => Ok(PyStringData::Ucs1(std::slice::from_raw_parts(\n                    raw_data as *const u8,\n                    length,\n                ))),\n                ffi::PyUnicode_2BYTE_KIND => Ok(PyStringData::Ucs2(std::slice::from_raw_parts(\n                    raw_data as *const u16,\n                    length,\n                ))),\n                ffi::PyUnicode_4BYTE_KIND => Ok(PyStringData::Ucs4(std::slice::from_raw_parts(\n                    raw_data as *const u32,\n                    length,\n                ))),\n                _ => unreachable!(),\n            }\n        }\n    }\n}\n\nimpl Py<PyString> {\n    /// Gets the Python string as a Rust UTF-8 string slice.\n    ///\n    /// Returns a `UnicodeEncodeError` if the input is not valid unicode\n    /// (containing unpaired surrogates).\n    ///\n    /// Because `str` objects are immutable, the returned slice is independent of\n    /// the GIL lifetime.\n    #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n    pub fn to_str<'a>(&'a self, py: Python<'_>) -> PyResult<&'a str> {\n        self.bind_borrowed(py).to_str()\n    }\n\n    /// Converts the `PyString` into a Rust string, avoiding copying when possible.\n    ///\n    /// Returns a `UnicodeEncodeError` if the input is not valid unicode\n    /// (containing unpaired surrogates).\n    ///\n    /// Because `str` objects are immutable, the returned slice is independent of\n    /// the GIL lifetime.\n    pub fn to_cow<'a>(&'a self, py: Python<'_>) -> PyResult<Cow<'a, str>> {\n        self.bind_borrowed(py).to_cow()\n    }\n\n    /// Converts the `PyString` into a Rust string.\n    ///\n    /// Unpaired surrogates invalid UTF-8 sequences are\n    /// replaced with `U+FFFD REPLACEMENT CHARACTER`.\n    ///\n    /// Because `str` objects are immutable, the returned slice is independent of\n    /// the GIL lifetime.\n    pub fn to_string_lossy<'a>(&'a self, py: Python<'_>) -> Cow<'a, str> {\n        self.bind_borrowed(py).to_string_lossy()\n    }\n}\n\n/// Compares whether the data in the Python string is equal to the given UTF8.\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyString`].\nimpl PartialEq<str> for Bound<'_, PyString> {\n    #[inline]\n    fn eq(&self, other: &str) -> bool {\n        self.as_borrowed() == *other\n    }\n}\n\n/// Compares whether the data in the Python string is equal to the given UTF8.\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyString`].\nimpl PartialEq<&'_ str> for Bound<'_, PyString> {\n    #[inline]\n    fn eq(&self, other: &&str) -> bool {\n        self.as_borrowed() == **other\n    }\n}\n\n/// Compares whether the data in the Python string is equal to the given UTF8.\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyString`].\nimpl PartialEq<Bound<'_, PyString>> for str {\n    #[inline]\n    fn eq(&self, other: &Bound<'_, PyString>) -> bool {\n        *self == other.as_borrowed()\n    }\n}\n\n/// Compares whether the data in the Python string is equal to the given UTF8.\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyString`].\nimpl PartialEq<&'_ Bound<'_, PyString>> for str {\n    #[inline]\n    fn eq(&self, other: &&Bound<'_, PyString>) -> bool {\n        *self == other.as_borrowed()\n    }\n}\n\n/// Compares whether the data in the Python string is equal to the given UTF8.\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyString`].\nimpl PartialEq<Bound<'_, PyString>> for &'_ str {\n    #[inline]\n    fn eq(&self, other: &Bound<'_, PyString>) -> bool {\n        **self == other.as_borrowed()\n    }\n}\n\n/// Compares whether the data in the Python string is equal to the given UTF8.\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyString`].\nimpl PartialEq<str> for &'_ Bound<'_, PyString> {\n    #[inline]\n    fn eq(&self, other: &str) -> bool {\n        self.as_borrowed() == other\n    }\n}\n\n/// Compares whether the data in the Python string is equal to the given UTF8.\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyString`].\nimpl PartialEq<str> for Borrowed<'_, '_, PyString> {\n    #[inline]\n    fn eq(&self, other: &str) -> bool {\n        #[cfg(not(Py_3_13))]\n        {\n            self.to_cow().is_ok_and(|s| s == other)\n        }\n\n        #[cfg(Py_3_13)]\n        unsafe {\n            ffi::PyUnicode_EqualToUTF8AndSize(\n                self.as_ptr(),\n                other.as_ptr().cast(),\n                other.len() as _,\n            ) == 1\n        }\n    }\n}\n\n/// Compares whether the data in the Python string is equal to the given UTF8.\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyString`].\nimpl PartialEq<&str> for Borrowed<'_, '_, PyString> {\n    #[inline]\n    fn eq(&self, other: &&str) -> bool {\n        *self == **other\n    }\n}\n\n/// Compares whether the data in the Python string is equal to the given UTF8.\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyString`].\nimpl PartialEq<Borrowed<'_, '_, PyString>> for str {\n    #[inline]\n    fn eq(&self, other: &Borrowed<'_, '_, PyString>) -> bool {\n        other == self\n    }\n}\n\n/// Compares whether the data in the Python string is equal to the given UTF8.\n///\n/// In some cases Python equality might be more appropriate; see the note on [`PyString`].\nimpl PartialEq<Borrowed<'_, '_, PyString>> for &'_ str {\n    #[inline]\n    fn eq(&self, other: &Borrowed<'_, '_, PyString>) -> bool {\n        other == self\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::{exceptions::PyLookupError, types::PyAnyMethods as _, IntoPyObject};\n\n    #[test]\n    fn test_to_cow_utf8() {\n        Python::attach(|py| {\n            let s = \"ascii 🐈\";\n            let py_string = PyString::new(py, s);\n            assert_eq!(s, py_string.to_cow().unwrap());\n        })\n    }\n\n    #[test]\n    fn test_to_cow_surrogate() {\n        Python::attach(|py| {\n            let py_string = py\n                .eval(cr\"'\\ud800'\", None, None)\n                .unwrap()\n                .cast_into::<PyString>()\n                .unwrap();\n            assert!(py_string.to_cow().is_err());\n        })\n    }\n\n    #[test]\n    fn test_to_cow_unicode() {\n        Python::attach(|py| {\n            let s = \"哈哈🐈\";\n            let py_string = PyString::new(py, s);\n            assert_eq!(s, py_string.to_cow().unwrap());\n        })\n    }\n\n    #[test]\n    fn test_encode_utf8_unicode() {\n        Python::attach(|py| {\n            let s = \"哈哈🐈\";\n            let obj = PyString::new(py, s);\n            assert_eq!(s.as_bytes(), obj.encode_utf8().unwrap().as_bytes());\n        })\n    }\n\n    #[test]\n    fn test_encode_utf8_surrogate() {\n        Python::attach(|py| {\n            let obj: Py<PyAny> = py.eval(cr\"'\\ud800'\", None, None).unwrap().into();\n            assert!(obj\n                .bind(py)\n                .cast::<PyString>()\n                .unwrap()\n                .encode_utf8()\n                .is_err());\n        })\n    }\n\n    #[test]\n    fn test_to_string_lossy() {\n        Python::attach(|py| {\n            let py_string = py\n                .eval(cr\"'🐈 Hello \\ud800World'\", None, None)\n                .unwrap()\n                .cast_into::<PyString>()\n                .unwrap();\n\n            assert_eq!(py_string.to_string_lossy(), \"🐈 Hello ���World\");\n        })\n    }\n\n    #[test]\n    fn test_debug_string() {\n        Python::attach(|py| {\n            let s = \"Hello\\n\".into_pyobject(py).unwrap();\n            assert_eq!(format!(\"{s:?}\"), \"'Hello\\\\n'\");\n        })\n    }\n\n    #[test]\n    fn test_display_string() {\n        Python::attach(|py| {\n            let s = \"Hello\\n\".into_pyobject(py).unwrap();\n            assert_eq!(format!(\"{s}\"), \"Hello\\n\");\n        })\n    }\n\n    #[test]\n    fn test_string_from_encoded_object() {\n        Python::attach(|py| {\n            let py_bytes = PyBytes::new(py, b\"ab\\xFFcd\");\n\n            // default encoding is utf-8, default error handler is strict\n            let py_string = PyString::from_encoded_object(&py_bytes, None, None).unwrap_err();\n            assert!(py_string\n                .get_type(py)\n                .is(py.get_type::<crate::exceptions::PyUnicodeDecodeError>()));\n\n            // with `ignore` error handler, the invalid byte is dropped\n            let py_string =\n                PyString::from_encoded_object(&py_bytes, None, Some(c\"ignore\")).unwrap();\n\n            let result = py_string.to_cow().unwrap();\n            assert_eq!(result, \"abcd\");\n        });\n    }\n\n    #[test]\n    fn test_string_from_encoded_object_with_invalid_encoding_errors() {\n        Python::attach(|py| {\n            let py_bytes = PyBytes::new(py, b\"abcd\");\n\n            // invalid encoding\n            let err = PyString::from_encoded_object(&py_bytes, Some(c\"wat\"), None).unwrap_err();\n            assert!(err.is_instance(py, &py.get_type::<PyLookupError>()));\n            assert_eq!(err.to_string(), \"LookupError: unknown encoding: wat\");\n\n            // invalid error handler\n            let err =\n                PyString::from_encoded_object(&PyBytes::new(py, b\"ab\\xFFcd\"), None, Some(c\"wat\"))\n                    .unwrap_err();\n            assert!(err.is_instance(py, &py.get_type::<PyLookupError>()));\n            assert_eq!(\n                err.to_string(),\n                \"LookupError: unknown error handler name 'wat'\"\n            );\n        });\n    }\n\n    #[test]\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    fn test_string_data_ucs1() {\n        Python::attach(|py| {\n            let s = PyString::new(py, \"hello, world\");\n            let data = unsafe { s.data().unwrap() };\n\n            assert_eq!(data, PyStringData::Ucs1(b\"hello, world\"));\n            assert_eq!(data.to_string(py).unwrap(), Cow::Borrowed(\"hello, world\"));\n            assert_eq!(data.to_string_lossy(), Cow::Borrowed(\"hello, world\"));\n        })\n    }\n\n    #[test]\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    fn test_string_data_ucs1_invalid() {\n        Python::attach(|py| {\n            // 0xfe is not allowed in UTF-8.\n            let buffer = b\"f\\xfe\\0\";\n            let ptr = unsafe {\n                crate::ffi::PyUnicode_FromKindAndData(\n                    crate::ffi::PyUnicode_1BYTE_KIND as _,\n                    buffer.as_ptr().cast(),\n                    2,\n                )\n            };\n            assert!(!ptr.is_null());\n            let s = unsafe { ptr.assume_owned(py).cast_into_unchecked::<PyString>() };\n            let data = unsafe { s.data().unwrap() };\n            assert_eq!(data, PyStringData::Ucs1(b\"f\\xfe\"));\n            let err = data.to_string(py).unwrap_err();\n            assert!(err.get_type(py).is(py.get_type::<PyUnicodeDecodeError>()));\n            assert!(err\n                .to_string()\n                .contains(\"'utf-8' codec can't decode byte 0xfe in position 1\"));\n            assert_eq!(data.to_string_lossy(), Cow::Borrowed(\"f�\"));\n        });\n    }\n\n    #[test]\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    fn test_string_data_ucs2() {\n        Python::attach(|py| {\n            let s = py.eval(c\"'foo\\\\ud800'\", None, None).unwrap();\n            let py_string = s.cast::<PyString>().unwrap();\n            let data = unsafe { py_string.data().unwrap() };\n\n            assert_eq!(data, PyStringData::Ucs2(&[102, 111, 111, 0xd800]));\n            assert_eq!(\n                data.to_string_lossy(),\n                Cow::Owned::<str>(\"foo�\".to_string())\n            );\n        })\n    }\n\n    #[test]\n    #[cfg(all(not(any(Py_LIMITED_API, PyPy, GraalPy)), target_endian = \"little\"))]\n    fn test_string_data_ucs2_invalid() {\n        Python::attach(|py| {\n            // U+FF22 (valid) & U+d800 (never valid)\n            let buffer = b\"\\x22\\xff\\x00\\xd8\\x00\\x00\";\n            let ptr = unsafe {\n                crate::ffi::PyUnicode_FromKindAndData(\n                    crate::ffi::PyUnicode_2BYTE_KIND as _,\n                    buffer.as_ptr().cast(),\n                    2,\n                )\n            };\n            assert!(!ptr.is_null());\n            let s = unsafe { ptr.assume_owned(py).cast_into_unchecked::<PyString>() };\n            let data = unsafe { s.data().unwrap() };\n            assert_eq!(data, PyStringData::Ucs2(&[0xff22, 0xd800]));\n            let err = data.to_string(py).unwrap_err();\n            assert!(err.get_type(py).is(py.get_type::<PyUnicodeDecodeError>()));\n            assert!(err\n                .to_string()\n                .contains(\"'utf-16' codec can't decode bytes in position 0-3\"));\n            assert_eq!(data.to_string_lossy(), Cow::Owned::<str>(\"Ｂ�\".into()));\n        });\n    }\n\n    #[test]\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    fn test_string_data_ucs4() {\n        Python::attach(|py| {\n            let s = \"哈哈🐈\";\n            let py_string = PyString::new(py, s);\n            let data = unsafe { py_string.data().unwrap() };\n\n            assert_eq!(data, PyStringData::Ucs4(&[21704, 21704, 128008]));\n            assert_eq!(data.to_string_lossy(), Cow::Owned::<str>(s.to_string()));\n        })\n    }\n\n    #[test]\n    #[cfg(all(not(any(Py_LIMITED_API, PyPy, GraalPy)), target_endian = \"little\"))]\n    fn test_string_data_ucs4_invalid() {\n        Python::attach(|py| {\n            // U+20000 (valid) & U+d800 (never valid)\n            let buffer = b\"\\x00\\x00\\x02\\x00\\x00\\xd8\\x00\\x00\\x00\\x00\\x00\\x00\";\n            let ptr = unsafe {\n                crate::ffi::PyUnicode_FromKindAndData(\n                    crate::ffi::PyUnicode_4BYTE_KIND as _,\n                    buffer.as_ptr().cast(),\n                    2,\n                )\n            };\n            assert!(!ptr.is_null());\n            let s = unsafe { ptr.assume_owned(py).cast_into_unchecked::<PyString>() };\n            let data = unsafe { s.data().unwrap() };\n            assert_eq!(data, PyStringData::Ucs4(&[0x20000, 0xd800]));\n            let err = data.to_string(py).unwrap_err();\n            assert!(err.get_type(py).is(py.get_type::<PyUnicodeDecodeError>()));\n            assert!(err\n                .to_string()\n                .contains(\"'utf-32' codec can't decode bytes in position 0-7\"));\n            assert_eq!(data.to_string_lossy(), Cow::Owned::<str>(\"𠀀�\".into()));\n        });\n    }\n\n    #[test]\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    fn test_pystring_from_bytes() {\n        Python::attach(|py| {\n            let result = PyString::from_bytes(py, \"\\u{2122}\".as_bytes());\n            assert!(result.is_ok());\n            let result = PyString::from_bytes(py, b\"\\x80\");\n            assert!(result\n                .unwrap_err()\n                .get_type(py)\n                .is(py.get_type::<PyUnicodeDecodeError>()));\n        });\n    }\n\n    #[test]\n    fn test_intern_string() {\n        Python::attach(|py| {\n            let py_string1 = PyString::intern(py, \"foo\");\n            assert_eq!(py_string1, \"foo\");\n\n            let py_string2 = PyString::intern(py, \"foo\");\n            assert_eq!(py_string2, \"foo\");\n\n            assert_eq!(py_string1.as_ptr(), py_string2.as_ptr());\n\n            let py_string3 = PyString::intern(py, \"bar\");\n            assert_eq!(py_string3, \"bar\");\n\n            assert_ne!(py_string1.as_ptr(), py_string3.as_ptr());\n        });\n    }\n\n    #[test]\n    fn test_py_to_str_utf8() {\n        Python::attach(|py| {\n            let s = \"ascii 🐈\";\n            let py_string = PyString::new(py, s).unbind();\n\n            #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n            assert_eq!(s, py_string.to_str(py).unwrap());\n\n            assert_eq!(s, py_string.to_cow(py).unwrap());\n        })\n    }\n\n    #[test]\n    fn test_py_to_str_surrogate() {\n        Python::attach(|py| {\n            let py_string: Py<PyString> = py\n                .eval(cr\"'\\ud800'\", None, None)\n                .unwrap()\n                .extract()\n                .unwrap();\n\n            #[cfg(any(Py_3_10, not(Py_LIMITED_API)))]\n            assert!(py_string.to_str(py).is_err());\n\n            assert!(py_string.to_cow(py).is_err());\n        })\n    }\n\n    #[test]\n    fn test_py_to_string_lossy() {\n        Python::attach(|py| {\n            let py_string: Py<PyString> = py\n                .eval(cr\"'🐈 Hello \\ud800World'\", None, None)\n                .unwrap()\n                .extract()\n                .unwrap();\n            assert_eq!(py_string.to_string_lossy(py), \"🐈 Hello ���World\");\n        })\n    }\n\n    #[test]\n    fn test_comparisons() {\n        Python::attach(|py| {\n            let s = \"hello, world\";\n            let py_string = PyString::new(py, s);\n\n            assert_eq!(py_string, \"hello, world\");\n\n            assert_eq!(py_string, s);\n            assert_eq!(&py_string, s);\n            assert_eq!(s, py_string);\n            assert_eq!(s, &py_string);\n\n            assert_eq!(py_string, *s);\n            assert_eq!(&py_string, *s);\n            assert_eq!(*s, py_string);\n            assert_eq!(*s, &py_string);\n\n            let py_string = py_string.as_borrowed();\n\n            assert_eq!(py_string, s);\n            assert_eq!(&py_string, s);\n            assert_eq!(s, py_string);\n            assert_eq!(s, &py_string);\n\n            assert_eq!(py_string, *s);\n            assert_eq!(*s, py_string);\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/traceback.rs",
    "content": "use crate::err::{error_on_minusone, PyResult};\nuse crate::types::{any::PyAnyMethods, string::PyStringMethods, PyString};\nuse crate::{ffi, Bound, PyAny};\n#[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]\nuse crate::{types::PyFrame, PyTypeCheck, Python};\n\n/// Represents a Python traceback.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyTraceback>`][crate::Py] or [`Bound<'py, PyTraceback>`][Bound].\n///\n/// For APIs available on traceback objects, see the [`PyTracebackMethods`] trait which is implemented for\n/// [`Bound<'py, PyTraceback>`][Bound].\n#[repr(transparent)]\npub struct PyTraceback(PyAny);\n\npyobject_native_type_core!(\n    PyTraceback,\n    pyobject_native_static_type_object!(ffi::PyTraceBack_Type),\n    \"builtins\",\n    \"traceback\",\n    #checkfunction=ffi::PyTraceBack_Check\n);\n\nimpl PyTraceback {\n    /// Creates a new traceback object from the given frame.\n    ///\n    /// The `next` is the next traceback in the direction of where the exception was raised\n    /// or `None` if this is the last frame in the traceback.\n    #[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]\n    pub fn new<'py>(\n        py: Python<'py>,\n        next: Option<Bound<'py, PyTraceback>>,\n        frame: Bound<'py, PyFrame>,\n        instruction_index: i32,\n        line_number: i32,\n    ) -> PyResult<Bound<'py, PyTraceback>> {\n        unsafe {\n            Ok(PyTraceback::classinfo_object(py)\n                .call1((next, frame, instruction_index, line_number))?\n                .cast_into_unchecked())\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyTraceback`].\n///\n/// These methods are defined for the `Bound<'py, PyTraceback>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyTraceback\")]\npub trait PyTracebackMethods<'py>: crate::sealed::Sealed {\n    /// Formats the traceback as a string.\n    ///\n    /// This does not include the exception type and value. The exception type and value can be\n    /// formatted using the `Display` implementation for `PyErr`.\n    ///\n    /// # Example\n    ///\n    /// The following code formats a Python traceback and exception pair from Rust:\n    ///\n    /// ```rust\n    /// # use pyo3::{Python, PyResult, prelude::PyTracebackMethods, ffi::c_str};\n    /// # let result: PyResult<()> =\n    /// Python::attach(|py| {\n    ///     let err = py\n    ///         .run(c\"raise Exception('banana')\", None, None)\n    ///         .expect_err(\"raise will create a Python error\");\n    ///\n    ///     let traceback = err.traceback(py).expect(\"raised exception will have a traceback\");\n    ///     assert_eq!(\n    ///         format!(\"{}{}\", traceback.format()?, err),\n    ///         \"\\\n    /// Traceback (most recent call last):\n    ///   File \\\"<string>\\\", line 1, in <module>\n    /// Exception: banana\\\n    /// \"\n    ///     );\n    ///     Ok(())\n    /// })\n    /// # ;\n    /// # result.expect(\"example failed\");\n    /// ```\n    fn format(&self) -> PyResult<String>;\n}\n\nimpl<'py> PyTracebackMethods<'py> for Bound<'py, PyTraceback> {\n    fn format(&self) -> PyResult<String> {\n        let py = self.py();\n        let string_io = py\n            .import(intern!(py, \"io\"))?\n            .getattr(intern!(py, \"StringIO\"))?\n            .call0()?;\n        let result = unsafe { ffi::PyTraceBack_Print(self.as_ptr(), string_io.as_ptr()) };\n        error_on_minusone(py, result)?;\n        let formatted = string_io\n            .getattr(intern!(py, \"getvalue\"))?\n            .call0()?\n            .cast::<PyString>()?\n            .to_cow()?\n            .into_owned();\n        Ok(formatted)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::IntoPyObject;\n    use crate::{\n        types::{dict::PyDictMethods, PyDict},\n        PyErr, Python,\n    };\n\n    #[test]\n    fn format_traceback() {\n        Python::attach(|py| {\n            let err = py\n                .run(c\"raise Exception('banana')\", None, None)\n                .expect_err(\"raising should have given us an error\");\n\n            assert_eq!(\n                err.traceback(py).unwrap().format().unwrap(),\n                \"Traceback (most recent call last):\\n  File \\\"<string>\\\", line 1, in <module>\\n\"\n            );\n        })\n    }\n\n    #[test]\n    fn test_err_from_value() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            // Produce an error from python so that it has a traceback\n            py.run(\n                cr\"\ntry:\n    raise ValueError('raised exception')\nexcept Exception as e:\n    err = e\n\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let err = PyErr::from_value(locals.get_item(\"err\").unwrap().unwrap());\n            let traceback = err.value(py).getattr(\"__traceback__\").unwrap();\n            assert!(err.traceback(py).unwrap().is(&traceback));\n        })\n    }\n\n    #[test]\n    fn test_err_into_py() {\n        Python::attach(|py| {\n            let locals = PyDict::new(py);\n            // Produce an error from python so that it has a traceback\n            py.run(\n                cr\"\ndef f():\n    raise ValueError('raised exception')\n\",\n                None,\n                Some(&locals),\n            )\n            .unwrap();\n            let f = locals.get_item(\"f\").unwrap().unwrap();\n            let err = f.call0().unwrap_err();\n            let traceback = err.traceback(py).unwrap();\n            let err_object = err.clone_ref(py).into_pyobject(py).unwrap();\n\n            assert!(err_object.getattr(\"__traceback__\").unwrap().is(&traceback));\n        })\n    }\n\n    #[test]\n    #[cfg(all(not(Py_LIMITED_API), not(PyPy), not(GraalPy)))]\n    fn test_create_traceback() {\n        Python::attach(|py| {\n            let traceback = PyTraceback::new(\n                py,\n                None,\n                PyFrame::new(py, c\"file2.py\", c\"func2\", 20).unwrap(),\n                0,\n                20,\n            )\n            .unwrap();\n            let traceback = PyTraceback::new(\n                py,\n                Some(traceback),\n                PyFrame::new(py, c\"file1.py\", c\"func1\", 10).unwrap(),\n                0,\n                10,\n            )\n            .unwrap();\n            assert_eq!(\n                traceback.format().unwrap(), \"Traceback (most recent call last):\\n  File \\\"file1.py\\\", line 10, in func1\\n  File \\\"file2.py\\\", line 20, in func2\\n\"\n            );\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/tuple.rs",
    "content": "use crate::ffi::{self, Py_ssize_t};\nuse crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_subscript, PyStaticExpr};\nuse crate::instance::Borrowed;\nuse crate::internal_tricks::get_ssize_index;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::type_object::PyTypeInfo;\nuse crate::types::{sequence::PySequenceMethods, PyList, PySequence};\nuse crate::{\n    exceptions, Bound, FromPyObject, IntoPyObject, IntoPyObjectExt, PyAny, PyErr, PyResult, Python,\n};\nuse std::iter::FusedIterator;\n#[cfg(feature = \"nightly\")]\nuse std::num::NonZero;\n\n#[inline]\n#[track_caller]\nfn try_new_from_iter<'py>(\n    py: Python<'py>,\n    mut elements: impl ExactSizeIterator<Item = PyResult<Bound<'py, PyAny>>>,\n) -> PyResult<Bound<'py, PyTuple>> {\n    unsafe {\n        // PyTuple_New checks for overflow but has a bad error message, so we check ourselves\n        let len: Py_ssize_t = elements\n            .len()\n            .try_into()\n            .expect(\"out of range integral type conversion attempted on `elements.len()`\");\n\n        let ptr = ffi::PyTuple_New(len);\n\n        // - Panics if the ptr is null\n        // - Cleans up the tuple if `convert` or the asserts panic\n        let tup = ptr.assume_owned(py).cast_into_unchecked();\n\n        let mut counter: Py_ssize_t = 0;\n\n        for obj in (&mut elements).take(len as usize) {\n            #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n            ffi::PyTuple_SET_ITEM(ptr, counter, obj?.into_ptr());\n            #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))]\n            ffi::PyTuple_SetItem(ptr, counter, obj?.into_ptr());\n            counter += 1;\n        }\n\n        assert!(elements.next().is_none(), \"Attempted to create PyTuple but `elements` was larger than reported by its `ExactSizeIterator` implementation.\");\n        assert_eq!(len, counter, \"Attempted to create PyTuple but `elements` was smaller than reported by its `ExactSizeIterator` implementation.\");\n\n        Ok(tup)\n    }\n}\n\n/// Represents a Python `tuple` object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyTuple>`][crate::Py] or [`Bound<'py, PyTuple>`][Bound].\n///\n/// For APIs available on `tuple` objects, see the [`PyTupleMethods`] trait which is implemented for\n/// [`Bound<'py, PyTuple>`][Bound].\n#[repr(transparent)]\npub struct PyTuple(PyAny);\n\npyobject_native_type_core!(PyTuple, pyobject_native_static_type_object!(ffi::PyTuple_Type), \"builtins\", \"tuple\", #checkfunction=ffi::PyTuple_Check);\n\nimpl PyTuple {\n    /// Constructs a new tuple with the given elements.\n    ///\n    /// If you want to create a [`PyTuple`] with elements of different or unknown types, create a Rust\n    /// tuple with the given elements and convert it at once using [`into_pyobject()`][crate::IntoPyObject].\n    /// (`IntoPyObject` is implemented for tuples of up to 12 elements.)\n    ///\n    /// To create a [`PyTuple`] from an iterable that doesn't implement [`ExactSizeIterator`],\n    /// collect the elements into a `Vec` first.\n    ///\n    /// # Examples\n    ///\n    /// ```rust\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyTuple;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let elements: Vec<i32> = vec![0, 1, 2, 3, 4, 5];\n    ///     let tuple = PyTuple::new(py, elements)?;\n    ///     assert_eq!(format!(\"{:?}\", tuple), \"(0, 1, 2, 3, 4, 5)\");\n    ///\n    ///     // alternative using `into_pyobject()`\n    ///     let tuple = (0, \"hello\", true).into_pyobject(py)?;\n    ///     assert_eq!(format!(\"{:?}\", tuple), \"(0, 'hello', True)\");\n    /// # Ok(())\n    /// })\n    /// # }\n    /// ```\n    ///\n    /// # Panics\n    ///\n    /// This function will panic if `element`'s [`ExactSizeIterator`] implementation is incorrect.\n    /// All standard library structures implement this trait correctly, if they do, so calling this\n    /// function using [`Vec`]`<T>` or `&[T]` will always succeed.\n    #[track_caller]\n    pub fn new<'py, T, U>(\n        py: Python<'py>,\n        elements: impl IntoIterator<Item = T, IntoIter = U>,\n    ) -> PyResult<Bound<'py, PyTuple>>\n    where\n        T: IntoPyObject<'py>,\n        U: ExactSizeIterator<Item = T>,\n    {\n        let elements = elements.into_iter().map(|e| e.into_bound_py_any(py));\n        try_new_from_iter(py, elements)\n    }\n\n    /// Constructs an empty tuple (on the Python side, a singleton object).\n    pub fn empty(py: Python<'_>) -> Bound<'_, PyTuple> {\n        unsafe { ffi::PyTuple_New(0).assume_owned(py).cast_into_unchecked() }\n    }\n}\n\n/// Implementation of functionality for [`PyTuple`].\n///\n/// These methods are defined for the `Bound<'py, PyTuple>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyTuple\")]\npub trait PyTupleMethods<'py>: crate::sealed::Sealed {\n    /// Gets the length of the tuple.\n    fn len(&self) -> usize;\n\n    /// Checks if the tuple is empty.\n    fn is_empty(&self) -> bool;\n\n    /// Returns `self` cast as a `PySequence`.\n    fn as_sequence(&self) -> &Bound<'py, PySequence>;\n\n    /// Returns `self` cast as a `PySequence`.\n    fn into_sequence(self) -> Bound<'py, PySequence>;\n\n    /// Takes the slice `self[low:high]` and returns it as a new tuple.\n    ///\n    /// Indices must be nonnegative, and out-of-range indices are clipped to\n    /// `self.len()`.\n    fn get_slice(&self, low: usize, high: usize) -> Bound<'py, PyTuple>;\n\n    /// Gets the tuple item at the specified index.\n    /// # Example\n    /// ```\n    /// use pyo3::prelude::*;\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| -> PyResult<()> {\n    ///     let tuple = (1, 2, 3).into_pyobject(py)?;\n    ///     let obj = tuple.get_item(0);\n    ///     assert_eq!(obj?.extract::<i32>()?, 1);\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    fn get_item(&self, index: usize) -> PyResult<Bound<'py, PyAny>>;\n\n    /// Like [`get_item`][PyTupleMethods::get_item], but returns a borrowed object, which is a slight performance optimization\n    /// by avoiding a reference count change.\n    fn get_borrowed_item<'a>(&'a self, index: usize) -> PyResult<Borrowed<'a, 'py, PyAny>>;\n\n    /// Gets the tuple item at the specified index. Undefined behavior on bad index, or if the tuple\n    /// contains a null pointer at the specified index. Use with caution.\n    ///\n    /// # Safety\n    ///\n    /// - Caller must verify that the index is within the bounds of the tuple.\n    /// - A null pointer is only legal in a tuple which is in the process of being initialized, callers\n    ///   can typically assume the tuple item is non-null unless they are knowingly filling an\n    ///   uninitialized tuple. (If a tuple were to contain a null pointer element, accessing it from Python\n    ///   typically causes a segfault.)\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny>;\n\n    /// Like [`get_item_unchecked`][PyTupleMethods::get_item_unchecked], but returns a borrowed object,\n    /// which is a slight performance optimization by avoiding a reference count change.\n    ///\n    /// # Safety\n    ///\n    /// See [`get_item_unchecked`][PyTupleMethods::get_item_unchecked].\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    unsafe fn get_borrowed_item_unchecked<'a>(&'a self, index: usize) -> Borrowed<'a, 'py, PyAny>;\n\n    /// Returns `self` as a slice of objects.\n    #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\n    fn as_slice(&self) -> &[Bound<'py, PyAny>];\n\n    /// Determines if self contains `value`.\n    ///\n    /// This is equivalent to the Python expression `value in self`.\n    fn contains<V>(&self, value: V) -> PyResult<bool>\n    where\n        V: IntoPyObject<'py>;\n\n    /// Returns the first index `i` for which `self[i] == value`.\n    ///\n    /// This is equivalent to the Python expression `self.index(value)`.\n    fn index<V>(&self, value: V) -> PyResult<usize>\n    where\n        V: IntoPyObject<'py>;\n\n    /// Returns an iterator over the tuple items.\n    fn iter(&self) -> BoundTupleIterator<'py>;\n\n    /// Like [`iter`][PyTupleMethods::iter], but produces an iterator which returns borrowed objects,\n    /// which is a slight performance optimization by avoiding a reference count change.\n    fn iter_borrowed<'a>(&'a self) -> BorrowedTupleIterator<'a, 'py>;\n\n    /// Return a new list containing the contents of this tuple; equivalent to the Python expression `list(tuple)`.\n    ///\n    /// This method is equivalent to `self.as_sequence().to_list()` and faster than `PyList::new(py, self)`.\n    fn to_list(&self) -> Bound<'py, PyList>;\n}\n\nimpl<'py> PyTupleMethods<'py> for Bound<'py, PyTuple> {\n    fn len(&self) -> usize {\n        unsafe {\n            #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n            let size = ffi::PyTuple_GET_SIZE(self.as_ptr());\n            #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))]\n            let size = ffi::PyTuple_Size(self.as_ptr());\n            // non-negative Py_ssize_t should always fit into Rust uint\n            size as usize\n        }\n    }\n\n    fn is_empty(&self) -> bool {\n        self.len() == 0\n    }\n\n    fn as_sequence(&self) -> &Bound<'py, PySequence> {\n        unsafe { self.cast_unchecked() }\n    }\n\n    fn into_sequence(self) -> Bound<'py, PySequence> {\n        unsafe { self.cast_into_unchecked() }\n    }\n\n    fn get_slice(&self, low: usize, high: usize) -> Bound<'py, PyTuple> {\n        unsafe {\n            ffi::PyTuple_GetSlice(self.as_ptr(), get_ssize_index(low), get_ssize_index(high))\n                .assume_owned(self.py())\n                .cast_into_unchecked()\n        }\n    }\n\n    fn get_item(&self, index: usize) -> PyResult<Bound<'py, PyAny>> {\n        self.get_borrowed_item(index).map(Borrowed::to_owned)\n    }\n\n    fn get_borrowed_item<'a>(&'a self, index: usize) -> PyResult<Borrowed<'a, 'py, PyAny>> {\n        self.as_borrowed().get_borrowed_item(index)\n    }\n\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    unsafe fn get_item_unchecked(&self, index: usize) -> Bound<'py, PyAny> {\n        unsafe { self.get_borrowed_item_unchecked(index).to_owned() }\n    }\n\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    unsafe fn get_borrowed_item_unchecked<'a>(&'a self, index: usize) -> Borrowed<'a, 'py, PyAny> {\n        unsafe { self.as_borrowed().get_borrowed_item_unchecked(index) }\n    }\n\n    #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\n    fn as_slice(&self) -> &[Bound<'py, PyAny>] {\n        // SAFETY: self is known to be a tuple object, and tuples are immutable\n        let items = unsafe { &(*self.as_ptr().cast::<ffi::PyTupleObject>()).ob_item };\n        // SAFETY: Bound<'py, PyAny> has the same memory layout as *mut ffi::PyObject\n        unsafe { std::slice::from_raw_parts(items.as_ptr().cast(), self.len()) }\n    }\n\n    #[inline]\n    fn contains<V>(&self, value: V) -> PyResult<bool>\n    where\n        V: IntoPyObject<'py>,\n    {\n        self.as_sequence().contains(value)\n    }\n\n    #[inline]\n    fn index<V>(&self, value: V) -> PyResult<usize>\n    where\n        V: IntoPyObject<'py>,\n    {\n        self.as_sequence().index(value)\n    }\n\n    fn iter(&self) -> BoundTupleIterator<'py> {\n        BoundTupleIterator::new(self.clone())\n    }\n\n    fn iter_borrowed<'a>(&'a self) -> BorrowedTupleIterator<'a, 'py> {\n        self.as_borrowed().iter_borrowed()\n    }\n\n    fn to_list(&self) -> Bound<'py, PyList> {\n        self.as_sequence()\n            .to_list()\n            .expect(\"failed to convert tuple to list\")\n    }\n}\n\nimpl<'a, 'py> Borrowed<'a, 'py, PyTuple> {\n    fn get_borrowed_item(self, index: usize) -> PyResult<Borrowed<'a, 'py, PyAny>> {\n        unsafe {\n            ffi::PyTuple_GetItem(self.as_ptr(), index as Py_ssize_t)\n                .assume_borrowed_or_err(self.py())\n        }\n    }\n\n    /// # Safety\n    ///\n    /// See `get_item_unchecked` in `PyTupleMethods`.\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    unsafe fn get_borrowed_item_unchecked(self, index: usize) -> Borrowed<'a, 'py, PyAny> {\n        // SAFETY: caller has upheld the safety contract\n        unsafe {\n            ffi::PyTuple_GET_ITEM(self.as_ptr(), index as Py_ssize_t)\n                .assume_borrowed_unchecked(self.py())\n        }\n    }\n\n    pub(crate) fn iter_borrowed(self) -> BorrowedTupleIterator<'a, 'py> {\n        BorrowedTupleIterator::new(self)\n    }\n}\n\n/// Used by `PyTuple::into_iter()`.\npub struct BoundTupleIterator<'py> {\n    tuple: Bound<'py, PyTuple>,\n    index: usize,\n    length: usize,\n}\n\nimpl<'py> BoundTupleIterator<'py> {\n    fn new(tuple: Bound<'py, PyTuple>) -> Self {\n        let length = tuple.len();\n        BoundTupleIterator {\n            tuple,\n            index: 0,\n            length,\n        }\n    }\n}\n\nimpl<'py> Iterator for BoundTupleIterator<'py> {\n    type Item = Bound<'py, PyAny>;\n\n    #[inline]\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.index < self.length {\n            let item = unsafe {\n                BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), self.index).to_owned()\n            };\n            self.index += 1;\n            Some(item)\n        } else {\n            None\n        }\n    }\n\n    #[inline]\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let len = self.len();\n        (len, Some(len))\n    }\n\n    #[inline]\n    fn count(self) -> usize\n    where\n        Self: Sized,\n    {\n        self.len()\n    }\n\n    #[inline]\n    fn last(mut self) -> Option<Self::Item>\n    where\n        Self: Sized,\n    {\n        self.next_back()\n    }\n\n    #[inline]\n    #[cfg(not(feature = \"nightly\"))]\n    fn nth(&mut self, n: usize) -> Option<Self::Item> {\n        let length = self.length.min(self.tuple.len());\n        let target_index = self.index + n;\n        if target_index < length {\n            let item = unsafe {\n                BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), target_index).to_owned()\n            };\n            self.index = target_index + 1;\n            Some(item)\n        } else {\n            None\n        }\n    }\n\n    #[inline]\n    #[cfg(feature = \"nightly\")]\n    fn advance_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {\n        let max_len = self.length.min(self.tuple.len());\n        let currently_at = self.index;\n        if currently_at >= max_len {\n            if n == 0 {\n                return Ok(());\n            } else {\n                return Err(unsafe { NonZero::new_unchecked(n) });\n            }\n        }\n\n        let items_left = max_len - currently_at;\n        if n <= items_left {\n            self.index += n;\n            Ok(())\n        } else {\n            self.index = max_len;\n            let remainder = n - items_left;\n            Err(unsafe { NonZero::new_unchecked(remainder) })\n        }\n    }\n}\n\nimpl DoubleEndedIterator for BoundTupleIterator<'_> {\n    #[inline]\n    fn next_back(&mut self) -> Option<Self::Item> {\n        if self.index < self.length {\n            let item = unsafe {\n                BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), self.length - 1)\n                    .to_owned()\n            };\n            self.length -= 1;\n            Some(item)\n        } else {\n            None\n        }\n    }\n\n    #[inline]\n    #[cfg(not(feature = \"nightly\"))]\n    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {\n        let length_size = self.length.min(self.tuple.len());\n        if self.index + n < length_size {\n            let target_index = length_size - n - 1;\n            let item = unsafe {\n                BorrowedTupleIterator::get_item(self.tuple.as_borrowed(), target_index).to_owned()\n            };\n            self.length = target_index;\n            Some(item)\n        } else {\n            None\n        }\n    }\n\n    #[inline]\n    #[cfg(feature = \"nightly\")]\n    fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero<usize>> {\n        let max_len = self.length.min(self.tuple.len());\n        let currently_at = self.index;\n        if currently_at >= max_len {\n            if n == 0 {\n                return Ok(());\n            } else {\n                return Err(unsafe { NonZero::new_unchecked(n) });\n            }\n        }\n\n        let items_left = max_len - currently_at;\n        if n <= items_left {\n            self.length = max_len - n;\n            Ok(())\n        } else {\n            self.length = currently_at;\n            let remainder = n - items_left;\n            Err(unsafe { NonZero::new_unchecked(remainder) })\n        }\n    }\n}\n\nimpl ExactSizeIterator for BoundTupleIterator<'_> {\n    fn len(&self) -> usize {\n        self.length.saturating_sub(self.index)\n    }\n}\n\nimpl FusedIterator for BoundTupleIterator<'_> {}\n\nimpl<'py> IntoIterator for Bound<'py, PyTuple> {\n    type Item = Bound<'py, PyAny>;\n    type IntoIter = BoundTupleIterator<'py>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        BoundTupleIterator::new(self)\n    }\n}\n\nimpl<'py> IntoIterator for &Bound<'py, PyTuple> {\n    type Item = Bound<'py, PyAny>;\n    type IntoIter = BoundTupleIterator<'py>;\n\n    fn into_iter(self) -> Self::IntoIter {\n        self.iter()\n    }\n}\n\n/// Used by `PyTuple::iter_borrowed()`.\npub struct BorrowedTupleIterator<'a, 'py> {\n    tuple: Borrowed<'a, 'py, PyTuple>,\n    index: usize,\n    length: usize,\n}\n\nimpl<'a, 'py> BorrowedTupleIterator<'a, 'py> {\n    fn new(tuple: Borrowed<'a, 'py, PyTuple>) -> Self {\n        let length = tuple.len();\n        BorrowedTupleIterator {\n            tuple,\n            index: 0,\n            length,\n        }\n    }\n\n    unsafe fn get_item(\n        tuple: Borrowed<'a, 'py, PyTuple>,\n        index: usize,\n    ) -> Borrowed<'a, 'py, PyAny> {\n        #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))]\n        let item = tuple.get_borrowed_item(index).expect(\"tuple.get failed\");\n        #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n        let item = unsafe { tuple.get_borrowed_item_unchecked(index) };\n        item\n    }\n}\n\nimpl<'a, 'py> Iterator for BorrowedTupleIterator<'a, 'py> {\n    type Item = Borrowed<'a, 'py, PyAny>;\n\n    #[inline]\n    fn next(&mut self) -> Option<Self::Item> {\n        if self.index < self.length {\n            let item = unsafe { Self::get_item(self.tuple, self.index) };\n            self.index += 1;\n            Some(item)\n        } else {\n            None\n        }\n    }\n\n    #[inline]\n    fn size_hint(&self) -> (usize, Option<usize>) {\n        let len = self.len();\n        (len, Some(len))\n    }\n\n    #[inline]\n    fn count(self) -> usize\n    where\n        Self: Sized,\n    {\n        self.len()\n    }\n\n    #[inline]\n    fn last(mut self) -> Option<Self::Item>\n    where\n        Self: Sized,\n    {\n        self.next_back()\n    }\n}\n\nimpl DoubleEndedIterator for BorrowedTupleIterator<'_, '_> {\n    #[inline]\n    fn next_back(&mut self) -> Option<Self::Item> {\n        if self.index < self.length {\n            let item = unsafe { Self::get_item(self.tuple, self.length - 1) };\n            self.length -= 1;\n            Some(item)\n        } else {\n            None\n        }\n    }\n}\n\nimpl ExactSizeIterator for BorrowedTupleIterator<'_, '_> {\n    fn len(&self) -> usize {\n        self.length.saturating_sub(self.index)\n    }\n}\n\nimpl FusedIterator for BorrowedTupleIterator<'_, '_> {}\n\n#[cold]\nfn wrong_tuple_length(t: Borrowed<'_, '_, PyTuple>, expected_length: usize) -> PyErr {\n    let msg = format!(\n        \"expected tuple of length {}, but got tuple of length {}\",\n        expected_length,\n        t.len()\n    );\n    exceptions::PyValueError::new_err(msg)\n}\n\nmacro_rules! tuple_conversion ({$length:expr,$(($refN:ident, $n:tt, $T:ident)),+} => {\n    impl <'py, $($T),+> IntoPyObject<'py> for ($($T,)+)\n    where\n        $($T: IntoPyObject<'py>,)+\n    {\n        type Target = PyTuple;\n        type Output = Bound<'py, Self::Target>;\n        type Error = PyErr;\n\n        #[cfg(feature = \"experimental-inspect\")]\n        const OUTPUT_TYPE: PyStaticExpr = type_hint_subscript!(\n            PyTuple::TYPE_HINT,\n            $($T::OUTPUT_TYPE),+\n        );\n\n        fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n            Ok(array_into_tuple(py, [$(self.$n.into_bound_py_any(py)?),+]))\n        }\n    }\n\n    impl <'a, 'py, $($T),+> IntoPyObject<'py> for &'a ($($T,)+)\n    where\n        $(&'a $T: IntoPyObject<'py>,)+\n    {\n        type Target = PyTuple;\n        type Output = Bound<'py, Self::Target>;\n        type Error = PyErr;\n\n        #[cfg(feature = \"experimental-inspect\")]\n        const OUTPUT_TYPE: PyStaticExpr = type_hint_subscript!(\n            PyTuple::TYPE_HINT,\n            $(<&$T>::OUTPUT_TYPE ),+\n        );\n\n        fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n            Ok(array_into_tuple(py, [$(self.$n.into_bound_py_any(py)?),+]))\n        }\n    }\n\n    impl<'py, $($T),+> crate::call::private::Sealed for ($($T,)+) where $($T: IntoPyObject<'py>,)+ {}\n    impl<'py, $($T),+> crate::call::PyCallArgs<'py> for ($($T,)+)\n    where\n        $($T: IntoPyObject<'py>,)+\n    {\n        #[cfg(all(Py_3_9, not(any(PyPy, GraalPy, Py_LIMITED_API))))]\n        fn call(\n            self,\n            function: Borrowed<'_, 'py, PyAny>,\n            kwargs: Borrowed<'_, '_, crate::types::PyDict>,\n            _: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            let py = function.py();\n            // We need this to drop the arguments correctly.\n            let args_bound = [$(self.$n.into_bound_py_any(py)?,)*];\n            // Prepend one null argument for `PY_VECTORCALL_ARGUMENTS_OFFSET`.\n            let mut args = [std::ptr::null_mut(), $(args_bound[$n].as_ptr()),*];\n            unsafe {\n                ffi::PyObject_VectorcallDict(\n                    function.as_ptr(),\n                    args.as_mut_ptr().add(1),\n                    $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET,\n                    kwargs.as_ptr(),\n                )\n                .assume_owned_or_err(py)\n            }\n        }\n\n        #[cfg(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12)))]\n        fn call_positional(\n            self,\n            function: Borrowed<'_, 'py, PyAny>,\n            _: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            let py = function.py();\n            // We need this to drop the arguments correctly.\n            let args_bound = [$(self.$n.into_bound_py_any(py)?,)*];\n\n            #[cfg(not(Py_LIMITED_API))]\n            if $length == 1 {\n                return unsafe {\n                    ffi::PyObject_CallOneArg(\n                       function.as_ptr(),\n                       args_bound[0].as_ptr()\n                    )\n                    .assume_owned_or_err(py)\n                };\n            }\n\n            // Prepend one null argument for `PY_VECTORCALL_ARGUMENTS_OFFSET`.\n            let mut args = [std::ptr::null_mut(), $(args_bound[$n].as_ptr()),*];\n            unsafe {\n                ffi::PyObject_Vectorcall(\n                    function.as_ptr(),\n                    args.as_mut_ptr().add(1),\n                    $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET,\n                    std::ptr::null_mut(),\n                )\n                .assume_owned_or_err(py)\n            }\n        }\n\n        #[cfg(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12)))]\n        fn call_method_positional(\n            self,\n            object: Borrowed<'_, 'py, PyAny>,\n            method_name: Borrowed<'_, 'py, crate::types::PyString>,\n            _: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            let py = object.py();\n            // We need this to drop the arguments correctly.\n            let args_bound = [$(self.$n.into_bound_py_any(py)?,)*];\n\n            #[cfg(not(Py_LIMITED_API))]\n            if $length == 1 {\n                return unsafe {\n                    ffi::PyObject_CallMethodOneArg(\n                            object.as_ptr(),\n                            method_name.as_ptr(),\n                            args_bound[0].as_ptr(),\n                    )\n                    .assume_owned_or_err(py)\n                };\n            }\n\n            let mut args = [object.as_ptr(), $(args_bound[$n].as_ptr()),*];\n            unsafe {\n                ffi::PyObject_VectorcallMethod(\n                    method_name.as_ptr(),\n                    args.as_mut_ptr(),\n                    // +1 for the receiver.\n                    1 + $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET,\n                    std::ptr::null_mut(),\n                )\n                .assume_owned_or_err(py)\n            }\n\n        }\n\n        #[cfg(not(all(Py_3_9, not(any(PyPy, GraalPy, Py_LIMITED_API)))))]\n        fn call(\n            self,\n            function: Borrowed<'_, 'py, PyAny>,\n            kwargs: Borrowed<'_, 'py, crate::types::PyDict>,\n            token: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            self.into_pyobject_or_pyerr(function.py())?.call(function, kwargs, token)\n        }\n\n        #[cfg(not(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12))))]\n        fn call_positional(\n            self,\n            function: Borrowed<'_, 'py, PyAny>,\n            token: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            self.into_pyobject_or_pyerr(function.py())?.call_positional(function, token)\n        }\n\n        #[cfg(not(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12))))]\n        fn call_method_positional(\n            self,\n            object: Borrowed<'_, 'py, PyAny>,\n            method_name: Borrowed<'_, 'py, crate::types::PyString>,\n            token: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            self.into_pyobject_or_pyerr(object.py())?.call_method_positional(object, method_name, token)\n        }\n    }\n\n    impl<'a, 'py, $($T),+> crate::call::private::Sealed for &'a ($($T,)+) where $(&'a $T: IntoPyObject<'py>,)+ {}\n    impl<'a, 'py, $($T),+> crate::call::PyCallArgs<'py> for &'a ($($T,)+)\n    where\n        $(&'a $T: IntoPyObject<'py>,)+\n    {\n        #[cfg(all(Py_3_9, not(any(PyPy, GraalPy, Py_LIMITED_API))))]\n        fn call(\n            self,\n            function: Borrowed<'_, 'py, PyAny>,\n            kwargs: Borrowed<'_, '_, crate::types::PyDict>,\n            _: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            let py = function.py();\n            // We need this to drop the arguments correctly.\n            let args_bound = [$(self.$n.into_bound_py_any(py)?,)*];\n            // Prepend one null argument for `PY_VECTORCALL_ARGUMENTS_OFFSET`.\n            let mut args = [std::ptr::null_mut(), $(args_bound[$n].as_ptr()),*];\n            unsafe {\n                ffi::PyObject_VectorcallDict(\n                    function.as_ptr(),\n                    args.as_mut_ptr().add(1),\n                    $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET,\n                    kwargs.as_ptr(),\n                )\n                .assume_owned_or_err(py)\n            }\n        }\n\n        #[cfg(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12)))]\n        fn call_positional(\n            self,\n            function: Borrowed<'_, 'py, PyAny>,\n            _: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            let py = function.py();\n            // We need this to drop the arguments correctly.\n            let args_bound = [$(self.$n.into_bound_py_any(py)?,)*];\n\n            #[cfg(not(Py_LIMITED_API))]\n            if $length == 1 {\n                return unsafe {\n                    ffi::PyObject_CallOneArg(\n                       function.as_ptr(),\n                       args_bound[0].as_ptr()\n                    )\n                    .assume_owned_or_err(py)\n                };\n            }\n\n            // Prepend one null argument for `PY_VECTORCALL_ARGUMENTS_OFFSET`.\n            let mut args = [std::ptr::null_mut(), $(args_bound[$n].as_ptr()),*];\n            unsafe {\n                ffi::PyObject_Vectorcall(\n                    function.as_ptr(),\n                    args.as_mut_ptr().add(1),\n                    $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET,\n                    std::ptr::null_mut(),\n                )\n                .assume_owned_or_err(py)\n            }\n        }\n\n        #[cfg(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12)))]\n        fn call_method_positional(\n            self,\n            object: Borrowed<'_, 'py, PyAny>,\n            method_name: Borrowed<'_, 'py, crate::types::PyString>,\n            _: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            let py = object.py();\n            // We need this to drop the arguments correctly.\n            let args_bound = [$(self.$n.into_bound_py_any(py)?,)*];\n\n            #[cfg(not(Py_LIMITED_API))]\n            if $length == 1 {\n                return unsafe {\n                    ffi::PyObject_CallMethodOneArg(\n                            object.as_ptr(),\n                            method_name.as_ptr(),\n                            args_bound[0].as_ptr(),\n                    )\n                    .assume_owned_or_err(py)\n                };\n            }\n\n            let mut args = [object.as_ptr(), $(args_bound[$n].as_ptr()),*];\n            unsafe {\n                ffi::PyObject_VectorcallMethod(\n                    method_name.as_ptr(),\n                    args.as_mut_ptr(),\n                    // +1 for the receiver.\n                    1 + $length + ffi::PY_VECTORCALL_ARGUMENTS_OFFSET,\n                    std::ptr::null_mut(),\n                )\n                .assume_owned_or_err(py)\n            }\n        }\n\n        #[cfg(not(all(Py_3_9, not(any(PyPy, GraalPy, Py_LIMITED_API)))))]\n        fn call(\n            self,\n            function: Borrowed<'_, 'py, PyAny>,\n            kwargs: Borrowed<'_, 'py, crate::types::PyDict>,\n            token: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            self.into_pyobject_or_pyerr(function.py())?.call(function, kwargs, token)\n        }\n\n        #[cfg(not(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12))))]\n        fn call_positional(\n            self,\n            function: Borrowed<'_, 'py, PyAny>,\n            token: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            self.into_pyobject_or_pyerr(function.py())?.call_positional(function, token)\n        }\n\n        #[cfg(not(all(not(any(PyPy, GraalPy)), any(all(Py_3_9, not(Py_LIMITED_API)), Py_3_12))))]\n        fn call_method_positional(\n            self,\n            object: Borrowed<'_, 'py, PyAny>,\n            method_name: Borrowed<'_, 'py, crate::types::PyString>,\n            token: crate::call::private::Token,\n        ) -> PyResult<Bound<'py, PyAny>> {\n            self.into_pyobject_or_pyerr(object.py())?.call_method_positional(object, method_name, token)\n        }\n    }\n\n    impl<'a, 'py, $($T: FromPyObject<'a, 'py>),+> FromPyObject<'a, 'py> for ($($T,)+) {\n        type Error = PyErr;\n\n        #[cfg(feature = \"experimental-inspect\")]\n        const INPUT_TYPE: PyStaticExpr = type_hint_subscript!(\n            PyTuple::TYPE_HINT,\n            $($T::INPUT_TYPE ),+\n        );\n\n        fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error>\n        {\n            let t = obj.cast::<PyTuple>()?;\n            if t.len() == $length {\n                #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))]\n                return Ok(($(t.get_borrowed_item($n)?.extract::<$T>().map_err(Into::into)?,)+));\n\n                #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n                unsafe {return Ok(($(t.get_borrowed_item_unchecked($n).extract::<$T>().map_err(Into::into)?,)+));}\n            } else {\n                Err(wrong_tuple_length(t, $length))\n            }\n        }\n    }\n});\n\nfn array_into_tuple<'py, const N: usize>(\n    py: Python<'py>,\n    array: [Bound<'py, PyAny>; N],\n) -> Bound<'py, PyTuple> {\n    unsafe {\n        let ptr = ffi::PyTuple_New(N.try_into().expect(\"0 < N <= 12\"));\n        let tup = ptr.assume_owned(py).cast_into_unchecked();\n        for (index, obj) in array.into_iter().enumerate() {\n            #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n            ffi::PyTuple_SET_ITEM(ptr, index as ffi::Py_ssize_t, obj.into_ptr());\n            #[cfg(any(Py_LIMITED_API, PyPy, GraalPy))]\n            ffi::PyTuple_SetItem(ptr, index as ffi::Py_ssize_t, obj.into_ptr());\n        }\n        tup\n    }\n}\n\ntuple_conversion!(1, (ref0, 0, T0));\ntuple_conversion!(2, (ref0, 0, T0), (ref1, 1, T1));\ntuple_conversion!(3, (ref0, 0, T0), (ref1, 1, T1), (ref2, 2, T2));\ntuple_conversion!(\n    4,\n    (ref0, 0, T0),\n    (ref1, 1, T1),\n    (ref2, 2, T2),\n    (ref3, 3, T3)\n);\ntuple_conversion!(\n    5,\n    (ref0, 0, T0),\n    (ref1, 1, T1),\n    (ref2, 2, T2),\n    (ref3, 3, T3),\n    (ref4, 4, T4)\n);\ntuple_conversion!(\n    6,\n    (ref0, 0, T0),\n    (ref1, 1, T1),\n    (ref2, 2, T2),\n    (ref3, 3, T3),\n    (ref4, 4, T4),\n    (ref5, 5, T5)\n);\ntuple_conversion!(\n    7,\n    (ref0, 0, T0),\n    (ref1, 1, T1),\n    (ref2, 2, T2),\n    (ref3, 3, T3),\n    (ref4, 4, T4),\n    (ref5, 5, T5),\n    (ref6, 6, T6)\n);\ntuple_conversion!(\n    8,\n    (ref0, 0, T0),\n    (ref1, 1, T1),\n    (ref2, 2, T2),\n    (ref3, 3, T3),\n    (ref4, 4, T4),\n    (ref5, 5, T5),\n    (ref6, 6, T6),\n    (ref7, 7, T7)\n);\ntuple_conversion!(\n    9,\n    (ref0, 0, T0),\n    (ref1, 1, T1),\n    (ref2, 2, T2),\n    (ref3, 3, T3),\n    (ref4, 4, T4),\n    (ref5, 5, T5),\n    (ref6, 6, T6),\n    (ref7, 7, T7),\n    (ref8, 8, T8)\n);\ntuple_conversion!(\n    10,\n    (ref0, 0, T0),\n    (ref1, 1, T1),\n    (ref2, 2, T2),\n    (ref3, 3, T3),\n    (ref4, 4, T4),\n    (ref5, 5, T5),\n    (ref6, 6, T6),\n    (ref7, 7, T7),\n    (ref8, 8, T8),\n    (ref9, 9, T9)\n);\ntuple_conversion!(\n    11,\n    (ref0, 0, T0),\n    (ref1, 1, T1),\n    (ref2, 2, T2),\n    (ref3, 3, T3),\n    (ref4, 4, T4),\n    (ref5, 5, T5),\n    (ref6, 6, T6),\n    (ref7, 7, T7),\n    (ref8, 8, T8),\n    (ref9, 9, T9),\n    (ref10, 10, T10)\n);\n\ntuple_conversion!(\n    12,\n    (ref0, 0, T0),\n    (ref1, 1, T1),\n    (ref2, 2, T2),\n    (ref3, 3, T3),\n    (ref4, 4, T4),\n    (ref5, 5, T5),\n    (ref6, 6, T6),\n    (ref7, 7, T7),\n    (ref8, 8, T8),\n    (ref9, 9, T9),\n    (ref10, 10, T10),\n    (ref11, 11, T11)\n);\n\n#[cfg(test)]\nmod tests {\n    use crate::types::{any::PyAnyMethods, tuple::PyTupleMethods, PyList, PyTuple};\n    use crate::{IntoPyObject, Python};\n    use std::collections::HashSet;\n    #[cfg(feature = \"nightly\")]\n    use std::num::NonZero;\n    use std::ops::Range;\n    #[test]\n    fn test_new() {\n        Python::attach(|py| {\n            let ob = PyTuple::new(py, [1, 2, 3]).unwrap();\n            assert_eq!(3, ob.len());\n            let ob = ob.as_any();\n            assert_eq!((1, 2, 3), ob.extract().unwrap());\n\n            let mut map = HashSet::new();\n            map.insert(1);\n            map.insert(2);\n            PyTuple::new(py, map).unwrap();\n        });\n    }\n\n    #[test]\n    fn test_len() {\n        Python::attach(|py| {\n            let ob = (1, 2, 3).into_pyobject(py).unwrap();\n            let tuple = ob.cast::<PyTuple>().unwrap();\n            assert_eq!(3, tuple.len());\n            assert!(!tuple.is_empty());\n            let ob = tuple.as_any();\n            assert_eq!((1, 2, 3), ob.extract().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_empty() {\n        Python::attach(|py| {\n            let tuple = PyTuple::empty(py);\n            assert!(tuple.is_empty());\n            assert_eq!(0, tuple.len());\n        });\n    }\n\n    #[test]\n    fn test_slice() {\n        Python::attach(|py| {\n            let tup = PyTuple::new(py, [2, 3, 5, 7]).unwrap();\n            let slice = tup.get_slice(1, 3);\n            assert_eq!(2, slice.len());\n            let slice = tup.get_slice(1, 7);\n            assert_eq!(3, slice.len());\n        });\n    }\n\n    #[test]\n    fn test_iter() {\n        Python::attach(|py| {\n            let ob = (1, 2, 3).into_pyobject(py).unwrap();\n            let tuple = ob.cast::<PyTuple>().unwrap();\n            assert_eq!(3, tuple.len());\n            let mut iter = tuple.iter();\n\n            assert_eq!(iter.size_hint(), (3, Some(3)));\n\n            assert_eq!(1_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());\n            assert_eq!(iter.size_hint(), (2, Some(2)));\n\n            assert_eq!(2_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());\n            assert_eq!(iter.size_hint(), (1, Some(1)));\n\n            assert_eq!(3_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());\n            assert_eq!(iter.size_hint(), (0, Some(0)));\n\n            assert!(iter.next().is_none());\n            assert!(iter.next().is_none());\n        });\n    }\n\n    #[test]\n    fn test_iter_rev() {\n        Python::attach(|py| {\n            let ob = (1, 2, 3).into_pyobject(py).unwrap();\n            let tuple = ob.cast::<PyTuple>().unwrap();\n            assert_eq!(3, tuple.len());\n            let mut iter = tuple.iter().rev();\n\n            assert_eq!(iter.size_hint(), (3, Some(3)));\n\n            assert_eq!(3_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());\n            assert_eq!(iter.size_hint(), (2, Some(2)));\n\n            assert_eq!(2_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());\n            assert_eq!(iter.size_hint(), (1, Some(1)));\n\n            assert_eq!(1_i32, iter.next().unwrap().extract::<'_, i32>().unwrap());\n            assert_eq!(iter.size_hint(), (0, Some(0)));\n\n            assert!(iter.next().is_none());\n            assert!(iter.next().is_none());\n        });\n    }\n\n    #[test]\n    fn test_bound_iter() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, [1, 2, 3]).unwrap();\n            assert_eq!(3, tuple.len());\n            let mut iter = tuple.iter();\n\n            assert_eq!(iter.size_hint(), (3, Some(3)));\n\n            assert_eq!(1, iter.next().unwrap().extract::<i32>().unwrap());\n            assert_eq!(iter.size_hint(), (2, Some(2)));\n\n            assert_eq!(2, iter.next().unwrap().extract::<i32>().unwrap());\n            assert_eq!(iter.size_hint(), (1, Some(1)));\n\n            assert_eq!(3, iter.next().unwrap().extract::<i32>().unwrap());\n            assert_eq!(iter.size_hint(), (0, Some(0)));\n\n            assert!(iter.next().is_none());\n            assert!(iter.next().is_none());\n        });\n    }\n\n    #[test]\n    fn test_bound_iter_rev() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, [1, 2, 3]).unwrap();\n            assert_eq!(3, tuple.len());\n            let mut iter = tuple.iter().rev();\n\n            assert_eq!(iter.size_hint(), (3, Some(3)));\n\n            assert_eq!(3, iter.next().unwrap().extract::<i32>().unwrap());\n            assert_eq!(iter.size_hint(), (2, Some(2)));\n\n            assert_eq!(2, iter.next().unwrap().extract::<i32>().unwrap());\n            assert_eq!(iter.size_hint(), (1, Some(1)));\n\n            assert_eq!(1, iter.next().unwrap().extract::<i32>().unwrap());\n            assert_eq!(iter.size_hint(), (0, Some(0)));\n\n            assert!(iter.next().is_none());\n            assert!(iter.next().is_none());\n        });\n    }\n\n    #[test]\n    fn test_into_iter() {\n        Python::attach(|py| {\n            let ob = (1, 2, 3).into_pyobject(py).unwrap();\n            let tuple = ob.cast::<PyTuple>().unwrap();\n            assert_eq!(3, tuple.len());\n\n            for (i, item) in tuple.iter().enumerate() {\n                assert_eq!(i + 1, item.extract::<'_, usize>().unwrap());\n            }\n        });\n    }\n\n    #[test]\n    fn test_into_iter_bound() {\n        Python::attach(|py| {\n            let tuple = (1, 2, 3).into_pyobject(py).unwrap();\n            assert_eq!(3, tuple.len());\n\n            let mut items = vec![];\n            for item in tuple {\n                items.push(item.extract::<usize>().unwrap());\n            }\n            assert_eq!(items, vec![1, 2, 3]);\n        });\n    }\n\n    #[test]\n    #[cfg(not(any(Py_LIMITED_API, GraalPy)))]\n    fn test_as_slice() {\n        Python::attach(|py| {\n            let ob = (1, 2, 3).into_pyobject(py).unwrap();\n            let tuple = ob.cast::<PyTuple>().unwrap();\n\n            let slice = tuple.as_slice();\n            assert_eq!(3, slice.len());\n            assert_eq!(1_i32, slice[0].extract::<'_, i32>().unwrap());\n            assert_eq!(2_i32, slice[1].extract::<'_, i32>().unwrap());\n            assert_eq!(3_i32, slice[2].extract::<'_, i32>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_tuple_lengths_up_to_12() {\n        Python::attach(|py| {\n            let t0 = (0,).into_pyobject(py).unwrap();\n            let t1 = (0, 1).into_pyobject(py).unwrap();\n            let t2 = (0, 1, 2).into_pyobject(py).unwrap();\n            let t3 = (0, 1, 2, 3).into_pyobject(py).unwrap();\n            let t4 = (0, 1, 2, 3, 4).into_pyobject(py).unwrap();\n            let t5 = (0, 1, 2, 3, 4, 5).into_pyobject(py).unwrap();\n            let t6 = (0, 1, 2, 3, 4, 5, 6).into_pyobject(py).unwrap();\n            let t7 = (0, 1, 2, 3, 4, 5, 6, 7).into_pyobject(py).unwrap();\n            let t8 = (0, 1, 2, 3, 4, 5, 6, 7, 8).into_pyobject(py).unwrap();\n            let t9 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9).into_pyobject(py).unwrap();\n            let t10 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)\n                .into_pyobject(py)\n                .unwrap();\n            let t11 = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11)\n                .into_pyobject(py)\n                .unwrap();\n\n            assert_eq!(t0.extract::<(i32,)>().unwrap(), (0,));\n            assert_eq!(t1.extract::<(i32, i32)>().unwrap(), (0, 1,));\n            assert_eq!(t2.extract::<(i32, i32, i32)>().unwrap(), (0, 1, 2,));\n            assert_eq!(\n                t3.extract::<(i32, i32, i32, i32,)>().unwrap(),\n                (0, 1, 2, 3,)\n            );\n            assert_eq!(\n                t4.extract::<(i32, i32, i32, i32, i32,)>().unwrap(),\n                (0, 1, 2, 3, 4,)\n            );\n            assert_eq!(\n                t5.extract::<(i32, i32, i32, i32, i32, i32,)>().unwrap(),\n                (0, 1, 2, 3, 4, 5,)\n            );\n            assert_eq!(\n                t6.extract::<(i32, i32, i32, i32, i32, i32, i32,)>()\n                    .unwrap(),\n                (0, 1, 2, 3, 4, 5, 6,)\n            );\n            assert_eq!(\n                t7.extract::<(i32, i32, i32, i32, i32, i32, i32, i32,)>()\n                    .unwrap(),\n                (0, 1, 2, 3, 4, 5, 6, 7,)\n            );\n            assert_eq!(\n                t8.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32,)>()\n                    .unwrap(),\n                (0, 1, 2, 3, 4, 5, 6, 7, 8,)\n            );\n            assert_eq!(\n                t9.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,)>()\n                    .unwrap(),\n                (0, 1, 2, 3, 4, 5, 6, 7, 8, 9,)\n            );\n            assert_eq!(\n                t10.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,)>()\n                    .unwrap(),\n                (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,)\n            );\n            assert_eq!(\n                t11.extract::<(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32,)>()\n                    .unwrap(),\n                (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,)\n            );\n        })\n    }\n\n    #[test]\n    fn test_tuple_get_item_invalid_index() {\n        Python::attach(|py| {\n            let ob = (1, 2, 3).into_pyobject(py).unwrap();\n            let tuple = ob.cast::<PyTuple>().unwrap();\n            let obj = tuple.get_item(5);\n            assert!(obj.is_err());\n            assert_eq!(\n                obj.unwrap_err().to_string(),\n                \"IndexError: tuple index out of range\"\n            );\n        });\n    }\n\n    #[test]\n    fn test_tuple_get_item_sanity() {\n        Python::attach(|py| {\n            let ob = (1, 2, 3).into_pyobject(py).unwrap();\n            let tuple = ob.cast::<PyTuple>().unwrap();\n            let obj = tuple.get_item(0);\n            assert_eq!(obj.unwrap().extract::<i32>().unwrap(), 1);\n        });\n    }\n\n    #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n    #[test]\n    fn test_tuple_get_item_unchecked_sanity() {\n        Python::attach(|py| {\n            let ob = (1, 2, 3).into_pyobject(py).unwrap();\n            let tuple = ob.cast::<PyTuple>().unwrap();\n            let obj = unsafe { tuple.get_item_unchecked(0) };\n            assert_eq!(obj.extract::<i32>().unwrap(), 1);\n        });\n    }\n\n    #[test]\n    fn test_tuple_contains() {\n        Python::attach(|py| {\n            let ob = (1, 1, 2, 3, 5, 8).into_pyobject(py).unwrap();\n            let tuple = ob.cast::<PyTuple>().unwrap();\n            assert_eq!(6, tuple.len());\n\n            let bad_needle = 7i32.into_pyobject(py).unwrap();\n            assert!(!tuple.contains(&bad_needle).unwrap());\n\n            let good_needle = 8i32.into_pyobject(py).unwrap();\n            assert!(tuple.contains(&good_needle).unwrap());\n\n            let type_coerced_needle = 8f32.into_pyobject(py).unwrap();\n            assert!(tuple.contains(&type_coerced_needle).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_tuple_index() {\n        Python::attach(|py| {\n            let ob = (1, 1, 2, 3, 5, 8).into_pyobject(py).unwrap();\n            let tuple = ob.cast::<PyTuple>().unwrap();\n            assert_eq!(0, tuple.index(1i32).unwrap());\n            assert_eq!(2, tuple.index(2i32).unwrap());\n            assert_eq!(3, tuple.index(3i32).unwrap());\n            assert_eq!(4, tuple.index(5i32).unwrap());\n            assert_eq!(5, tuple.index(8i32).unwrap());\n            assert!(tuple.index(42i32).is_err());\n        });\n    }\n\n    // An iterator that lies about its `ExactSizeIterator` implementation.\n    // See https://github.com/PyO3/pyo3/issues/2118\n    struct FaultyIter(Range<usize>, usize);\n\n    impl Iterator for FaultyIter {\n        type Item = usize;\n\n        fn next(&mut self) -> Option<Self::Item> {\n            self.0.next()\n        }\n    }\n\n    impl ExactSizeIterator for FaultyIter {\n        fn len(&self) -> usize {\n            self.1\n        }\n    }\n\n    #[test]\n    #[should_panic(\n        expected = \"Attempted to create PyTuple but `elements` was larger than reported by its `ExactSizeIterator` implementation.\"\n    )]\n    fn too_long_iterator() {\n        Python::attach(|py| {\n            let iter = FaultyIter(0..usize::MAX, 73);\n            let _tuple = PyTuple::new(py, iter);\n        })\n    }\n\n    #[test]\n    #[should_panic(\n        expected = \"Attempted to create PyTuple but `elements` was smaller than reported by its `ExactSizeIterator` implementation.\"\n    )]\n    fn too_short_iterator() {\n        Python::attach(|py| {\n            let iter = FaultyIter(0..35, 73);\n            let _tuple = PyTuple::new(py, iter);\n        })\n    }\n\n    #[test]\n    #[should_panic(\n        expected = \"out of range integral type conversion attempted on `elements.len()`\"\n    )]\n    fn overflowing_size() {\n        Python::attach(|py| {\n            let iter = FaultyIter(0..0, usize::MAX);\n\n            let _tuple = PyTuple::new(py, iter);\n        })\n    }\n\n    #[test]\n    #[cfg(panic = \"unwind\")]\n    fn bad_intopyobject_doesnt_cause_leaks() {\n        use crate::types::PyInt;\n        use std::convert::Infallible;\n        use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};\n\n        static NEEDS_DESTRUCTING_COUNT: AtomicUsize = AtomicUsize::new(0);\n\n        struct Bad(usize);\n\n        impl Drop for Bad {\n            fn drop(&mut self) {\n                NEEDS_DESTRUCTING_COUNT.fetch_sub(1, SeqCst);\n            }\n        }\n\n        impl<'py> IntoPyObject<'py> for Bad {\n            type Target = PyInt;\n            type Output = crate::Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                // This panic should not lead to a memory leak\n                assert_ne!(self.0, 42);\n                self.0.into_pyobject(py)\n            }\n        }\n\n        struct FaultyIter(Range<usize>, usize);\n\n        impl Iterator for FaultyIter {\n            type Item = Bad;\n\n            fn next(&mut self) -> Option<Self::Item> {\n                self.0.next().map(|i| {\n                    NEEDS_DESTRUCTING_COUNT.fetch_add(1, SeqCst);\n                    Bad(i)\n                })\n            }\n        }\n\n        impl ExactSizeIterator for FaultyIter {\n            fn len(&self) -> usize {\n                self.1\n            }\n        }\n\n        Python::attach(|py| {\n            std::panic::catch_unwind(|| {\n                let iter = FaultyIter(0..50, 50);\n                let _tuple = PyTuple::new(py, iter);\n            })\n            .unwrap_err();\n        });\n\n        assert_eq!(\n            NEEDS_DESTRUCTING_COUNT.load(SeqCst),\n            0,\n            \"Some destructors did not run\"\n        );\n    }\n\n    #[test]\n    #[cfg(panic = \"unwind\")]\n    fn bad_intopyobject_doesnt_cause_leaks_2() {\n        use crate::types::PyInt;\n        use std::convert::Infallible;\n        use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};\n\n        static NEEDS_DESTRUCTING_COUNT: AtomicUsize = AtomicUsize::new(0);\n\n        struct Bad(usize);\n\n        impl Drop for Bad {\n            fn drop(&mut self) {\n                NEEDS_DESTRUCTING_COUNT.fetch_sub(1, SeqCst);\n            }\n        }\n\n        impl<'py> IntoPyObject<'py> for &Bad {\n            type Target = PyInt;\n            type Output = crate::Bound<'py, Self::Target>;\n            type Error = Infallible;\n\n            fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {\n                // This panic should not lead to a memory leak\n                assert_ne!(self.0, 3);\n                self.0.into_pyobject(py)\n            }\n        }\n\n        let s = (Bad(1), Bad(2), Bad(3), Bad(4));\n        NEEDS_DESTRUCTING_COUNT.store(4, SeqCst);\n        Python::attach(|py| {\n            std::panic::catch_unwind(|| {\n                let _tuple = (&s).into_pyobject(py).unwrap();\n            })\n            .unwrap_err();\n        });\n        drop(s);\n\n        assert_eq!(\n            NEEDS_DESTRUCTING_COUNT.load(SeqCst),\n            0,\n            \"Some destructors did not run\"\n        );\n    }\n\n    #[test]\n    fn test_tuple_to_list() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap();\n            let list = tuple.to_list();\n            let list_expected = PyList::new(py, vec![1, 2, 3]).unwrap();\n            assert!(list.eq(list_expected).unwrap());\n        })\n    }\n\n    #[test]\n    fn test_tuple_as_sequence() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap();\n            let sequence = tuple.as_sequence();\n            assert!(tuple.get_item(0).unwrap().eq(1).unwrap());\n            assert!(sequence.get_item(0).unwrap().eq(1).unwrap());\n\n            assert_eq!(tuple.len(), 3);\n            assert_eq!(sequence.len().unwrap(), 3);\n        })\n    }\n\n    #[test]\n    fn test_tuple_into_sequence() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap();\n            let sequence = tuple.into_sequence();\n            assert!(sequence.get_item(0).unwrap().eq(1).unwrap());\n            assert_eq!(sequence.len().unwrap(), 3);\n        })\n    }\n\n    #[test]\n    fn test_bound_tuple_get_item() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, vec![1, 2, 3, 4]).unwrap();\n\n            assert_eq!(tuple.len(), 4);\n            assert_eq!(tuple.get_item(0).unwrap().extract::<i32>().unwrap(), 1);\n            assert_eq!(\n                tuple\n                    .get_borrowed_item(1)\n                    .unwrap()\n                    .extract::<i32>()\n                    .unwrap(),\n                2\n            );\n            #[cfg(not(any(Py_LIMITED_API, PyPy, GraalPy)))]\n            {\n                assert_eq!(\n                    unsafe { tuple.get_item_unchecked(2) }\n                        .extract::<i32>()\n                        .unwrap(),\n                    3\n                );\n                assert_eq!(\n                    unsafe { tuple.get_borrowed_item_unchecked(3) }\n                        .extract::<i32>()\n                        .unwrap(),\n                    4\n                );\n            }\n        })\n    }\n\n    #[test]\n    fn test_bound_tuple_nth() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, vec![1, 2, 3, 4]).unwrap();\n            let mut iter = tuple.iter();\n            assert_eq!(iter.nth(1).unwrap().extract::<i32>().unwrap(), 2);\n            assert_eq!(iter.nth(1).unwrap().extract::<i32>().unwrap(), 4);\n            assert!(iter.nth(1).is_none());\n\n            let tuple = PyTuple::new(py, Vec::<i32>::new()).unwrap();\n            let mut iter = tuple.iter();\n            iter.next();\n            assert!(iter.nth(1).is_none());\n\n            let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap();\n            let mut iter = tuple.iter();\n            assert!(iter.nth(10).is_none());\n\n            let tuple = PyTuple::new(py, vec![6, 7, 8, 9, 10]).unwrap();\n            let mut iter = tuple.iter();\n            assert_eq!(iter.next().unwrap().extract::<i32>().unwrap(), 6);\n            assert_eq!(iter.nth(2).unwrap().extract::<i32>().unwrap(), 9);\n            assert_eq!(iter.next().unwrap().extract::<i32>().unwrap(), 10);\n\n            let mut iter = tuple.iter();\n            assert_eq!(iter.nth_back(1).unwrap().extract::<i32>().unwrap(), 9);\n            assert_eq!(iter.nth(2).unwrap().extract::<i32>().unwrap(), 8);\n            assert!(iter.next().is_none());\n        });\n    }\n\n    #[test]\n    fn test_bound_tuple_nth_back() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, vec![1, 2, 3, 4, 5]).unwrap();\n            let mut iter = tuple.iter();\n            assert_eq!(iter.nth_back(0).unwrap().extract::<i32>().unwrap(), 5);\n            assert_eq!(iter.nth_back(1).unwrap().extract::<i32>().unwrap(), 3);\n            assert!(iter.nth_back(2).is_none());\n\n            let tuple = PyTuple::new(py, Vec::<i32>::new()).unwrap();\n            let mut iter = tuple.iter();\n            assert!(iter.nth_back(0).is_none());\n            assert!(iter.nth_back(1).is_none());\n\n            let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap();\n            let mut iter = tuple.iter();\n            assert!(iter.nth_back(5).is_none());\n\n            let tuple = PyTuple::new(py, vec![1, 2, 3, 4, 5]).unwrap();\n            let mut iter = tuple.iter();\n            iter.next_back(); // Consume the last element\n            assert_eq!(iter.nth_back(1).unwrap().extract::<i32>().unwrap(), 3);\n            assert_eq!(iter.next_back().unwrap().extract::<i32>().unwrap(), 2);\n            assert_eq!(iter.nth_back(0).unwrap().extract::<i32>().unwrap(), 1);\n\n            let tuple = PyTuple::new(py, vec![1, 2, 3, 4, 5]).unwrap();\n            let mut iter = tuple.iter();\n            assert_eq!(iter.nth_back(1).unwrap().extract::<i32>().unwrap(), 4);\n            assert_eq!(iter.nth_back(2).unwrap().extract::<i32>().unwrap(), 1);\n\n            let mut iter2 = tuple.iter();\n            iter2.next_back();\n            assert_eq!(iter2.nth_back(1).unwrap().extract::<i32>().unwrap(), 3);\n            assert_eq!(iter2.next_back().unwrap().extract::<i32>().unwrap(), 2);\n\n            let mut iter3 = tuple.iter();\n            iter3.nth(1);\n            assert_eq!(iter3.nth_back(2).unwrap().extract::<i32>().unwrap(), 3);\n            assert!(iter3.nth_back(0).is_none());\n        });\n    }\n\n    #[cfg(feature = \"nightly\")]\n    #[test]\n    fn test_bound_tuple_advance_by() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, vec![1, 2, 3, 4, 5]).unwrap();\n            let mut iter = tuple.iter();\n\n            assert_eq!(iter.advance_by(2), Ok(()));\n            assert_eq!(iter.next().unwrap().extract::<i32>().unwrap(), 3);\n            assert_eq!(iter.advance_by(0), Ok(()));\n            assert_eq!(iter.advance_by(100), Err(NonZero::new(98).unwrap()));\n            assert!(iter.next().is_none());\n\n            let mut iter2 = tuple.iter();\n            assert_eq!(iter2.advance_by(6), Err(NonZero::new(1).unwrap()));\n\n            let mut iter3 = tuple.iter();\n            assert_eq!(iter3.advance_by(5), Ok(()));\n\n            let mut iter4 = tuple.iter();\n            assert_eq!(iter4.advance_by(0), Ok(()));\n            assert_eq!(iter4.next().unwrap().extract::<i32>().unwrap(), 1);\n        })\n    }\n\n    #[cfg(feature = \"nightly\")]\n    #[test]\n    fn test_bound_tuple_advance_back_by() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, vec![1, 2, 3, 4, 5]).unwrap();\n            let mut iter = tuple.iter();\n\n            assert_eq!(iter.advance_back_by(2), Ok(()));\n            assert_eq!(iter.next_back().unwrap().extract::<i32>().unwrap(), 3);\n            assert_eq!(iter.advance_back_by(0), Ok(()));\n            assert_eq!(iter.advance_back_by(100), Err(NonZero::new(98).unwrap()));\n            assert!(iter.next_back().is_none());\n\n            let mut iter2 = tuple.iter();\n            assert_eq!(iter2.advance_back_by(6), Err(NonZero::new(1).unwrap()));\n\n            let mut iter3 = tuple.iter();\n            assert_eq!(iter3.advance_back_by(5), Ok(()));\n\n            let mut iter4 = tuple.iter();\n            assert_eq!(iter4.advance_back_by(0), Ok(()));\n            assert_eq!(iter4.next_back().unwrap().extract::<i32>().unwrap(), 5);\n        })\n    }\n\n    #[test]\n    fn test_iter_last() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap();\n            let last = tuple.iter().last();\n            assert_eq!(last.unwrap().extract::<i32>().unwrap(), 3);\n        })\n    }\n\n    #[test]\n    fn test_iter_count() {\n        Python::attach(|py| {\n            let tuple = PyTuple::new(py, vec![1, 2, 3]).unwrap();\n            assert_eq!(tuple.iter().count(), 3);\n        })\n    }\n}\n"
  },
  {
    "path": "src/types/typeobject.rs",
    "content": "use crate::err::{self, PyResult};\nuse crate::instance::Borrowed;\n#[cfg(not(Py_3_13))]\nuse crate::pybacked::PyBackedStr;\n#[cfg(any(Py_LIMITED_API, PyPy, not(Py_3_13)))]\nuse crate::types::any::PyAnyMethods;\nuse crate::types::PyTuple;\nuse crate::{ffi, Bound, PyAny, PyTypeInfo, Python};\n\nuse super::PyString;\n\n/// Represents a reference to a Python `type` object.\n///\n/// Values of this type are accessed via PyO3's smart pointers, e.g. as\n/// [`Py<PyType>`][crate::Py] or [`Bound<'py, PyType>`][Bound].\n///\n/// For APIs available on `type` objects, see the [`PyTypeMethods`] trait which is implemented for\n/// [`Bound<'py, PyType>`][Bound].\n#[repr(transparent)]\npub struct PyType(PyAny);\n\npyobject_native_type_core!(PyType, pyobject_native_static_type_object!(ffi::PyType_Type), \"builtins\", \"type\", #checkfunction=ffi::PyType_Check);\n\nimpl PyType {\n    /// Creates a new type object.\n    #[inline]\n    pub fn new<T: PyTypeInfo>(py: Python<'_>) -> Bound<'_, PyType> {\n        T::type_object(py)\n    }\n\n    /// Converts the given FFI pointer into `Bound<PyType>`, to use in safe code.\n    ///\n    /// The function creates a new reference from the given pointer, and returns\n    /// it as a `Bound<PyType>`.\n    ///\n    /// # Safety\n    /// - The pointer must be a valid non-null reference to a `PyTypeObject`\n    #[inline]\n    pub unsafe fn from_borrowed_type_ptr(\n        py: Python<'_>,\n        p: *mut ffi::PyTypeObject,\n    ) -> Bound<'_, PyType> {\n        unsafe {\n            Borrowed::from_ptr_unchecked(py, p.cast())\n                .cast_unchecked()\n                .to_owned()\n        }\n    }\n}\n\n/// Implementation of functionality for [`PyType`].\n///\n/// These methods are defined for the `Bound<'py, PyType>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyType\")]\npub trait PyTypeMethods<'py>: crate::sealed::Sealed {\n    /// Retrieves the underlying FFI pointer associated with this Python object.\n    fn as_type_ptr(&self) -> *mut ffi::PyTypeObject;\n\n    /// Gets the name of the `PyType`. Equivalent to `self.__name__` in Python.\n    fn name(&self) -> PyResult<Bound<'py, PyString>>;\n\n    /// Gets the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name) of the `PyType`.\n    /// Equivalent to `self.__qualname__` in Python.\n    fn qualname(&self) -> PyResult<Bound<'py, PyString>>;\n\n    /// Gets the name of the module defining the `PyType`.\n    fn module(&self) -> PyResult<Bound<'py, PyString>>;\n\n    /// Gets the [fully qualified name](https://peps.python.org/pep-0737/#add-pytype-getfullyqualifiedname-function) of the `PyType`.\n    fn fully_qualified_name(&self) -> PyResult<Bound<'py, PyString>>;\n\n    /// Checks whether `self` is a subclass of `other`.\n    ///\n    /// Equivalent to the Python expression `issubclass(self, other)`.\n    fn is_subclass(&self, other: &Bound<'_, PyAny>) -> PyResult<bool>;\n\n    /// Checks whether `self` is a subclass of type `T`.\n    ///\n    /// Equivalent to the Python expression `issubclass(self, T)`, if the type\n    /// `T` is known at compile time.\n    fn is_subclass_of<T>(&self) -> PyResult<bool>\n    where\n        T: PyTypeInfo;\n\n    /// Return the method resolution order for this type.\n    ///\n    /// Equivalent to the Python expression `self.__mro__`.\n    fn mro(&self) -> Bound<'py, PyTuple>;\n\n    /// Return Python bases\n    ///\n    /// Equivalent to the Python expression `self.__bases__`.\n    fn bases(&self) -> Bound<'py, PyTuple>;\n}\n\nimpl<'py> PyTypeMethods<'py> for Bound<'py, PyType> {\n    /// Retrieves the underlying FFI pointer associated with this Python object.\n    #[inline]\n    fn as_type_ptr(&self) -> *mut ffi::PyTypeObject {\n        self.as_ptr() as *mut ffi::PyTypeObject\n    }\n\n    /// Gets the name of the `PyType`.\n    fn name(&self) -> PyResult<Bound<'py, PyString>> {\n        #[cfg(not(Py_3_11))]\n        let name = self.getattr(intern!(self.py(), \"__name__\"))?.cast_into()?;\n\n        #[cfg(Py_3_11)]\n        let name = unsafe {\n            use crate::ffi_ptr_ext::FfiPtrExt;\n            ffi::PyType_GetName(self.as_type_ptr())\n                .assume_owned_or_err(self.py())?\n                // SAFETY: setting `__name__` from Python is required to be a `str`\n                .cast_into_unchecked()\n        };\n\n        Ok(name)\n    }\n\n    /// Gets the [qualified name](https://docs.python.org/3/glossary.html#term-qualified-name) of the `PyType`.\n    fn qualname(&self) -> PyResult<Bound<'py, PyString>> {\n        #[cfg(not(Py_3_11))]\n        let name = self\n            .getattr(intern!(self.py(), \"__qualname__\"))?\n            .cast_into()?;\n\n        #[cfg(Py_3_11)]\n        let name = unsafe {\n            use crate::ffi_ptr_ext::FfiPtrExt;\n            ffi::PyType_GetQualName(self.as_type_ptr())\n                .assume_owned_or_err(self.py())?\n                // SAFETY: setting `__qualname__` from Python is required to be a `str`\n                .cast_into_unchecked()\n        };\n\n        Ok(name)\n    }\n\n    /// Gets the name of the module defining the `PyType`.\n    fn module(&self) -> PyResult<Bound<'py, PyString>> {\n        #[cfg(not(Py_3_13))]\n        let name = self.getattr(intern!(self.py(), \"__module__\"))?;\n\n        #[cfg(Py_3_13)]\n        let name = unsafe {\n            use crate::ffi_ptr_ext::FfiPtrExt;\n            ffi::PyType_GetModuleName(self.as_type_ptr()).assume_owned_or_err(self.py())?\n        };\n\n        // `__module__` is never guaranteed to be a `str`\n        name.cast_into().map_err(Into::into)\n    }\n\n    /// Gets the [fully qualified name](https://docs.python.org/3/glossary.html#term-qualified-name) of the `PyType`.\n    fn fully_qualified_name(&self) -> PyResult<Bound<'py, PyString>> {\n        #[cfg(not(Py_3_13))]\n        let name = {\n            let module = self.getattr(intern!(self.py(), \"__module__\"))?;\n            let qualname = self.getattr(intern!(self.py(), \"__qualname__\"))?;\n\n            let module_str = module.extract::<PyBackedStr>()?;\n            if module_str == \"builtins\" || module_str == \"__main__\" {\n                qualname.cast_into()?\n            } else {\n                PyString::new(self.py(), &format!(\"{module}.{qualname}\"))\n            }\n        };\n\n        #[cfg(Py_3_13)]\n        let name = unsafe {\n            use crate::ffi_ptr_ext::FfiPtrExt;\n            ffi::PyType_GetFullyQualifiedName(self.as_type_ptr())\n                .assume_owned_or_err(self.py())?\n                .cast_into_unchecked()\n        };\n\n        Ok(name)\n    }\n\n    /// Checks whether `self` is a subclass of `other`.\n    ///\n    /// Equivalent to the Python expression `issubclass(self, other)`.\n    fn is_subclass(&self, other: &Bound<'_, PyAny>) -> PyResult<bool> {\n        let result = unsafe { ffi::PyObject_IsSubclass(self.as_ptr(), other.as_ptr()) };\n        err::error_on_minusone(self.py(), result)?;\n        Ok(result == 1)\n    }\n\n    /// Checks whether `self` is a subclass of type `T`.\n    ///\n    /// Equivalent to the Python expression `issubclass(self, T)`, if the type\n    /// `T` is known at compile time.\n    fn is_subclass_of<T>(&self) -> PyResult<bool>\n    where\n        T: PyTypeInfo,\n    {\n        self.is_subclass(&T::type_object(self.py()))\n    }\n\n    fn mro(&self) -> Bound<'py, PyTuple> {\n        #[cfg(any(Py_LIMITED_API, PyPy))]\n        let mro = self\n            .getattr(intern!(self.py(), \"__mro__\"))\n            .expect(\"Cannot get `__mro__` from object.\")\n            .extract()\n            .expect(\"Unexpected type in `__mro__` attribute.\");\n\n        #[cfg(not(any(Py_LIMITED_API, PyPy)))]\n        let mro = unsafe {\n            use crate::ffi_ptr_ext::FfiPtrExt;\n            (*self.as_type_ptr())\n                .tp_mro\n                .assume_borrowed(self.py())\n                .to_owned()\n                .cast_into_unchecked()\n        };\n\n        mro\n    }\n\n    fn bases(&self) -> Bound<'py, PyTuple> {\n        #[cfg(any(Py_LIMITED_API, PyPy))]\n        let bases = self\n            .getattr(intern!(self.py(), \"__bases__\"))\n            .expect(\"Cannot get `__bases__` from object.\")\n            .extract()\n            .expect(\"Unexpected type in `__bases__` attribute.\");\n\n        #[cfg(not(any(Py_LIMITED_API, PyPy)))]\n        let bases = unsafe {\n            use crate::ffi_ptr_ext::FfiPtrExt;\n            (*self.as_type_ptr())\n                .tp_bases\n                .assume_borrowed(self.py())\n                .to_owned()\n                .cast_into_unchecked()\n        };\n\n        bases\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::test_utils::generate_unique_module_name;\n    use crate::types::{PyAnyMethods, PyBool, PyInt, PyModule, PyTuple, PyType, PyTypeMethods};\n    use crate::PyAny;\n    use crate::Python;\n    use pyo3_ffi::c_str;\n\n    #[test]\n    fn test_type_is_subclass() {\n        Python::attach(|py| {\n            let bool_type = py.get_type::<PyBool>();\n            let long_type = py.get_type::<PyInt>();\n            assert!(bool_type.is_subclass(&long_type).unwrap());\n        });\n    }\n\n    #[test]\n    fn test_type_is_subclass_of() {\n        Python::attach(|py| {\n            assert!(py.get_type::<PyBool>().is_subclass_of::<PyInt>().unwrap());\n        });\n    }\n\n    #[test]\n    fn test_mro() {\n        Python::attach(|py| {\n            assert!(py\n                .get_type::<PyBool>()\n                .mro()\n                .eq(PyTuple::new(\n                    py,\n                    [\n                        py.get_type::<PyBool>(),\n                        py.get_type::<PyInt>(),\n                        py.get_type::<PyAny>()\n                    ]\n                )\n                .unwrap())\n                .unwrap());\n        });\n    }\n\n    #[test]\n    fn test_bases_bool() {\n        Python::attach(|py| {\n            assert!(py\n                .get_type::<PyBool>()\n                .bases()\n                .eq(PyTuple::new(py, [py.get_type::<PyInt>()]).unwrap())\n                .unwrap());\n        });\n    }\n\n    #[test]\n    fn test_bases_object() {\n        Python::attach(|py| {\n            assert!(py\n                .get_type::<PyAny>()\n                .bases()\n                .eq(PyTuple::empty(py))\n                .unwrap());\n        });\n    }\n\n    #[test]\n    fn test_type_names_standard() {\n        Python::attach(|py| {\n            let module_name = generate_unique_module_name(\"test_module\");\n            let module = PyModule::from_code(\n                py,\n                cr#\"\nclass MyClass:\n    pass\n\"#,\n                c_str!(file!()),\n                &module_name,\n            )\n            .expect(\"module create failed\");\n\n            let my_class = module.getattr(\"MyClass\").unwrap();\n            let my_class_type = my_class.cast_into::<PyType>().unwrap();\n            assert_eq!(my_class_type.name().unwrap(), \"MyClass\");\n            assert_eq!(my_class_type.qualname().unwrap(), \"MyClass\");\n            let module_name = module_name.to_str().unwrap();\n            let qualname = format!(\"{module_name}.MyClass\");\n            assert_eq!(my_class_type.module().unwrap(), module_name);\n            assert_eq!(\n                my_class_type.fully_qualified_name().unwrap(),\n                qualname.as_str()\n            );\n        });\n    }\n\n    #[test]\n    fn test_type_names_builtin() {\n        Python::attach(|py| {\n            let bool_type = py.get_type::<PyBool>();\n            assert_eq!(bool_type.name().unwrap(), \"bool\");\n            assert_eq!(bool_type.qualname().unwrap(), \"bool\");\n            assert_eq!(bool_type.module().unwrap(), \"builtins\");\n            assert_eq!(bool_type.fully_qualified_name().unwrap(), \"bool\");\n        });\n    }\n\n    #[test]\n    fn test_type_names_nested() {\n        Python::attach(|py| {\n            let module_name = generate_unique_module_name(\"test_module\");\n            let module = PyModule::from_code(\n                py,\n                cr#\"\nclass OuterClass:\n    class InnerClass:\n        pass\n\"#,\n                c_str!(file!()),\n                &module_name,\n            )\n            .expect(\"module create failed\");\n\n            let outer_class = module.getattr(\"OuterClass\").unwrap();\n            let inner_class = outer_class.getattr(\"InnerClass\").unwrap();\n            let inner_class_type = inner_class.cast_into::<PyType>().unwrap();\n            assert_eq!(inner_class_type.name().unwrap(), \"InnerClass\");\n            assert_eq!(\n                inner_class_type.qualname().unwrap(),\n                \"OuterClass.InnerClass\"\n            );\n            let module_name = module_name.to_str().unwrap();\n            let qualname = format!(\"{module_name}.OuterClass.InnerClass\");\n            assert_eq!(inner_class_type.module().unwrap(), module_name);\n            assert_eq!(\n                inner_class_type.fully_qualified_name().unwrap(),\n                qualname.as_str()\n            );\n        });\n    }\n}\n"
  },
  {
    "path": "src/types/weakref/anyref.rs",
    "content": "use crate::err::PyResult;\nuse crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_union, PyStaticExpr};\nuse crate::sync::PyOnceLock;\nuse crate::type_object::{PyTypeCheck, PyTypeInfo};\nuse crate::types::any::PyAny;\nuse crate::types::{PyTuple, PyWeakrefProxy, PyWeakrefReference};\nuse crate::{ffi, Bound, Py, Python};\n\n/// Represents any Python `weakref` reference.\n///\n/// In Python this is created by calling `weakref.ref` or `weakref.proxy`.\n#[repr(transparent)]\npub struct PyWeakref(PyAny);\n\npyobject_native_type_named!(PyWeakref);\n\n// TODO: We known the layout but this cannot be implemented, due to the lack of public typeobject pointers\n// #[cfg(not(Py_LIMITED_API))]\n// pyobject_native_type_sized!(PyWeakref, ffi::PyWeakReference);\n\nunsafe impl PyTypeCheck for PyWeakref {\n    const NAME: &'static str = \"weakref\";\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const TYPE_HINT: PyStaticExpr = type_hint_union!(\n        PyWeakrefProxy::TYPE_HINT,\n        <PyWeakrefReference as PyTypeCheck>::TYPE_HINT\n    );\n\n    #[inline]\n    fn type_check(object: &Bound<'_, PyAny>) -> bool {\n        unsafe { ffi::PyWeakref_Check(object.as_ptr()) > 0 }\n    }\n\n    fn classinfo_object(py: Python<'_>) -> Bound<'_, PyAny> {\n        static TYPE: PyOnceLock<Py<PyAny>> = PyOnceLock::new();\n        TYPE.get_or_try_init(py, || {\n            PyResult::Ok(\n                PyTuple::new(\n                    py,\n                    [\n                        PyWeakrefProxy::classinfo_object(py),\n                        PyWeakrefReference::classinfo_object(py),\n                    ],\n                )?\n                .into_any()\n                .unbind(),\n            )\n        })\n        .unwrap()\n        .bind(py)\n        .clone()\n    }\n}\n\n/// Implementation of functionality for [`PyWeakref`].\n///\n/// These methods are defined for the `Bound<'py, PyWeakref>` smart pointer, so to use method call\n/// syntax these methods are separated into a trait, because stable Rust does not yet support\n/// `arbitrary_self_types`.\n#[doc(alias = \"PyWeakref\")]\npub trait PyWeakrefMethods<'py>: crate::sealed::Sealed {\n    /// Upgrade the weakref to a direct Bound object reference.\n    ///\n    /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade).\n    /// In Python it would be equivalent to [`PyWeakref_GetRef`].\n    ///\n    /// # Example\n    #[cfg_attr(\n        not(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9))))),\n        doc = \"```rust,ignore\"\n    )]\n    #[cfg_attr(\n        all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))),\n        doc = \"```rust\"\n    )]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyWeakrefReference;\n    ///\n    /// #[pyclass(weakref)]\n    /// struct Foo { /* fields omitted */ }\n    ///\n    /// #[pymethods]\n    /// impl Foo {\n    ///     fn get_data(&self) -> (&str, u32) {\n    ///         (\"Dave\", 10)\n    ///     }\n    /// }\n    ///\n    /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult<String> {\n    ///     if let Some(data_src) = reference.upgrade_as::<Foo>()? {\n    ///         let data = data_src.borrow();\n    ///         let (name, score) = data.get_data();\n    ///         Ok(format!(\"Processing '{}': score = {}\", name, score))\n    ///     } else {\n    ///         Ok(\"The supplied data reference is no longer relevant.\".to_owned())\n    ///     }\n    /// }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let data = Bound::new(py, Foo{})?;\n    ///     let reference = PyWeakrefReference::new(&data)?;\n    ///\n    ///     assert_eq!(\n    ///         parse_data(reference.as_borrowed())?,\n    ///         \"Processing 'Dave': score = 10\"\n    ///     );\n    ///\n    ///     drop(data);\n    ///\n    ///     assert_eq!(\n    ///         parse_data(reference.as_borrowed())?,\n    ///         \"The supplied data reference is no longer relevant.\"\n    ///     );\n    ///\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    ///\n    /// # Panics\n    /// This function panics is the current object is invalid.\n    /// If used properly this is never the case. (NonNull and actually a weakref type)\n    ///\n    /// [`PyWeakref_GetRef`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetRef\n    /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType\n    /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref\n    fn upgrade_as<T>(&self) -> PyResult<Option<Bound<'py, T>>>\n    where\n        T: PyTypeCheck,\n    {\n        self.upgrade()\n            .map(Bound::cast_into::<T>)\n            .transpose()\n            .map_err(Into::into)\n    }\n\n    /// Upgrade the weakref to a direct Bound object reference unchecked. The type of the recovered object is not checked before casting, this could lead to unexpected behavior. Use only when absolutely certain the type can be guaranteed. The `weakref` may still return `None`.\n    ///\n    /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade).\n    /// In Python it would be equivalent to [`PyWeakref_GetRef`].\n    ///\n    /// # Safety\n    /// Callers must ensure that the type is valid or risk type confusion.\n    /// The `weakref` is still allowed to be `None`, if the referenced object has been cleaned up.\n    ///\n    /// # Example\n    #[cfg_attr(\n        not(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9))))),\n        doc = \"```rust,ignore\"\n    )]\n    #[cfg_attr(\n        all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))),\n        doc = \"```rust\"\n    )]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyWeakrefReference;\n    ///\n    /// #[pyclass(weakref)]\n    /// struct Foo { /* fields omitted */ }\n    ///\n    /// #[pymethods]\n    /// impl Foo {\n    ///     fn get_data(&self) -> (&str, u32) {\n    ///         (\"Dave\", 10)\n    ///     }\n    /// }\n    ///\n    /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> String {\n    ///     if let Some(data_src) = unsafe { reference.upgrade_as_unchecked::<Foo>() } {\n    ///         let data = data_src.borrow();\n    ///         let (name, score) = data.get_data();\n    ///         format!(\"Processing '{}': score = {}\", name, score)\n    ///     } else {\n    ///         \"The supplied data reference is no longer relevant.\".to_owned()\n    ///     }\n    /// }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let data = Bound::new(py, Foo{})?;\n    ///     let reference = PyWeakrefReference::new(&data)?;\n    ///\n    ///     assert_eq!(\n    ///         parse_data(reference.as_borrowed()),\n    ///         \"Processing 'Dave': score = 10\"\n    ///     );\n    ///\n    ///     drop(data);\n    ///\n    ///     assert_eq!(\n    ///         parse_data(reference.as_borrowed()),\n    ///         \"The supplied data reference is no longer relevant.\"\n    ///     );\n    ///\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    ///\n    /// # Panics\n    /// This function panics is the current object is invalid.\n    /// If used properly this is never the case. (NonNull and actually a weakref type)\n    ///\n    /// [`PyWeakref_GetRef`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetRef\n    /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType\n    /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref\n    unsafe fn upgrade_as_unchecked<T>(&self) -> Option<Bound<'py, T>> {\n        Some(unsafe { self.upgrade()?.cast_into_unchecked() })\n    }\n\n    /// Upgrade the weakref to a exact direct Bound object reference.\n    ///\n    /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade).\n    /// In Python it would be equivalent to [`PyWeakref_GetRef`].\n    ///\n    /// # Example\n    #[cfg_attr(\n        not(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9))))),\n        doc = \"```rust,ignore\"\n    )]\n    #[cfg_attr(\n        all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))),\n        doc = \"```rust\"\n    )]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyWeakrefReference;\n    ///\n    /// #[pyclass(weakref)]\n    /// struct Foo { /* fields omitted */ }\n    ///\n    /// #[pymethods]\n    /// impl Foo {\n    ///     fn get_data(&self) -> (&str, u32) {\n    ///         (\"Dave\", 10)\n    ///     }\n    /// }\n    ///\n    /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult<String> {\n    ///     if let Some(data_src) = reference.upgrade_as_exact::<Foo>()? {\n    ///         let data = data_src.borrow();\n    ///         let (name, score) = data.get_data();\n    ///         Ok(format!(\"Processing '{}': score = {}\", name, score))\n    ///     } else {\n    ///         Ok(\"The supplied data reference is no longer relevant.\".to_owned())\n    ///     }\n    /// }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let data = Bound::new(py, Foo{})?;\n    ///     let reference = PyWeakrefReference::new(&data)?;\n    ///\n    ///     assert_eq!(\n    ///         parse_data(reference.as_borrowed())?,\n    ///         \"Processing 'Dave': score = 10\"\n    ///     );\n    ///\n    ///     drop(data);\n    ///\n    ///     assert_eq!(\n    ///         parse_data(reference.as_borrowed())?,\n    ///         \"The supplied data reference is no longer relevant.\"\n    ///     );\n    ///\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    ///\n    /// # Panics\n    /// This function panics is the current object is invalid.\n    /// If used properly this is never the case. (NonNull and actually a weakref type)\n    ///\n    /// [`PyWeakref_GetRef`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetRef\n    /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType\n    /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref\n    fn upgrade_as_exact<T>(&self) -> PyResult<Option<Bound<'py, T>>>\n    where\n        T: PyTypeInfo,\n    {\n        self.upgrade()\n            .map(Bound::cast_into_exact)\n            .transpose()\n            .map_err(Into::into)\n    }\n\n    /// Upgrade the weakref to a Bound [`PyAny`] reference to the target object if possible.\n    ///\n    /// It is named `upgrade` to be inline with [rust's `Weak::upgrade`](std::rc::Weak::upgrade).\n    /// This function returns `Some(Bound<'py, PyAny>)` if the reference still exists, otherwise `None` will be returned.\n    ///\n    /// This function gets the optional target of this [`weakref.ReferenceType`] (result of calling [`weakref.ref`]).\n    /// It produces similar results to using [`PyWeakref_GetRef`] in the C api.\n    ///\n    /// # Example\n    #[cfg_attr(\n        not(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9))))),\n        doc = \"```rust,ignore\"\n    )]\n    #[cfg_attr(\n        all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))),\n        doc = \"```rust\"\n    )]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyWeakrefReference;\n    ///\n    /// #[pyclass(weakref)]\n    /// struct Foo { /* fields omitted */ }\n    ///\n    /// fn parse_data(reference: Borrowed<'_, '_, PyWeakrefReference>) -> PyResult<String> {\n    ///     if let Some(object) = reference.upgrade() {\n    ///         Ok(format!(\"The object '{}' referred by this reference still exists.\", object.getattr(\"__class__\")?.getattr(\"__qualname__\")?))\n    ///     } else {\n    ///         Ok(\"The object, which this reference referred to, no longer exists\".to_owned())\n    ///     }\n    /// }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let data = Bound::new(py, Foo{})?;\n    ///     let reference = PyWeakrefReference::new(&data)?;\n    ///\n    ///     assert_eq!(\n    ///         parse_data(reference.as_borrowed())?,\n    ///         \"The object 'Foo' referred by this reference still exists.\"\n    ///     );\n    ///\n    ///     drop(data);\n    ///\n    ///     assert_eq!(\n    ///         parse_data(reference.as_borrowed())?,\n    ///         \"The object, which this reference referred to, no longer exists\"\n    ///     );\n    ///\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    ///\n    /// # Panics\n    /// This function panics is the current object is invalid.\n    /// If used properly this is never the case. (NonNull and actually a weakref type)\n    ///\n    /// [`PyWeakref_GetRef`]: https://docs.python.org/3/c-api/weakref.html#c.PyWeakref_GetRef\n    /// [`weakref.ReferenceType`]: https://docs.python.org/3/library/weakref.html#weakref.ReferenceType\n    /// [`weakref.ref`]: https://docs.python.org/3/library/weakref.html#weakref.ref\n    fn upgrade(&self) -> Option<Bound<'py, PyAny>>;\n}\n\nimpl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakref> {\n    fn upgrade(&self) -> Option<Bound<'py, PyAny>> {\n        let mut obj: *mut ffi::PyObject = std::ptr::null_mut();\n        match unsafe { ffi::compat::PyWeakref_GetRef(self.as_ptr(), &mut obj) } {\n            std::ffi::c_int::MIN..=-1 => panic!(\"The 'weakref' weak reference instance should be valid (non-null and actually a weakref reference)\"),\n            0 => None,\n            1..=std::ffi::c_int::MAX => Some(unsafe { obj.assume_owned_unchecked(self.py()) }),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::any::{PyAny, PyAnyMethods};\n    use crate::types::weakref::{PyWeakref, PyWeakrefMethods, PyWeakrefProxy, PyWeakrefReference};\n    use crate::{Bound, PyResult, Python};\n\n    fn new_reference<'py>(object: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyWeakref>> {\n        let reference = PyWeakrefReference::new(object)?;\n        reference.cast_into().map_err(Into::into)\n    }\n\n    fn new_proxy<'py>(object: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyWeakref>> {\n        let reference = PyWeakrefProxy::new(object)?;\n        reference.cast_into().map_err(Into::into)\n    }\n\n    mod python_class {\n        use super::*;\n        #[cfg(Py_3_10)]\n        use crate::types::PyInt;\n        use crate::PyTypeCheck;\n        use crate::{py_result_ext::PyResultExt, types::PyType};\n        use std::ptr;\n\n        fn get_type(py: Python<'_>) -> PyResult<Bound<'_, PyType>> {\n            py.run(c\"class A:\\n    pass\\n\", None, None)?;\n            py.eval(c\"A\", None, None).cast_into::<PyType>()\n        }\n\n        #[test]\n        fn test_weakref_upgrade_as() -> PyResult<()> {\n            fn inner(\n                create_reference: impl for<'py> FnOnce(\n                    &Bound<'py, PyAny>,\n                )\n                    -> PyResult<Bound<'py, PyWeakref>>,\n            ) -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = create_reference(&object)?;\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = reference.upgrade_as::<PyAny>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())\n                            && obj.is_exact_instance(&class)));\n                    }\n\n                    drop(object);\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = reference.upgrade_as::<PyAny>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            inner(new_reference)?;\n            inner(new_proxy)\n        }\n\n        #[test]\n        fn test_weakref_upgrade_as_unchecked() -> PyResult<()> {\n            fn inner(\n                create_reference: impl for<'py> FnOnce(\n                    &Bound<'py, PyAny>,\n                )\n                    -> PyResult<Bound<'py, PyWeakref>>,\n            ) -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = create_reference(&object)?;\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = unsafe { reference.upgrade_as_unchecked::<PyAny>() };\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())\n                            && obj.is_exact_instance(&class)));\n                    }\n\n                    drop(object);\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = unsafe { reference.upgrade_as_unchecked::<PyAny>() };\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            inner(new_reference)?;\n            inner(new_proxy)\n        }\n\n        #[test]\n        fn test_weakref_upgrade() -> PyResult<()> {\n            fn inner(\n                create_reference: impl for<'py> FnOnce(\n                    &Bound<'py, PyAny>,\n                )\n                    -> PyResult<Bound<'py, PyWeakref>>,\n                call_retrievable: bool,\n            ) -> PyResult<()> {\n                let not_call_retrievable = !call_retrievable;\n\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = create_reference(&object)?;\n\n                    assert!(not_call_retrievable || reference.call0()?.is(&object));\n                    assert!(reference.upgrade().is_some());\n                    assert!(reference.upgrade().is_some_and(|obj| obj.is(&object)));\n\n                    drop(object);\n\n                    assert!(not_call_retrievable || reference.call0()?.is_none());\n                    assert!(reference.upgrade().is_none());\n\n                    Ok(())\n                })\n            }\n\n            inner(new_reference, true)?;\n            inner(new_proxy, false)\n        }\n\n        #[test]\n        fn test_classinfo_object() -> PyResult<()> {\n            fn inner(\n                create_reference: impl for<'py> FnOnce(\n                    &Bound<'py, PyAny>,\n                )\n                    -> PyResult<Bound<'py, PyWeakref>>,\n            ) -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = create_reference(&object)?;\n                    let t = PyWeakref::classinfo_object(py);\n                    assert!(reference.is_instance(&t)?);\n                    Ok(())\n                })\n            }\n\n            inner(new_reference)?;\n            inner(new_proxy)\n        }\n\n        #[cfg(Py_3_10)] // Name is different in 3.9\n        #[test]\n        fn test_classinfo_downcast_error() -> PyResult<()> {\n            Python::attach(|py| {\n                assert_eq!(\n                    PyInt::new(py, 1)\n                        .cast_into::<PyWeakref>()\n                        .unwrap_err()\n                        .to_string(),\n                    \"'int' object is not an instance of 'ProxyType | CallableProxyType | ReferenceType'\"\n                );\n                Ok(())\n            })\n        }\n    }\n\n    // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable.\n    #[cfg(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))))]\n    mod pyo3_pyclass {\n        use super::*;\n        use crate::{pyclass, Py};\n        use std::ptr;\n\n        #[pyclass(weakref, crate = \"crate\")]\n        struct WeakrefablePyClass {}\n\n        #[test]\n        fn test_weakref_upgrade_as() -> PyResult<()> {\n            fn inner(\n                create_reference: impl for<'py> FnOnce(\n                    &Bound<'py, PyAny>,\n                )\n                    -> PyResult<Bound<'py, PyWeakref>>,\n            ) -> PyResult<()> {\n                Python::attach(|py| {\n                    let object = Py::new(py, WeakrefablePyClass {})?;\n                    let reference = create_reference(object.bind(py))?;\n\n                    {\n                        let obj = reference.upgrade_as::<WeakrefablePyClass>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())));\n                    }\n\n                    drop(object);\n\n                    {\n                        let obj = reference.upgrade_as::<WeakrefablePyClass>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            inner(new_reference)?;\n            inner(new_proxy)\n        }\n\n        #[test]\n        fn test_weakref_upgrade_as_unchecked() -> PyResult<()> {\n            fn inner(\n                create_reference: impl for<'py> FnOnce(\n                    &Bound<'py, PyAny>,\n                )\n                    -> PyResult<Bound<'py, PyWeakref>>,\n            ) -> PyResult<()> {\n                Python::attach(|py| {\n                    let object = Py::new(py, WeakrefablePyClass {})?;\n                    let reference = create_reference(object.bind(py))?;\n\n                    {\n                        let obj = unsafe { reference.upgrade_as_unchecked::<WeakrefablePyClass>() };\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())));\n                    }\n\n                    drop(object);\n\n                    {\n                        let obj = unsafe { reference.upgrade_as_unchecked::<WeakrefablePyClass>() };\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            inner(new_reference)?;\n            inner(new_proxy)\n        }\n\n        #[test]\n        fn test_weakref_upgrade() -> PyResult<()> {\n            fn inner(\n                create_reference: impl for<'py> FnOnce(\n                    &Bound<'py, PyAny>,\n                )\n                    -> PyResult<Bound<'py, PyWeakref>>,\n                call_retrievable: bool,\n            ) -> PyResult<()> {\n                let not_call_retrievable = !call_retrievable;\n\n                Python::attach(|py| {\n                    let object = Py::new(py, WeakrefablePyClass {})?;\n                    let reference = create_reference(object.bind(py))?;\n\n                    assert!(not_call_retrievable || reference.call0()?.is(&object));\n                    assert!(reference.upgrade().is_some());\n                    assert!(reference.upgrade().is_some_and(|obj| obj.is(&object)));\n\n                    drop(object);\n\n                    assert!(not_call_retrievable || reference.call0()?.is_none());\n                    assert!(reference.upgrade().is_none());\n\n                    Ok(())\n                })\n            }\n\n            inner(new_reference, true)?;\n            inner(new_proxy, false)\n        }\n    }\n}\n"
  },
  {
    "path": "src/types/weakref/mod.rs",
    "content": "pub use anyref::{PyWeakref, PyWeakrefMethods};\npub use proxy::PyWeakrefProxy;\npub use reference::PyWeakrefReference;\n\npub(crate) mod anyref;\npub(crate) mod proxy;\npub(crate) mod reference;\n"
  },
  {
    "path": "src/types/weakref/proxy.rs",
    "content": "use super::PyWeakrefMethods;\nuse crate::err::PyResult;\nuse crate::ffi_ptr_ext::FfiPtrExt;\n#[cfg(feature = \"experimental-inspect\")]\nuse crate::inspect::{type_hint_identifier, type_hint_union, PyStaticExpr};\nuse crate::py_result_ext::PyResultExt;\nuse crate::sync::PyOnceLock;\nuse crate::type_object::PyTypeCheck;\nuse crate::types::any::PyAny;\nuse crate::{ffi, Borrowed, Bound, BoundObject, IntoPyObject, IntoPyObjectExt, Py, Python};\n\n/// Represents any Python `weakref` Proxy type.\n///\n/// In Python this is created by calling `weakref.proxy`.\n/// This is either a `weakref.ProxyType` or a `weakref.CallableProxyType` (`weakref.ProxyTypes`).\n#[repr(transparent)]\npub struct PyWeakrefProxy(PyAny);\n\npyobject_native_type_named!(PyWeakrefProxy);\n\n// TODO: We known the layout but this cannot be implemented, due to the lack of public typeobject pointers. And it is 2 distinct types\n// #[cfg(not(Py_LIMITED_API))]\n// pyobject_native_type_sized!(PyWeakrefProxy, ffi::PyWeakReference);\n\nunsafe impl PyTypeCheck for PyWeakrefProxy {\n    const NAME: &'static str = \"weakref.ProxyTypes\";\n\n    #[cfg(feature = \"experimental-inspect\")]\n    const TYPE_HINT: PyStaticExpr = type_hint_union!(\n        type_hint_identifier!(\"weakref\", \"ProxyType\"),\n        type_hint_identifier!(\"weakref\", \"CallableProxyType\")\n    );\n\n    #[inline]\n    fn type_check(object: &Bound<'_, PyAny>) -> bool {\n        unsafe { ffi::PyWeakref_CheckProxy(object.as_ptr()) > 0 }\n    }\n\n    fn classinfo_object(py: Python<'_>) -> Bound<'_, PyAny> {\n        static TYPE: PyOnceLock<Py<PyAny>> = PyOnceLock::new();\n        TYPE.import(py, \"weakref\", \"ProxyTypes\").unwrap().clone()\n    }\n}\n\n/// TODO: UPDATE DOCS\nimpl PyWeakrefProxy {\n    /// Constructs a new Weak Reference (`weakref.proxy`/`weakref.ProxyType`/`weakref.CallableProxyType`) for the given object.\n    ///\n    /// Returns a `TypeError` if `object` is not weak referenceable (Most native types and PyClasses without `weakref` flag).\n    ///\n    /// # Examples\n    #[cfg_attr(\n        not(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9))))),\n        doc = \"```rust,ignore\"\n    )]\n    #[cfg_attr(\n        all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))),\n        doc = \"```rust\"\n    )]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyWeakrefProxy;\n    ///\n    /// #[pyclass(weakref)]\n    /// struct Foo { /* fields omitted */ }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let foo = Bound::new(py, Foo {})?;\n    ///     let weakref = PyWeakrefProxy::new(&foo)?;\n    ///     assert!(\n    ///         // In normal situations where a direct `Bound<'py, Foo>` is required use `upgrade::<Foo>`\n    ///         weakref.upgrade().is_some_and(|obj| obj.is(&foo))\n    ///     );\n    ///\n    ///     let weakref2 = PyWeakrefProxy::new(&foo)?;\n    ///     assert!(weakref.is(&weakref2));\n    ///\n    ///     drop(foo);\n    ///\n    ///     assert!(weakref.upgrade().is_none());\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    #[inline]\n    pub fn new<'py>(object: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyWeakrefProxy>> {\n        unsafe {\n            Bound::from_owned_ptr_or_err(\n                object.py(),\n                ffi::PyWeakref_NewProxy(object.as_ptr(), ffi::Py_None()),\n            )\n            .cast_into_unchecked()\n        }\n    }\n\n    /// Constructs a new Weak Reference (`weakref.proxy`/`weakref.ProxyType`/`weakref.CallableProxyType`) for the given object with a callback.\n    ///\n    /// Returns a `TypeError` if `object` is not weak referenceable (Most native types and PyClasses without `weakref` flag) or if the `callback` is not callable or None.\n    ///\n    /// # Examples\n    #[cfg_attr(\n        not(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9))))),\n        doc = \"```rust,ignore\"\n    )]\n    #[cfg_attr(\n        all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))),\n        doc = \"```rust\"\n    )]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyWeakrefProxy;\n    /// use pyo3::ffi::c_str;\n    ///\n    /// #[pyclass(weakref)]\n    /// struct Foo { /* fields omitted */ }\n    ///\n    /// #[pyfunction]\n    /// fn callback(wref: Bound<'_, PyWeakrefProxy>) -> PyResult<()> {\n    ///         let py = wref.py();\n    ///         assert!(wref.upgrade_as::<Foo>()?.is_none());\n    ///         py.run(c\"counter = 1\", None, None)\n    /// }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     py.run(c\"counter = 0\", None, None)?;\n    ///     assert_eq!(py.eval(c\"counter\", None, None)?.extract::<u32>()?, 0);\n    ///     let foo = Bound::new(py, Foo{})?;\n    ///\n    ///     // This is fine.\n    ///     let weakref = PyWeakrefProxy::new_with(&foo, py.None())?;\n    ///     assert!(weakref.upgrade_as::<Foo>()?.is_some());\n    ///     assert!(\n    ///         // In normal situations where a direct `Bound<'py, Foo>` is required use `upgrade::<Foo>`\n    ///         weakref.upgrade().is_some_and(|obj| obj.is(&foo))\n    ///     );\n    ///     assert_eq!(py.eval(c\"counter\", None, None)?.extract::<u32>()?, 0);\n    ///\n    ///     let weakref2 = PyWeakrefProxy::new_with(&foo, wrap_pyfunction!(callback, py)?)?;\n    ///     assert!(!weakref.is(&weakref2)); // Not the same weakref\n    ///     assert!(weakref.eq(&weakref2)?);  // But Equal, since they point to the same object\n    ///\n    ///     drop(foo);\n    ///\n    ///     assert!(weakref.upgrade_as::<Foo>()?.is_none());\n    ///     assert_eq!(py.eval(c\"counter\", None, None)?.extract::<u32>()?, 1);\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    #[inline]\n    pub fn new_with<'py, C>(\n        object: &Bound<'py, PyAny>,\n        callback: C,\n    ) -> PyResult<Bound<'py, PyWeakrefProxy>>\n    where\n        C: IntoPyObject<'py>,\n    {\n        fn inner<'py>(\n            object: &Bound<'py, PyAny>,\n            callback: Borrowed<'_, 'py, PyAny>,\n        ) -> PyResult<Bound<'py, PyWeakrefProxy>> {\n            unsafe {\n                Bound::from_owned_ptr_or_err(\n                    object.py(),\n                    ffi::PyWeakref_NewProxy(object.as_ptr(), callback.as_ptr()),\n                )\n                .cast_into_unchecked()\n            }\n        }\n\n        let py = object.py();\n        inner(\n            object,\n            callback\n                .into_pyobject_or_pyerr(py)?\n                .into_any()\n                .as_borrowed(),\n        )\n    }\n}\n\nimpl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefProxy> {\n    fn upgrade(&self) -> Option<Bound<'py, PyAny>> {\n        let mut obj: *mut ffi::PyObject = std::ptr::null_mut();\n        match unsafe { ffi::compat::PyWeakref_GetRef(self.as_ptr(), &mut obj) } {\n            std::ffi::c_int::MIN..=-1 => panic!(\"The 'weakref.ProxyType' (or `weakref.CallableProxyType`) instance should be valid (non-null and actually a weakref reference)\"),\n            0 => None,\n            1..=std::ffi::c_int::MAX => Some(unsafe { obj.assume_owned_unchecked(self.py()) }),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::exceptions::{PyAttributeError, PyReferenceError, PyTypeError};\n    use crate::types::any::{PyAny, PyAnyMethods};\n    use crate::types::weakref::{PyWeakrefMethods, PyWeakrefProxy};\n    use crate::{Bound, PyResult, Python};\n\n    #[cfg(all(Py_3_13, not(Py_LIMITED_API)))]\n    const DEADREF_FIX: Option<&str> = None;\n    #[cfg(all(not(Py_3_13), not(Py_LIMITED_API)))]\n    const DEADREF_FIX: Option<&str> = Some(\"NoneType\");\n\n    #[cfg(not(Py_LIMITED_API))]\n    fn check_repr(\n        reference: &Bound<'_, PyWeakrefProxy>,\n        object: &Bound<'_, PyAny>,\n        class: Option<&str>,\n    ) -> PyResult<()> {\n        let repr = reference.repr()?.to_string();\n\n        #[cfg(Py_3_13)]\n        let (first_part, second_part) = repr.split_once(';').unwrap();\n        #[cfg(not(Py_3_13))]\n        let (first_part, second_part) = repr.split_once(\" to \").unwrap();\n\n        {\n            let (msg, addr) = first_part.split_once(\"0x\").unwrap();\n\n            assert_eq!(msg, \"<weakproxy at \");\n            assert!(addr\n                .to_lowercase()\n                .contains(format!(\"{:x?}\", reference.as_ptr()).split_at(2).1));\n        }\n\n        if let Some(class) = class.or(DEADREF_FIX) {\n            let (msg, addr) = second_part.split_once(\"0x\").unwrap();\n\n            // Avoids not succeeding at unreliable quotation (Python 3.13-dev adds ' around classname without documenting)\n            #[cfg(Py_3_13)]\n            assert!(msg.starts_with(\" to '\"));\n            assert!(msg.contains(class));\n            assert!(msg.ends_with(\" at \"));\n\n            assert!(addr\n                .to_lowercase()\n                .contains(format!(\"{:x?}\", object.as_ptr()).split_at(2).1));\n        } else {\n            assert!(second_part.contains(\"dead\"));\n        }\n\n        Ok(())\n    }\n\n    mod proxy {\n        use super::*;\n\n        #[cfg(all(not(Py_LIMITED_API), Py_3_10))]\n        const CLASS_NAME: &str = \"'weakref.ProxyType'\";\n        #[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))]\n        const CLASS_NAME: &str = \"'weakproxy'\";\n\n        mod python_class {\n            use super::*;\n            #[cfg(Py_3_10)]\n            use crate::types::PyInt;\n            use crate::PyTypeCheck;\n            use crate::{py_result_ext::PyResultExt, types::PyDict, types::PyType};\n            use std::ptr;\n\n            fn get_type(py: Python<'_>) -> PyResult<Bound<'_, PyType>> {\n                let globals = PyDict::new(py);\n                py.run(c\"class A:\\n    pass\\n\", Some(&globals), None)?;\n                py.eval(c\"A\", Some(&globals), None).cast_into::<PyType>()\n            }\n\n            #[test]\n            fn test_weakref_proxy_behavior() -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n\n                    assert!(!reference.is(&object));\n                    assert!(reference.upgrade().unwrap().is(&object));\n\n                    #[cfg(not(Py_LIMITED_API))]\n                    assert_eq!(\n                        reference.get_type().to_string(),\n                        format!(\"<class {CLASS_NAME}>\")\n                    );\n\n                    assert_eq!(reference.getattr(\"__class__\")?.to_string(), \"<class 'A'>\");\n                    #[cfg(not(Py_LIMITED_API))]\n                    check_repr(&reference, &object, Some(\"A\"))?;\n\n                    assert!(reference\n                        .getattr(\"__callback__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyAttributeError>(py)));\n\n                    assert!(reference.call0().err().is_some_and(|err| {\n                        let result = err.is_instance_of::<PyTypeError>(py);\n                        #[cfg(not(Py_LIMITED_API))]\n                        let result = result\n                            & (err.value(py).to_string()\n                                == format!(\"{CLASS_NAME} object is not callable\"));\n                        result\n                    }));\n\n                    drop(object);\n\n                    assert!(reference.upgrade().is_none());\n                    assert!(reference\n                        .getattr(\"__class__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyReferenceError>(py)));\n                    #[cfg(not(Py_LIMITED_API))]\n                    check_repr(&reference, py.None().bind(py), None)?;\n\n                    assert!(reference\n                        .getattr(\"__callback__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyReferenceError>(py)));\n\n                    assert!(reference.call0().err().is_some_and(|err| {\n                        let result = err.is_instance_of::<PyTypeError>(py);\n                        #[cfg(not(Py_LIMITED_API))]\n                        let result = result\n                            & (err.value(py).to_string()\n                                == format!(\"{CLASS_NAME} object is not callable\"));\n                        result\n                    }));\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade_as() -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = reference.upgrade_as::<PyAny>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())\n                            && obj.is_exact_instance(&class)));\n                    }\n\n                    drop(object);\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = reference.upgrade_as::<PyAny>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade_as_unchecked() -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = unsafe { reference.upgrade_as_unchecked::<PyAny>() };\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())\n                            && obj.is_exact_instance(&class)));\n                    }\n\n                    drop(object);\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = unsafe { reference.upgrade_as_unchecked::<PyAny>() };\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade() -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n\n                    assert!(reference.upgrade().is_some());\n                    assert!(reference.upgrade().is_some_and(|obj| obj.is(&object)));\n\n                    drop(object);\n\n                    assert!(reference.upgrade().is_none());\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_get_object() -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n\n                    assert!(reference.upgrade().unwrap().is(&object));\n\n                    drop(object);\n\n                    assert!(reference.upgrade().is_none());\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_type_object() -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n                    let t = PyWeakrefProxy::classinfo_object(py);\n                    assert!(reference.is_instance(&t)?);\n                    Ok(())\n                })\n            }\n\n            #[cfg(Py_3_10)] // Name is different in 3.9\n            #[test]\n            fn test_classinfo_downcast_error() -> PyResult<()> {\n                Python::attach(|py| {\n                    assert_eq!(\n                        PyInt::new(py, 1)\n                            .cast_into::<PyWeakrefProxy>()\n                            .unwrap_err()\n                            .to_string(),\n                        \"'int' object is not an instance of 'ProxyType | CallableProxyType'\"\n                    );\n                    Ok(())\n                })\n            }\n        }\n\n        // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable.\n        #[cfg(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))))]\n        mod pyo3_pyclass {\n            use super::*;\n            use crate::{pyclass, Py};\n            use std::ptr;\n\n            #[pyclass(weakref, crate = \"crate\")]\n            struct WeakrefablePyClass {}\n\n            #[test]\n            fn test_weakref_proxy_behavior() -> PyResult<()> {\n                Python::attach(|py| {\n                    let object: Bound<'_, WeakrefablePyClass> =\n                        Bound::new(py, WeakrefablePyClass {})?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n\n                    assert!(!reference.is(&object));\n                    assert!(reference.upgrade().unwrap().is(&object));\n                    #[cfg(not(Py_LIMITED_API))]\n                    assert_eq!(\n                        reference.get_type().to_string(),\n                        format!(\"<class {CLASS_NAME}>\")\n                    );\n\n                    assert_eq!(\n                        reference.getattr(\"__class__\")?.to_string(),\n                        \"<class 'builtins.WeakrefablePyClass'>\"\n                    );\n                    #[cfg(not(Py_LIMITED_API))]\n                    check_repr(&reference, object.as_any(), Some(\"WeakrefablePyClass\"))?;\n\n                    assert!(reference\n                        .getattr(\"__callback__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyAttributeError>(py)));\n\n                    assert!(reference.call0().err().is_some_and(|err| {\n                        let result = err.is_instance_of::<PyTypeError>(py);\n                        #[cfg(not(Py_LIMITED_API))]\n                        let result = result\n                            & (err.value(py).to_string()\n                                == format!(\"{CLASS_NAME} object is not callable\"));\n                        result\n                    }));\n\n                    drop(object);\n\n                    assert!(reference.upgrade().is_none());\n                    assert!(reference\n                        .getattr(\"__class__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyReferenceError>(py)));\n                    #[cfg(not(Py_LIMITED_API))]\n                    check_repr(&reference, py.None().bind(py), None)?;\n\n                    assert!(reference\n                        .getattr(\"__callback__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyReferenceError>(py)));\n\n                    assert!(reference.call0().err().is_some_and(|err| {\n                        let result = err.is_instance_of::<PyTypeError>(py);\n                        #[cfg(not(Py_LIMITED_API))]\n                        let result = result\n                            & (err.value(py).to_string()\n                                == format!(\"{CLASS_NAME} object is not callable\"));\n                        result\n                    }));\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade_as() -> PyResult<()> {\n                Python::attach(|py| {\n                    let object = Py::new(py, WeakrefablePyClass {})?;\n                    let reference = PyWeakrefProxy::new(object.bind(py))?;\n\n                    {\n                        let obj = reference.upgrade_as::<WeakrefablePyClass>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())));\n                    }\n\n                    drop(object);\n\n                    {\n                        let obj = reference.upgrade_as::<WeakrefablePyClass>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade_as_unchecked() -> PyResult<()> {\n                Python::attach(|py| {\n                    let object = Py::new(py, WeakrefablePyClass {})?;\n                    let reference = PyWeakrefProxy::new(object.bind(py))?;\n\n                    {\n                        let obj = unsafe { reference.upgrade_as_unchecked::<WeakrefablePyClass>() };\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())));\n                    }\n\n                    drop(object);\n\n                    {\n                        let obj = unsafe { reference.upgrade_as_unchecked::<WeakrefablePyClass>() };\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade() -> PyResult<()> {\n                Python::attach(|py| {\n                    let object = Py::new(py, WeakrefablePyClass {})?;\n                    let reference = PyWeakrefProxy::new(object.bind(py))?;\n\n                    assert!(reference.upgrade().is_some());\n                    assert!(reference.upgrade().is_some_and(|obj| obj.is(&object)));\n\n                    drop(object);\n\n                    assert!(reference.upgrade().is_none());\n\n                    Ok(())\n                })\n            }\n        }\n    }\n\n    mod callable_proxy {\n        use super::*;\n\n        #[cfg(all(not(Py_LIMITED_API), Py_3_10))]\n        const CLASS_NAME: &str = \"<class 'weakref.CallableProxyType'>\";\n        #[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))]\n        const CLASS_NAME: &str = \"<class 'weakcallableproxy'>\";\n\n        mod python_class {\n            use super::*;\n            use crate::PyTypeCheck;\n            use crate::{py_result_ext::PyResultExt, types::PyDict, types::PyType};\n            use std::ptr;\n\n            fn get_type(py: Python<'_>) -> PyResult<Bound<'_, PyType>> {\n                let globals = PyDict::new(py);\n                py.run(\n                    c\"class A:\\n    def __call__(self):\\n        return 'This class is callable!'\\n\",\n                    Some(&globals),\n                    None,\n                )?;\n                py.eval(c\"A\", Some(&globals), None).cast_into::<PyType>()\n            }\n\n            #[test]\n            fn test_weakref_proxy_behavior() -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n\n                    assert!(!reference.is(&object));\n                    assert!(reference.upgrade().unwrap().is(&object));\n                    #[cfg(not(Py_LIMITED_API))]\n                    assert_eq!(reference.get_type().to_string(), CLASS_NAME);\n\n                    assert_eq!(reference.getattr(\"__class__\")?.to_string(), \"<class 'A'>\");\n                    #[cfg(not(Py_LIMITED_API))]\n                    check_repr(&reference, &object, Some(\"A\"))?;\n\n                    assert!(reference\n                        .getattr(\"__callback__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyAttributeError>(py)));\n\n                    assert_eq!(reference.call0()?.to_string(), \"This class is callable!\");\n\n                    drop(object);\n\n                    assert!(reference.upgrade().is_none());\n                    assert!(reference\n                        .getattr(\"__class__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyReferenceError>(py)));\n                    #[cfg(not(Py_LIMITED_API))]\n                    check_repr(&reference, py.None().bind(py), None)?;\n\n                    assert!(reference\n                        .getattr(\"__callback__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyReferenceError>(py)));\n\n                    assert!(reference\n                        .call0()\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyReferenceError>(py)\n                            & (err.value(py).to_string()\n                                == \"weakly-referenced object no longer exists\")));\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade_as() -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = reference.upgrade_as::<PyAny>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())\n                            && obj.is_exact_instance(&class)));\n                    }\n\n                    drop(object);\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = reference.upgrade_as::<PyAny>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade_as_unchecked() -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = unsafe { reference.upgrade_as_unchecked::<PyAny>() };\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())\n                            && obj.is_exact_instance(&class)));\n                    }\n\n                    drop(object);\n\n                    {\n                        // This test is a bit weird but ok.\n                        let obj = unsafe { reference.upgrade_as_unchecked::<PyAny>() };\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade() -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n\n                    assert!(reference.upgrade().is_some());\n                    assert!(reference.upgrade().is_some_and(|obj| obj.is(&object)));\n\n                    drop(object);\n\n                    assert!(reference.upgrade().is_none());\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_type_object() -> PyResult<()> {\n                Python::attach(|py| {\n                    let class = get_type(py)?;\n                    let object = class.call0()?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n                    let t = PyWeakrefProxy::classinfo_object(py);\n                    assert!(reference.is_instance(&t)?);\n                    Ok(())\n                })\n            }\n        }\n\n        // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable.\n        #[cfg(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))))]\n        mod pyo3_pyclass {\n            use super::*;\n            use crate::{pyclass, pymethods, Py};\n            use std::ptr;\n\n            #[pyclass(weakref, crate = \"crate\")]\n            struct WeakrefablePyClass {}\n\n            #[pymethods(crate = \"crate\")]\n            impl WeakrefablePyClass {\n                fn __call__(&self) -> &str {\n                    \"This class is callable!\"\n                }\n            }\n\n            #[test]\n            fn test_weakref_proxy_behavior() -> PyResult<()> {\n                Python::attach(|py| {\n                    let object: Bound<'_, WeakrefablePyClass> =\n                        Bound::new(py, WeakrefablePyClass {})?;\n                    let reference = PyWeakrefProxy::new(&object)?;\n\n                    assert!(!reference.is(&object));\n                    assert!(reference.upgrade().unwrap().is(&object));\n                    #[cfg(not(Py_LIMITED_API))]\n                    assert_eq!(reference.get_type().to_string(), CLASS_NAME);\n\n                    assert_eq!(\n                        reference.getattr(\"__class__\")?.to_string(),\n                        \"<class 'builtins.WeakrefablePyClass'>\"\n                    );\n                    #[cfg(not(Py_LIMITED_API))]\n                    check_repr(&reference, object.as_any(), Some(\"WeakrefablePyClass\"))?;\n\n                    assert!(reference\n                        .getattr(\"__callback__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyAttributeError>(py)));\n\n                    assert_eq!(reference.call0()?.to_string(), \"This class is callable!\");\n\n                    drop(object);\n\n                    assert!(reference.upgrade().is_none());\n                    assert!(reference\n                        .getattr(\"__class__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyReferenceError>(py)));\n                    #[cfg(not(Py_LIMITED_API))]\n                    check_repr(&reference, py.None().bind(py), None)?;\n\n                    assert!(reference\n                        .getattr(\"__callback__\")\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyReferenceError>(py)));\n\n                    assert!(reference\n                        .call0()\n                        .err()\n                        .is_some_and(|err| err.is_instance_of::<PyReferenceError>(py)\n                            & (err.value(py).to_string()\n                                == \"weakly-referenced object no longer exists\")));\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade_as() -> PyResult<()> {\n                Python::attach(|py| {\n                    let object = Py::new(py, WeakrefablePyClass {})?;\n                    let reference = PyWeakrefProxy::new(object.bind(py))?;\n\n                    {\n                        let obj = reference.upgrade_as::<WeakrefablePyClass>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())));\n                    }\n\n                    drop(object);\n\n                    {\n                        let obj = reference.upgrade_as::<WeakrefablePyClass>();\n\n                        assert!(obj.is_ok());\n                        let obj = obj.unwrap();\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade_as_unchecked() -> PyResult<()> {\n                Python::attach(|py| {\n                    let object = Py::new(py, WeakrefablePyClass {})?;\n                    let reference = PyWeakrefProxy::new(object.bind(py))?;\n\n                    {\n                        let obj = unsafe { reference.upgrade_as_unchecked::<WeakrefablePyClass>() };\n\n                        assert!(obj.is_some());\n                        assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())));\n                    }\n\n                    drop(object);\n\n                    {\n                        let obj = unsafe { reference.upgrade_as_unchecked::<WeakrefablePyClass>() };\n\n                        assert!(obj.is_none());\n                    }\n\n                    Ok(())\n                })\n            }\n\n            #[test]\n            fn test_weakref_upgrade() -> PyResult<()> {\n                Python::attach(|py| {\n                    let object = Py::new(py, WeakrefablePyClass {})?;\n                    let reference = PyWeakrefProxy::new(object.bind(py))?;\n\n                    assert!(reference.upgrade().is_some());\n                    assert!(reference.upgrade().is_some_and(|obj| obj.is(&object)));\n\n                    drop(object);\n\n                    assert!(reference.upgrade().is_none());\n\n                    Ok(())\n                })\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/types/weakref/reference.rs",
    "content": "use crate::err::PyResult;\nuse crate::ffi_ptr_ext::FfiPtrExt;\nuse crate::py_result_ext::PyResultExt;\n#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))]\nuse crate::sync::PyOnceLock;\nuse crate::types::any::PyAny;\n#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))]\nuse crate::types::typeobject::PyTypeMethods;\n#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))]\nuse crate::types::PyType;\n#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))]\nuse crate::Py;\nuse crate::{ffi, Borrowed, Bound, BoundObject, IntoPyObject, IntoPyObjectExt};\n\nuse super::PyWeakrefMethods;\n\n/// Represents a Python `weakref.ReferenceType`.\n///\n/// In Python this is created by calling `weakref.ref`.\n#[repr(transparent)]\npub struct PyWeakrefReference(PyAny);\n\n#[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))]\npyobject_subclassable_native_type!(PyWeakrefReference, ffi::PyWeakReference);\n\n#[cfg(not(any(PyPy, GraalPy, Py_LIMITED_API)))]\npyobject_native_type!(\n    PyWeakrefReference,\n    ffi::PyWeakReference,\n    // TODO: should not be depending on a private symbol here!\n    pyobject_native_static_type_object!(ffi::_PyWeakref_RefType),\n    \"weakref\",\n    \"ReferenceType\",\n    #module=Some(\"weakref\"),\n    #checkfunction=ffi::PyWeakref_CheckRef\n);\n\n// When targeting alternative or multiple interpreters, it is better to not use the internal API.\n#[cfg(any(PyPy, GraalPy, Py_LIMITED_API))]\npyobject_native_type_core!(\n    PyWeakrefReference,\n    |py| {\n        static TYPE: PyOnceLock<Py<PyType>> = PyOnceLock::new();\n        TYPE.import(py, \"weakref\", \"ref\")\n            .unwrap()\n            .as_type_ptr()\n    },\n    \"weakref\",\n    \"ReferenceType\",\n    #module=Some(\"weakref\"),\n    #checkfunction=ffi::PyWeakref_CheckRef\n);\n\nimpl PyWeakrefReference {\n    /// Constructs a new Weak Reference (`weakref.ref`/`weakref.ReferenceType`) for the given object.\n    ///\n    /// Returns a `TypeError` if `object` is not weak referenceable (Most native types and PyClasses without `weakref` flag).\n    ///\n    /// # Examples\n    #[cfg_attr(\n        not(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9))))),\n        doc = \"```rust,ignore\"\n    )]\n    #[cfg_attr(\n        all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))),\n        doc = \"```rust\"\n    )]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyWeakrefReference;\n    ///\n    /// #[pyclass(weakref)]\n    /// struct Foo { /* fields omitted */ }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     let foo = Bound::new(py, Foo {})?;\n    ///     let weakref = PyWeakrefReference::new(&foo)?;\n    ///     assert!(\n    ///         // In normal situations where a direct `Bound<'py, Foo>` is required use `upgrade::<Foo>`\n    ///         weakref.upgrade().is_some_and(|obj| obj.is(&foo))\n    ///     );\n    ///\n    ///     let weakref2 = PyWeakrefReference::new(&foo)?;\n    ///     assert!(weakref.is(&weakref2));\n    ///\n    ///     drop(foo);\n    ///\n    ///     assert!(weakref.upgrade().is_none());\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    pub fn new<'py>(object: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyWeakrefReference>> {\n        unsafe {\n            Bound::from_owned_ptr_or_err(\n                object.py(),\n                ffi::PyWeakref_NewRef(object.as_ptr(), ffi::Py_None()),\n            )\n            .cast_into_unchecked()\n        }\n    }\n\n    /// Constructs a new Weak Reference (`weakref.ref`/`weakref.ReferenceType`) for the given object with a callback.\n    ///\n    /// Returns a `TypeError` if `object` is not weak referenceable (Most native types and PyClasses without `weakref` flag) or if the `callback` is not callable or None.\n    ///\n    /// # Examples\n    #[cfg_attr(\n        not(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9))))),\n        doc = \"```rust,ignore\"\n    )]\n    #[cfg_attr(\n        all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))),\n        doc = \"```rust\"\n    )]\n    /// use pyo3::prelude::*;\n    /// use pyo3::types::PyWeakrefReference;\n    /// use pyo3::ffi::c_str;\n    ///\n    /// #[pyclass(weakref)]\n    /// struct Foo { /* fields omitted */ }\n    ///\n    /// #[pyfunction]\n    /// fn callback(wref: Bound<'_, PyWeakrefReference>) -> PyResult<()> {\n    ///         let py = wref.py();\n    ///         assert!(wref.upgrade_as::<Foo>()?.is_none());\n    ///         py.run(c\"counter = 1\", None, None)\n    /// }\n    ///\n    /// # fn main() -> PyResult<()> {\n    /// Python::attach(|py| {\n    ///     py.run(c\"counter = 0\", None, None)?;\n    ///     assert_eq!(py.eval(c\"counter\", None, None)?.extract::<u32>()?, 0);\n    ///     let foo = Bound::new(py, Foo{})?;\n    ///\n    ///     // This is fine.\n    ///     let weakref = PyWeakrefReference::new_with(&foo, py.None())?;\n    ///     assert!(weakref.upgrade_as::<Foo>()?.is_some());\n    ///     assert!(\n    ///         // In normal situations where a direct `Bound<'py, Foo>` is required use `upgrade::<Foo>`\n    ///         weakref.upgrade().is_some_and(|obj| obj.is(&foo))\n    ///     );\n    ///     assert_eq!(py.eval(c\"counter\", None, None)?.extract::<u32>()?, 0);\n    ///\n    ///     let weakref2 = PyWeakrefReference::new_with(&foo, wrap_pyfunction!(callback, py)?)?;\n    ///     assert!(!weakref.is(&weakref2)); // Not the same weakref\n    ///     assert!(weakref.eq(&weakref2)?);  // But Equal, since they point to the same object\n    ///\n    ///     drop(foo);\n    ///\n    ///     assert!(weakref.upgrade_as::<Foo>()?.is_none());\n    ///     assert_eq!(py.eval(c\"counter\", None, None)?.extract::<u32>()?, 1);\n    ///     Ok(())\n    /// })\n    /// # }\n    /// ```\n    pub fn new_with<'py, C>(\n        object: &Bound<'py, PyAny>,\n        callback: C,\n    ) -> PyResult<Bound<'py, PyWeakrefReference>>\n    where\n        C: IntoPyObject<'py>,\n    {\n        fn inner<'py>(\n            object: &Bound<'py, PyAny>,\n            callback: Borrowed<'_, 'py, PyAny>,\n        ) -> PyResult<Bound<'py, PyWeakrefReference>> {\n            unsafe {\n                Bound::from_owned_ptr_or_err(\n                    object.py(),\n                    ffi::PyWeakref_NewRef(object.as_ptr(), callback.as_ptr()),\n                )\n                .cast_into_unchecked()\n            }\n        }\n\n        let py = object.py();\n        inner(\n            object,\n            callback\n                .into_pyobject_or_pyerr(py)?\n                .into_any()\n                .as_borrowed(),\n        )\n    }\n}\n\nimpl<'py> PyWeakrefMethods<'py> for Bound<'py, PyWeakrefReference> {\n    fn upgrade(&self) -> Option<Bound<'py, PyAny>> {\n        let mut obj: *mut ffi::PyObject = std::ptr::null_mut();\n        match unsafe { ffi::compat::PyWeakref_GetRef(self.as_ptr(), &mut obj) } {\n            std::ffi::c_int::MIN..=-1 => panic!(\"The 'weakref.ReferenceType' instance should be valid (non-null and actually a weakref reference)\"),\n            0 => None,\n            1..=std::ffi::c_int::MAX => Some(unsafe { obj.assume_owned_unchecked(self.py()) }),\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::types::any::{PyAny, PyAnyMethods};\n    use crate::types::weakref::{PyWeakrefMethods, PyWeakrefReference};\n    use crate::{Bound, PyResult, Python};\n\n    #[cfg(all(not(Py_LIMITED_API), Py_3_10))]\n    const CLASS_NAME: &str = \"<class 'weakref.ReferenceType'>\";\n    #[cfg(all(not(Py_LIMITED_API), not(Py_3_10)))]\n    const CLASS_NAME: &str = \"<class 'weakref'>\";\n\n    fn check_repr(\n        reference: &Bound<'_, PyWeakrefReference>,\n        object: Option<(&Bound<'_, PyAny>, &str)>,\n    ) -> PyResult<()> {\n        let repr = reference.repr()?.to_string();\n        let (first_part, second_part) = repr.split_once(\"; \").unwrap();\n\n        {\n            let (msg, addr) = first_part.split_once(\"0x\").unwrap();\n\n            assert_eq!(msg, \"<weakref at \");\n            assert!(addr\n                .to_lowercase()\n                .contains(format!(\"{:x?}\", reference.as_ptr()).split_at(2).1));\n        }\n\n        match object {\n            Some((object, class)) => {\n                let (msg, addr) = second_part.split_once(\"0x\").unwrap();\n\n                // Avoid testing on reprs directly since they the quoting and full path vs class name tends to be changedi undocumented.\n                assert!(msg.starts_with(\"to '\"));\n                assert!(msg.contains(class));\n                assert!(msg.ends_with(\"' at \"));\n\n                assert!(addr\n                    .to_lowercase()\n                    .contains(format!(\"{:x?}\", object.as_ptr()).split_at(2).1));\n            }\n            None => {\n                assert_eq!(second_part, \"dead>\")\n            }\n        }\n\n        Ok(())\n    }\n\n    mod python_class {\n        use super::*;\n        use crate::PyTypeInfo;\n        use crate::{py_result_ext::PyResultExt, types::PyType};\n        use std::ptr;\n\n        fn get_type(py: Python<'_>) -> PyResult<Bound<'_, PyType>> {\n            py.run(c\"class A:\\n    pass\\n\", None, None)?;\n            py.eval(c\"A\", None, None).cast_into::<PyType>()\n        }\n\n        #[test]\n        fn test_weakref_reference_behavior() -> PyResult<()> {\n            Python::attach(|py| {\n                let class = get_type(py)?;\n                let object = class.call0()?;\n                let reference = PyWeakrefReference::new(&object)?;\n\n                assert!(!reference.is(&object));\n                assert!(reference.upgrade().unwrap().is(&object));\n\n                #[cfg(not(Py_LIMITED_API))]\n                assert_eq!(reference.get_type().to_string(), CLASS_NAME);\n\n                #[cfg(not(Py_LIMITED_API))]\n                assert_eq!(reference.getattr(\"__class__\")?.to_string(), CLASS_NAME);\n\n                #[cfg(not(Py_LIMITED_API))]\n                check_repr(&reference, Some((object.as_any(), \"A\")))?;\n\n                assert!(reference\n                    .getattr(\"__callback__\")\n                    .is_ok_and(|result| result.is_none()));\n\n                assert!(reference.call0()?.is(&object));\n\n                drop(object);\n\n                assert!(reference.upgrade().is_none());\n                #[cfg(not(Py_LIMITED_API))]\n                assert_eq!(reference.getattr(\"__class__\")?.to_string(), CLASS_NAME);\n                check_repr(&reference, None)?;\n\n                assert!(reference\n                    .getattr(\"__callback__\")\n                    .is_ok_and(|result| result.is_none()));\n\n                assert!(reference.call0()?.is_none());\n\n                Ok(())\n            })\n        }\n\n        #[test]\n        fn test_weakref_upgrade_as() -> PyResult<()> {\n            Python::attach(|py| {\n                let class = get_type(py)?;\n                let object = class.call0()?;\n                let reference = PyWeakrefReference::new(&object)?;\n\n                {\n                    // This test is a bit weird but ok.\n                    let obj = reference.upgrade_as::<PyAny>();\n\n                    assert!(obj.is_ok());\n                    let obj = obj.unwrap();\n\n                    assert!(obj.is_some());\n                    assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())\n                        && obj.is_exact_instance(&class)));\n                }\n\n                drop(object);\n\n                {\n                    // This test is a bit weird but ok.\n                    let obj = reference.upgrade_as::<PyAny>();\n\n                    assert!(obj.is_ok());\n                    let obj = obj.unwrap();\n\n                    assert!(obj.is_none());\n                }\n\n                Ok(())\n            })\n        }\n\n        #[test]\n        fn test_weakref_upgrade_as_unchecked() -> PyResult<()> {\n            Python::attach(|py| {\n                let class = get_type(py)?;\n                let object = class.call0()?;\n                let reference = PyWeakrefReference::new(&object)?;\n\n                {\n                    // This test is a bit weird but ok.\n                    let obj = unsafe { reference.upgrade_as_unchecked::<PyAny>() };\n\n                    assert!(obj.is_some());\n                    assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())\n                        && obj.is_exact_instance(&class)));\n                }\n\n                drop(object);\n\n                {\n                    // This test is a bit weird but ok.\n                    let obj = unsafe { reference.upgrade_as_unchecked::<PyAny>() };\n\n                    assert!(obj.is_none());\n                }\n\n                Ok(())\n            })\n        }\n\n        #[test]\n        fn test_weakref_upgrade() -> PyResult<()> {\n            Python::attach(|py| {\n                let class = get_type(py)?;\n                let object = class.call0()?;\n                let reference = PyWeakrefReference::new(&object)?;\n\n                assert!(reference.call0()?.is(&object));\n                assert!(reference.upgrade().is_some());\n                assert!(reference.upgrade().is_some_and(|obj| obj.is(&object)));\n\n                drop(object);\n\n                assert!(reference.call0()?.is_none());\n                assert!(reference.upgrade().is_none());\n\n                Ok(())\n            })\n        }\n\n        #[test]\n        fn test_type_object() -> PyResult<()> {\n            Python::attach(|py| {\n                let class = get_type(py)?;\n                let object = class.call0()?;\n                let reference = PyWeakrefReference::new(&object)?;\n\n                assert!(reference.is_instance(&PyWeakrefReference::type_object(py))?);\n                Ok(())\n            })\n        }\n    }\n\n    // under 'abi3-py37' and 'abi3-py38' PyClass cannot be weakreferencable.\n    #[cfg(all(feature = \"macros\", not(all(Py_LIMITED_API, not(Py_3_9)))))]\n    mod pyo3_pyclass {\n        use super::*;\n        use crate::{pyclass, Py};\n        use std::ptr;\n\n        #[pyclass(weakref, crate = \"crate\")]\n        struct WeakrefablePyClass {}\n\n        #[test]\n        fn test_weakref_reference_behavior() -> PyResult<()> {\n            Python::attach(|py| {\n                let object: Bound<'_, WeakrefablePyClass> = Bound::new(py, WeakrefablePyClass {})?;\n                let reference = PyWeakrefReference::new(&object)?;\n\n                assert!(!reference.is(&object));\n                assert!(reference.upgrade().unwrap().is(&object));\n                #[cfg(not(Py_LIMITED_API))]\n                assert_eq!(reference.get_type().to_string(), CLASS_NAME);\n\n                #[cfg(not(Py_LIMITED_API))]\n                assert_eq!(reference.getattr(\"__class__\")?.to_string(), CLASS_NAME);\n                #[cfg(not(Py_LIMITED_API))]\n                check_repr(&reference, Some((object.as_any(), \"WeakrefablePyClass\")))?;\n\n                assert!(reference\n                    .getattr(\"__callback__\")\n                    .is_ok_and(|result| result.is_none()));\n\n                assert!(reference.call0()?.is(&object));\n\n                drop(object);\n\n                assert!(reference.upgrade().is_none());\n                #[cfg(not(Py_LIMITED_API))]\n                assert_eq!(reference.getattr(\"__class__\")?.to_string(), CLASS_NAME);\n                check_repr(&reference, None)?;\n\n                assert!(reference\n                    .getattr(\"__callback__\")\n                    .is_ok_and(|result| result.is_none()));\n\n                assert!(reference.call0()?.is_none());\n\n                Ok(())\n            })\n        }\n\n        #[test]\n        fn test_weakref_upgrade_as() -> PyResult<()> {\n            Python::attach(|py| {\n                let object = Py::new(py, WeakrefablePyClass {})?;\n                let reference = PyWeakrefReference::new(object.bind(py))?;\n\n                {\n                    let obj = reference.upgrade_as::<WeakrefablePyClass>();\n\n                    assert!(obj.is_ok());\n                    let obj = obj.unwrap();\n\n                    assert!(obj.is_some());\n                    assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())));\n                }\n\n                drop(object);\n\n                {\n                    let obj = reference.upgrade_as::<WeakrefablePyClass>();\n\n                    assert!(obj.is_ok());\n                    let obj = obj.unwrap();\n\n                    assert!(obj.is_none());\n                }\n\n                Ok(())\n            })\n        }\n\n        #[test]\n        fn test_weakref_upgrade_as_unchecked() -> PyResult<()> {\n            Python::attach(|py| {\n                let object = Py::new(py, WeakrefablePyClass {})?;\n                let reference = PyWeakrefReference::new(object.bind(py))?;\n\n                {\n                    let obj = unsafe { reference.upgrade_as_unchecked::<WeakrefablePyClass>() };\n\n                    assert!(obj.is_some());\n                    assert!(obj.is_some_and(|obj| ptr::eq(obj.as_ptr(), object.as_ptr())));\n                }\n\n                drop(object);\n\n                {\n                    let obj = unsafe { reference.upgrade_as_unchecked::<WeakrefablePyClass>() };\n\n                    assert!(obj.is_none());\n                }\n\n                Ok(())\n            })\n        }\n\n        #[test]\n        fn test_weakref_upgrade() -> PyResult<()> {\n            Python::attach(|py| {\n                let object = Py::new(py, WeakrefablePyClass {})?;\n                let reference = PyWeakrefReference::new(object.bind(py))?;\n\n                assert!(reference.call0()?.is(&object));\n                assert!(reference.upgrade().is_some());\n                assert!(reference.upgrade().is_some_and(|obj| obj.is(&object)));\n\n                drop(object);\n\n                assert!(reference.call0()?.is_none());\n                assert!(reference.upgrade().is_none());\n\n                Ok(())\n            })\n        }\n    }\n}\n"
  },
  {
    "path": "src/version.rs",
    "content": "/// Represents the major, minor, and patch (if any) versions of this interpreter.\n///\n/// This struct is usually created with [`Python::version_info`].\n///\n/// # Examples\n///\n/// ```rust\n/// # use pyo3::Python;\n/// Python::attach(|py| {\n///     // PyO3 supports Python 3.7 and up.\n///     assert!(py.version_info() >= (3, 7));\n///     assert!(py.version_info() >= (3, 7, 0));\n/// });\n/// ```\n///\n/// [`Python::version_info`]: crate::marker::Python::version_info\n#[derive(Debug)]\npub struct PythonVersionInfo<'a> {\n    /// Python major version (e.g. `3`).\n    pub major: u8,\n    /// Python minor version (e.g. `11`).\n    pub minor: u8,\n    /// Python patch version (e.g. `0`).\n    pub patch: u8,\n    /// Python version suffix, if applicable (e.g. `a0`).\n    pub suffix: Option<&'a str>,\n}\n\nimpl<'a> PythonVersionInfo<'a> {\n    /// Parses a hard-coded Python interpreter version string (e.g. 3.9.0a4+).\n    pub(crate) fn from_str(version_number_str: &'a str) -> Result<PythonVersionInfo<'a>, &'a str> {\n        fn split_and_parse_number(version_part: &str) -> (u8, Option<&str>) {\n            match version_part.find(|c: char| !c.is_ascii_digit()) {\n                None => (version_part.parse().unwrap(), None),\n                Some(version_part_suffix_start) => {\n                    let (version_part, version_part_suffix) =\n                        version_part.split_at(version_part_suffix_start);\n                    (version_part.parse().unwrap(), Some(version_part_suffix))\n                }\n            }\n        }\n\n        let mut parts = version_number_str.splitn(3, '.');\n        let major_str = parts.next().ok_or(\"Python major version missing\")?;\n        let minor_str = parts.next().ok_or(\"Python minor version missing\")?;\n        let patch_str = parts.next();\n\n        let major = major_str\n            .parse()\n            .map_err(|_| \"Python major version not an integer\")?;\n        let (minor, suffix) = split_and_parse_number(minor_str);\n        if suffix.is_some() {\n            assert!(patch_str.is_none());\n            return Ok(PythonVersionInfo {\n                major,\n                minor,\n                patch: 0,\n                suffix,\n            });\n        }\n\n        let (patch, suffix) = patch_str.map(split_and_parse_number).unwrap_or_default();\n        Ok(PythonVersionInfo {\n            major,\n            minor,\n            patch,\n            suffix,\n        })\n    }\n}\n\nimpl PartialEq<(u8, u8)> for PythonVersionInfo<'_> {\n    fn eq(&self, other: &(u8, u8)) -> bool {\n        self.major == other.0 && self.minor == other.1\n    }\n}\n\nimpl PartialEq<(u8, u8, u8)> for PythonVersionInfo<'_> {\n    fn eq(&self, other: &(u8, u8, u8)) -> bool {\n        self.major == other.0 && self.minor == other.1 && self.patch == other.2\n    }\n}\n\nimpl PartialOrd<(u8, u8)> for PythonVersionInfo<'_> {\n    fn partial_cmp(&self, other: &(u8, u8)) -> Option<std::cmp::Ordering> {\n        (self.major, self.minor).partial_cmp(other)\n    }\n}\n\nimpl PartialOrd<(u8, u8, u8)> for PythonVersionInfo<'_> {\n    fn partial_cmp(&self, other: &(u8, u8, u8)) -> Option<std::cmp::Ordering> {\n        (self.major, self.minor, self.patch).partial_cmp(other)\n    }\n}\n\n#[cfg(test)]\nmod test {\n    use super::*;\n    use crate::Python;\n    #[test]\n    fn test_python_version_info() {\n        Python::attach(|py| {\n            let version = py.version_info();\n            #[cfg(Py_3_7)]\n            assert!(version >= (3, 7));\n            #[cfg(Py_3_7)]\n            assert!(version >= (3, 7, 0));\n            #[cfg(Py_3_8)]\n            assert!(version >= (3, 8));\n            #[cfg(Py_3_8)]\n            assert!(version >= (3, 8, 0));\n            #[cfg(Py_3_9)]\n            assert!(version >= (3, 9));\n            #[cfg(Py_3_9)]\n            assert!(version >= (3, 9, 0));\n            #[cfg(Py_3_10)]\n            assert!(version >= (3, 10));\n            #[cfg(Py_3_10)]\n            assert!(version >= (3, 10, 0));\n            #[cfg(Py_3_11)]\n            assert!(version >= (3, 11));\n            #[cfg(Py_3_11)]\n            assert!(version >= (3, 11, 0));\n        });\n    }\n\n    #[test]\n    fn test_python_version_info_parse() {\n        assert!(PythonVersionInfo::from_str(\"3.5.0a1\").unwrap() >= (3, 5, 0));\n        assert!(PythonVersionInfo::from_str(\"3.5+\").unwrap() >= (3, 5, 0));\n        assert_eq!(PythonVersionInfo::from_str(\"3.5+\").unwrap(), (3, 5, 0));\n        assert_ne!(PythonVersionInfo::from_str(\"3.5+\").unwrap(), (3, 5, 1));\n        assert!(PythonVersionInfo::from_str(\"3.5.2a1+\").unwrap() < (3, 5, 3));\n        assert_eq!(PythonVersionInfo::from_str(\"3.5.2a1+\").unwrap(), (3, 5, 2));\n        assert_eq!(PythonVersionInfo::from_str(\"3.5.2a1+\").unwrap(), (3, 5));\n        assert_eq!(PythonVersionInfo::from_str(\"3.5+\").unwrap(), (3, 5));\n        assert!(PythonVersionInfo::from_str(\"3.5.2a1+\").unwrap() < (3, 6));\n        assert!(PythonVersionInfo::from_str(\"3.5.2a1+\").unwrap() > (3, 4));\n        assert!(PythonVersionInfo::from_str(\"3.11.3+chromium.29\").unwrap() >= (3, 11, 3));\n        assert_eq!(\n            PythonVersionInfo::from_str(\"3.11.3+chromium.29\")\n                .unwrap()\n                .suffix,\n            Some(\"+chromium.29\")\n        );\n    }\n}\n"
  },
  {
    "path": "tests/test_anyhow.rs",
    "content": "#![cfg(feature = \"anyhow\")]\n\nuse pyo3::wrap_pyfunction;\n\n#[test]\nfn test_anyhow_py_function_ok_result() {\n    use pyo3::{py_run, pyfunction, Python};\n\n    #[pyfunction]\n    #[expect(clippy::unnecessary_wraps)]\n    fn produce_ok_result() -> anyhow::Result<String> {\n        Ok(String::from(\"OK buddy\"))\n    }\n\n    Python::attach(|py| {\n        let func = wrap_pyfunction!(produce_ok_result)(py).unwrap();\n\n        py_run!(\n            py,\n            func,\n            r#\"\n            func()\n            \"#\n        );\n    });\n}\n\n#[test]\nfn test_anyhow_py_function_err_result() {\n    use pyo3::prelude::PyDictMethods;\n    use pyo3::{pyfunction, types::PyDict, Python};\n\n    #[pyfunction]\n    fn produce_err_result() -> anyhow::Result<String> {\n        anyhow::bail!(\"error time\")\n    }\n\n    Python::attach(|py| {\n        let func = wrap_pyfunction!(produce_err_result)(py).unwrap();\n        let locals = PyDict::new(py);\n        locals.set_item(\"func\", func).unwrap();\n\n        py.run(c\"func()\", None, Some(&locals)).unwrap_err();\n    });\n}\n"
  },
  {
    "path": "tests/test_append_to_inittab.rs",
    "content": "#![cfg(all(feature = \"macros\", not(PyPy)))]\n\nuse pyo3::prelude::*;\n\n#[pyfunction]\nfn foo() -> usize {\n    123\n}\n\n#[pymodule]\nfn module_fn_with_functions(m: &Bound<'_, PyModule>) -> PyResult<()> {\n    m.add_function(wrap_pyfunction!(foo, m)?)?;\n    Ok(())\n}\n\n#[pymodule]\nmod module_mod_with_functions {\n    #[pymodule_export]\n    use super::foo;\n}\n\n#[cfg(not(any(PyPy, GraalPy)))]\n#[test]\nfn test_module_append_to_inittab() {\n    use pyo3::append_to_inittab;\n\n    append_to_inittab!(module_fn_with_functions);\n\n    append_to_inittab!(module_mod_with_functions);\n\n    Python::attach(|py| {\n        py.run(\n            cr#\"\nimport module_fn_with_functions\nassert module_fn_with_functions.foo() == 123\n\"#,\n            None,\n            None,\n        )\n        .map_err(|e| e.display(py))\n        .unwrap();\n    });\n\n    Python::attach(|py| {\n        py.run(\n            cr#\"\nimport module_mod_with_functions\nassert module_mod_with_functions.foo() == 123\n\"#,\n            None,\n            None,\n        )\n        .map_err(|e| e.display(py))\n        .unwrap();\n    });\n}\n"
  },
  {
    "path": "tests/test_arithmetics.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::class::basic::CompareOp;\nuse pyo3::py_run;\nuse pyo3::{prelude::*, BoundObject};\n\nmod test_utils;\n\n#[pyclass]\nstruct UnaryArithmetic {\n    inner: f64,\n}\n\n#[pymethods]\nimpl UnaryArithmetic {\n    #[new]\n    fn new(value: f64) -> Self {\n        UnaryArithmetic { inner: value }\n    }\n\n    fn __repr__(&self) -> String {\n        format!(\"UA({})\", self.inner)\n    }\n\n    fn __neg__(&self) -> Self {\n        Self::new(-self.inner)\n    }\n\n    fn __pos__(&self) -> Self {\n        Self::new(self.inner)\n    }\n\n    fn __abs__(&self) -> Self {\n        Self::new(self.inner.abs())\n    }\n\n    fn __invert__(&self) -> Self {\n        Self::new(self.inner.recip())\n    }\n\n    #[pyo3(signature=(_ndigits=None))]\n    fn __round__(&self, _ndigits: Option<u32>) -> Self {\n        Self::new(self.inner.round())\n    }\n}\n\n#[test]\nfn unary_arithmetic() {\n    Python::attach(|py| {\n        let c = Py::new(py, UnaryArithmetic::new(2.7)).unwrap();\n        py_run!(py, c, \"assert repr(-c) == 'UA(-2.7)'\");\n        py_run!(py, c, \"assert repr(+c) == 'UA(2.7)'\");\n        py_run!(py, c, \"assert repr(abs(c)) == 'UA(2.7)'\");\n        py_run!(py, c, \"assert repr(~c) == 'UA(0.37037037037037035)'\");\n        py_run!(py, c, \"assert repr(round(c)) == 'UA(3)'\");\n        py_run!(py, c, \"assert repr(round(c, 1)) == 'UA(3)'\");\n\n        let c: Bound<'_, PyAny> = c.extract(py).unwrap();\n        assert_py_eq!(c.neg().unwrap().repr().unwrap().as_any(), \"UA(-2.7)\");\n        assert_py_eq!(c.pos().unwrap().repr().unwrap().as_any(), \"UA(2.7)\");\n        assert_py_eq!(c.abs().unwrap().repr().unwrap().as_any(), \"UA(2.7)\");\n        assert_py_eq!(\n            c.bitnot().unwrap().repr().unwrap().as_any(),\n            \"UA(0.37037037037037035)\"\n        );\n    });\n}\n\n#[pyclass]\nstruct Indexable(i32);\n\n#[pymethods]\nimpl Indexable {\n    fn __index__(&self) -> i32 {\n        self.0\n    }\n\n    fn __int__(&self) -> i32 {\n        self.0\n    }\n\n    fn __float__(&self) -> f64 {\n        f64::from(self.0)\n    }\n\n    fn __invert__(&self) -> Self {\n        Self(!self.0)\n    }\n}\n\n#[test]\nfn indexable() {\n    Python::attach(|py| {\n        let i = Py::new(py, Indexable(5)).unwrap();\n        py_run!(py, i, \"assert int(i) == 5\");\n        py_run!(py, i, \"assert [0, 1, 2, 3, 4, 5][i] == 5\");\n        py_run!(py, i, \"assert float(i) == 5.0\");\n        py_run!(py, i, \"assert int(~i) == -6\");\n    })\n}\n\n#[pyclass]\nstruct InPlaceOperations {\n    value: u32,\n}\n\n#[pymethods]\nimpl InPlaceOperations {\n    fn __repr__(&self) -> String {\n        format!(\"IPO({:?})\", self.value)\n    }\n\n    fn __iadd__(&mut self, other: u32) {\n        self.value += other;\n    }\n\n    fn __isub__(&mut self, other: u32) {\n        self.value -= other;\n    }\n\n    fn __imul__(&mut self, other: u32) {\n        self.value *= other;\n    }\n\n    fn __ilshift__(&mut self, other: u32) {\n        self.value <<= other;\n    }\n\n    fn __irshift__(&mut self, other: u32) {\n        self.value >>= other;\n    }\n\n    fn __iand__(&mut self, other: u32) {\n        self.value &= other;\n    }\n\n    fn __ixor__(&mut self, other: u32) {\n        self.value ^= other;\n    }\n\n    fn __ior__(&mut self, other: u32) {\n        self.value |= other;\n    }\n\n    fn __ipow__(&mut self, other: u32, _modulo: Option<u32>) {\n        self.value = self.value.pow(other);\n    }\n}\n\n#[test]\nfn inplace_operations() {\n    Python::attach(|py| {\n        let init = |value, code| {\n            let c = Py::new(py, InPlaceOperations { value }).unwrap();\n            py_run!(py, c, code);\n        };\n\n        init(0, \"d = c; c += 1; assert repr(c) == repr(d) == 'IPO(1)'\");\n        init(10, \"d = c; c -= 1; assert repr(c) == repr(d) == 'IPO(9)'\");\n        init(3, \"d = c; c *= 3; assert repr(c) == repr(d) == 'IPO(9)'\");\n        init(3, \"d = c; c <<= 2; assert repr(c) == repr(d) == 'IPO(12)'\");\n        init(12, \"d = c; c >>= 2; assert repr(c) == repr(d) == 'IPO(3)'\");\n        init(12, \"d = c; c &= 10; assert repr(c) == repr(d) == 'IPO(8)'\");\n        init(12, \"d = c; c |= 3; assert repr(c) == repr(d) == 'IPO(15)'\");\n        init(12, \"d = c; c ^= 5; assert repr(c) == repr(d) == 'IPO(9)'\");\n        init(3, \"d = c; c **= 4; assert repr(c) == repr(d) == 'IPO(81)'\");\n        init(\n            3,\n            \"d = c; c.__ipow__(4); assert repr(c) == repr(d) == 'IPO(81)'\",\n        );\n    });\n}\n\n#[pyclass]\nstruct BinaryArithmetic {}\n\n#[pymethods]\nimpl BinaryArithmetic {\n    fn __repr__(&self) -> &'static str {\n        \"BA\"\n    }\n\n    fn __add__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA + {rhs:?}\")\n    }\n\n    fn __sub__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA - {rhs:?}\")\n    }\n\n    fn __mul__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA * {rhs:?}\")\n    }\n\n    fn __matmul__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA @ {rhs:?}\")\n    }\n\n    fn __truediv__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA / {rhs:?}\")\n    }\n\n    fn __floordiv__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA // {rhs:?}\")\n    }\n\n    fn __mod__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA % {rhs:?}\")\n    }\n\n    fn __divmod__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"divmod(BA, {rhs:?})\")\n    }\n\n    fn __lshift__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA << {rhs:?}\")\n    }\n\n    fn __rshift__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA >> {rhs:?}\")\n    }\n\n    fn __and__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA & {rhs:?}\")\n    }\n\n    fn __xor__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA ^ {rhs:?}\")\n    }\n\n    fn __or__(&self, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"BA | {rhs:?}\")\n    }\n\n    fn __pow__(&self, rhs: &Bound<'_, PyAny>, mod_: Option<u32>) -> String {\n        format!(\"BA ** {rhs:?} (mod: {mod_:?})\")\n    }\n}\n\n#[test]\nfn binary_arithmetic() {\n    Python::attach(|py| {\n        let c = Py::new(py, BinaryArithmetic {}).unwrap();\n        py_run!(py, c, \"assert c + c == 'BA + BA'\");\n        py_run!(py, c, \"assert c.__add__(c) == 'BA + BA'\");\n        py_run!(py, c, \"assert c + 1 == 'BA + 1'\");\n        py_run!(py, c, \"assert c - 1 == 'BA - 1'\");\n        py_run!(py, c, \"assert c * 1 == 'BA * 1'\");\n        py_run!(py, c, \"assert c @ 1 == 'BA @ 1'\");\n        py_run!(py, c, \"assert c / 1 == 'BA / 1'\");\n        py_run!(py, c, \"assert c // 1 == 'BA // 1'\");\n        py_run!(py, c, \"assert c % 1 == 'BA % 1'\");\n        py_run!(py, c, \"assert divmod(c, 1) == 'divmod(BA, 1)'\");\n        py_run!(py, c, \"assert c << 1 == 'BA << 1'\");\n        py_run!(py, c, \"assert c >> 1 == 'BA >> 1'\");\n        py_run!(py, c, \"assert c & 1 == 'BA & 1'\");\n        py_run!(py, c, \"assert c ^ 1 == 'BA ^ 1'\");\n        py_run!(py, c, \"assert c | 1 == 'BA | 1'\");\n        py_run!(py, c, \"assert c ** 1 == 'BA ** 1 (mod: None)'\");\n\n        // Class with __add__ only should not allow the reverse op;\n        // this is consistent with Python classes.\n\n        py_expect_exception!(py, c, \"1 + c\", PyTypeError);\n        py_expect_exception!(py, c, \"1 - c\", PyTypeError);\n        py_expect_exception!(py, c, \"1 * c\", PyTypeError);\n        py_expect_exception!(py, c, \"1 @ c\", PyTypeError);\n        py_expect_exception!(py, c, \"1 / c\", PyTypeError);\n        py_expect_exception!(py, c, \"1 // c\", PyTypeError);\n        py_expect_exception!(py, c, \"1 % c\", PyTypeError);\n        py_expect_exception!(py, c, \"divmod(1, c)\", PyTypeError);\n        py_expect_exception!(py, c, \"1 << c\", PyTypeError);\n        py_expect_exception!(py, c, \"1 >> c\", PyTypeError);\n        py_expect_exception!(py, c, \"1 & c\", PyTypeError);\n        py_expect_exception!(py, c, \"1 ^ c\", PyTypeError);\n        py_expect_exception!(py, c, \"1 | c\", PyTypeError);\n        py_expect_exception!(py, c, \"1 ** c\", PyTypeError);\n\n        py_run!(py, c, \"assert pow(c, 1, 100) == 'BA ** 1 (mod: Some(100))'\");\n\n        let c: Bound<'_, PyAny> = c.extract(py).unwrap();\n        assert_py_eq!(c.add(&c).unwrap(), \"BA + BA\");\n        assert_py_eq!(c.sub(&c).unwrap(), \"BA - BA\");\n        assert_py_eq!(c.mul(&c).unwrap(), \"BA * BA\");\n        assert_py_eq!(c.matmul(&c).unwrap(), \"BA @ BA\");\n        assert_py_eq!(c.div(&c).unwrap(), \"BA / BA\");\n        assert_py_eq!(c.floor_div(&c).unwrap(), \"BA // BA\");\n        assert_py_eq!(c.rem(&c).unwrap(), \"BA % BA\");\n        assert_py_eq!(c.divmod(&c).unwrap(), \"divmod(BA, BA)\");\n        assert_py_eq!(c.lshift(&c).unwrap(), \"BA << BA\");\n        assert_py_eq!(c.rshift(&c).unwrap(), \"BA >> BA\");\n        assert_py_eq!(c.bitand(&c).unwrap(), \"BA & BA\");\n        assert_py_eq!(c.bitor(&c).unwrap(), \"BA | BA\");\n        assert_py_eq!(c.bitxor(&c).unwrap(), \"BA ^ BA\");\n        assert_py_eq!(c.pow(&c, py.None()).unwrap(), \"BA ** BA (mod: None)\");\n    });\n}\n\n#[pyclass]\nstruct RhsArithmetic {}\n\n#[pymethods]\nimpl RhsArithmetic {\n    fn __radd__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} + RA\")\n    }\n\n    fn __rsub__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} - RA\")\n    }\n\n    fn __rmul__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} * RA\")\n    }\n\n    fn __rlshift__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} << RA\")\n    }\n\n    fn __rrshift__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} >> RA\")\n    }\n\n    fn __rand__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} & RA\")\n    }\n\n    fn __rxor__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} ^ RA\")\n    }\n\n    fn __ror__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} | RA\")\n    }\n\n    fn __rpow__(&self, other: &Bound<'_, PyAny>, _mod: Option<&Bound<'_, PyAny>>) -> String {\n        format!(\"{other:?} ** RA\")\n    }\n}\n\n#[test]\nfn rhs_arithmetic() {\n    Python::attach(|py| {\n        let c = Py::new(py, RhsArithmetic {}).unwrap();\n        py_run!(py, c, \"assert c.__radd__(1) == '1 + RA'\");\n        py_run!(py, c, \"assert 1 + c == '1 + RA'\");\n        py_run!(py, c, \"assert c.__rsub__(1) == '1 - RA'\");\n        py_run!(py, c, \"assert 1 - c == '1 - RA'\");\n        py_run!(py, c, \"assert c.__rmul__(1) == '1 * RA'\");\n        py_run!(py, c, \"assert 1 * c == '1 * RA'\");\n        py_run!(py, c, \"assert c.__rlshift__(1) == '1 << RA'\");\n        py_run!(py, c, \"assert 1 << c == '1 << RA'\");\n        py_run!(py, c, \"assert c.__rrshift__(1) == '1 >> RA'\");\n        py_run!(py, c, \"assert 1 >> c == '1 >> RA'\");\n        py_run!(py, c, \"assert c.__rand__(1) == '1 & RA'\");\n        py_run!(py, c, \"assert 1 & c == '1 & RA'\");\n        py_run!(py, c, \"assert c.__rxor__(1) == '1 ^ RA'\");\n        py_run!(py, c, \"assert 1 ^ c == '1 ^ RA'\");\n        py_run!(py, c, \"assert c.__ror__(1) == '1 | RA'\");\n        py_run!(py, c, \"assert 1 | c == '1 | RA'\");\n        py_run!(py, c, \"assert c.__rpow__(1) == '1 ** RA'\");\n        py_run!(py, c, \"assert 1 ** c == '1 ** RA'\");\n    });\n}\n\n#[pyclass]\nstruct LhsAndRhs {}\n\nimpl std::fmt::Debug for LhsAndRhs {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"LR\")\n    }\n}\n\n#[pymethods]\nimpl LhsAndRhs {\n    // fn __repr__(&self) -> &'static str {\n    //     \"BA\"\n    // }\n\n    fn __add__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"{lhs:?} + {rhs:?}\")\n    }\n\n    fn __sub__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"{lhs:?} - {rhs:?}\")\n    }\n\n    fn __mul__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"{lhs:?} * {rhs:?}\")\n    }\n\n    fn __lshift__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"{lhs:?} << {rhs:?}\")\n    }\n\n    fn __rshift__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"{lhs:?} >> {rhs:?}\")\n    }\n\n    fn __and__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"{lhs:?} & {rhs:?}\")\n    }\n\n    fn __xor__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"{lhs:?} ^ {rhs:?}\")\n    }\n\n    fn __or__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"{lhs:?} | {rhs:?}\")\n    }\n\n    fn __pow__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>, _mod: Option<usize>) -> String {\n        format!(\"{lhs:?} ** {rhs:?}\")\n    }\n\n    fn __matmul__(lhs: PyRef<'_, Self>, rhs: &Bound<'_, PyAny>) -> String {\n        format!(\"{lhs:?} @ {rhs:?}\")\n    }\n\n    fn __radd__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} + RA\")\n    }\n\n    fn __rsub__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} - RA\")\n    }\n\n    fn __rmul__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} * RA\")\n    }\n\n    fn __rlshift__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} << RA\")\n    }\n\n    fn __rrshift__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} >> RA\")\n    }\n\n    fn __rand__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} & RA\")\n    }\n\n    fn __rxor__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} ^ RA\")\n    }\n\n    fn __ror__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} | RA\")\n    }\n\n    fn __rpow__(&self, other: &Bound<'_, PyAny>, _mod: Option<&Bound<'_, PyAny>>) -> String {\n        format!(\"{other:?} ** RA\")\n    }\n\n    fn __rmatmul__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} @ RA\")\n    }\n\n    fn __rtruediv__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} / RA\")\n    }\n\n    fn __rfloordiv__(&self, other: &Bound<'_, PyAny>) -> String {\n        format!(\"{other:?} // RA\")\n    }\n}\n\n#[test]\nfn lhs_fellback_to_rhs() {\n    Python::attach(|py| {\n        let c = Py::new(py, LhsAndRhs {}).unwrap();\n        // If the light hand value is `LhsAndRhs`, LHS is used.\n        py_run!(py, c, \"assert c + 1 == 'LR + 1'\");\n        py_run!(py, c, \"assert c - 1 == 'LR - 1'\");\n        py_run!(py, c, \"assert c * 1 == 'LR * 1'\");\n        py_run!(py, c, \"assert c << 1 == 'LR << 1'\");\n        py_run!(py, c, \"assert c >> 1 == 'LR >> 1'\");\n        py_run!(py, c, \"assert c & 1 == 'LR & 1'\");\n        py_run!(py, c, \"assert c ^ 1 == 'LR ^ 1'\");\n        py_run!(py, c, \"assert c | 1 == 'LR | 1'\");\n        py_run!(py, c, \"assert c ** 1 == 'LR ** 1'\");\n        py_run!(py, c, \"assert c @ 1 == 'LR @ 1'\");\n        // Fellback to RHS because of type mismatching\n        py_run!(py, c, \"assert 1 + c == '1 + RA'\");\n        py_run!(py, c, \"assert 1 - c == '1 - RA'\");\n        py_run!(py, c, \"assert 1 * c == '1 * RA'\");\n        py_run!(py, c, \"assert 1 << c == '1 << RA'\");\n        py_run!(py, c, \"assert 1 >> c == '1 >> RA'\");\n        py_run!(py, c, \"assert 1 & c == '1 & RA'\");\n        py_run!(py, c, \"assert 1 ^ c == '1 ^ RA'\");\n        py_run!(py, c, \"assert 1 | c == '1 | RA'\");\n        py_run!(py, c, \"assert 1 ** c == '1 ** RA'\");\n        py_run!(py, c, \"assert 1 @ c == '1 @ RA'\");\n    });\n}\n\n#[pyclass]\nstruct RichComparisons {}\n\n#[pymethods]\nimpl RichComparisons {\n    fn __repr__(&self) -> &'static str {\n        \"RC\"\n    }\n\n    fn __richcmp__(&self, other: &Bound<'_, PyAny>, op: CompareOp) -> String {\n        match op {\n            CompareOp::Lt => format!(\"{} < {:?}\", self.__repr__(), other),\n            CompareOp::Le => format!(\"{} <= {:?}\", self.__repr__(), other),\n            CompareOp::Eq => format!(\"{} == {:?}\", self.__repr__(), other),\n            CompareOp::Ne => format!(\"{} != {:?}\", self.__repr__(), other),\n            CompareOp::Gt => format!(\"{} > {:?}\", self.__repr__(), other),\n            CompareOp::Ge => format!(\"{} >= {:?}\", self.__repr__(), other),\n        }\n    }\n}\n\n#[pyclass]\nstruct RichComparisons2 {}\n\n#[pymethods]\nimpl RichComparisons2 {\n    fn __repr__(&self) -> &'static str {\n        \"RC2\"\n    }\n\n    fn __richcmp__(&self, other: &Bound<'_, PyAny>, op: CompareOp) -> PyResult<Py<PyAny>> {\n        match op {\n            CompareOp::Eq => true\n                .into_pyobject(other.py())\n                .map_err(Into::into)\n                .map(BoundObject::into_any)\n                .map(BoundObject::unbind),\n            CompareOp::Ne => false\n                .into_pyobject(other.py())\n                .map_err(Into::into)\n                .map(BoundObject::into_any)\n                .map(BoundObject::unbind),\n            _ => Ok(other.py().NotImplemented()),\n        }\n    }\n}\n\n#[test]\nfn rich_comparisons() {\n    Python::attach(|py| {\n        let c = Py::new(py, RichComparisons {}).unwrap();\n        py_run!(py, c, \"assert (c < c) == 'RC < RC'\");\n        py_run!(py, c, \"assert (c < 1) == 'RC < 1'\");\n        py_run!(py, c, \"assert (1 < c) == 'RC > 1'\");\n        py_run!(py, c, \"assert (c <= c) == 'RC <= RC'\");\n        py_run!(py, c, \"assert (c <= 1) == 'RC <= 1'\");\n        py_run!(py, c, \"assert (1 <= c) == 'RC >= 1'\");\n        py_run!(py, c, \"assert (c == c) == 'RC == RC'\");\n        py_run!(py, c, \"assert (c == 1) == 'RC == 1'\");\n        py_run!(py, c, \"assert (1 == c) == 'RC == 1'\");\n        py_run!(py, c, \"assert (c != c) == 'RC != RC'\");\n        py_run!(py, c, \"assert (c != 1) == 'RC != 1'\");\n        py_run!(py, c, \"assert (1 != c) == 'RC != 1'\");\n        py_run!(py, c, \"assert (c > c) == 'RC > RC'\");\n        py_run!(py, c, \"assert (c > 1) == 'RC > 1'\");\n        py_run!(py, c, \"assert (1 > c) == 'RC < 1'\");\n        py_run!(py, c, \"assert (c >= c) == 'RC >= RC'\");\n        py_run!(py, c, \"assert (c >= 1) == 'RC >= 1'\");\n        py_run!(py, c, \"assert (1 >= c) == 'RC <= 1'\");\n    });\n}\n\n#[test]\nfn rich_comparisons_python_3_type_error() {\n    Python::attach(|py| {\n        let c2 = Py::new(py, RichComparisons2 {}).unwrap();\n        py_expect_exception!(py, c2, \"c2 < c2\", PyTypeError);\n        py_expect_exception!(py, c2, \"c2 < 1\", PyTypeError);\n        py_expect_exception!(py, c2, \"1 < c2\", PyTypeError);\n        py_expect_exception!(py, c2, \"c2 <= c2\", PyTypeError);\n        py_expect_exception!(py, c2, \"c2 <= 1\", PyTypeError);\n        py_expect_exception!(py, c2, \"1 <= c2\", PyTypeError);\n        py_run!(py, c2, \"assert (c2 == c2) == True\");\n        py_run!(py, c2, \"assert (c2 == 1) == True\");\n        py_run!(py, c2, \"assert (1 == c2) == True\");\n        py_run!(py, c2, \"assert (c2 != c2) == False\");\n        py_run!(py, c2, \"assert (c2 != 1) == False\");\n        py_run!(py, c2, \"assert (1 != c2) == False\");\n        py_expect_exception!(py, c2, \"c2 > c2\", PyTypeError);\n        py_expect_exception!(py, c2, \"c2 > 1\", PyTypeError);\n        py_expect_exception!(py, c2, \"1 > c2\", PyTypeError);\n        py_expect_exception!(py, c2, \"c2 >= c2\", PyTypeError);\n        py_expect_exception!(py, c2, \"c2 >= 1\", PyTypeError);\n        py_expect_exception!(py, c2, \"1 >= c2\", PyTypeError);\n    });\n}\n\n// Checks that binary operations for which the arguments don't match the\n// required type, return NotImplemented.\nmod return_not_implemented {\n    use super::*;\n\n    #[pyclass]\n    struct RichComparisonToSelf {}\n\n    #[pymethods]\n    impl RichComparisonToSelf {\n        fn __repr__(&self) -> &'static str {\n            \"RC_Self\"\n        }\n\n        fn __richcmp__(&self, other: PyRef<'_, Self>, _op: CompareOp) -> Py<PyAny> {\n            other.py().None()\n        }\n\n        fn __add__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __sub__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __mul__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __matmul__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __truediv__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __floordiv__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __mod__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __pow__(slf: PyRef<'_, Self>, _other: u8, _modulo: Option<u8>) -> PyRef<'_, Self> {\n            slf\n        }\n        fn __lshift__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __rshift__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __divmod__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __and__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __or__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n        fn __xor__<'p>(slf: PyRef<'p, Self>, _other: PyRef<'p, Self>) -> PyRef<'p, Self> {\n            slf\n        }\n\n        // Inplace assignments\n        fn __iadd__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __isub__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __imul__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __imatmul__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __itruediv__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __ifloordiv__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __imod__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __ilshift__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __irshift__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __iand__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __ior__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __ixor__(&mut self, _other: PyRef<'_, Self>) {}\n        fn __ipow__(&mut self, _other: PyRef<'_, Self>, _modulo: Option<u8>) {}\n    }\n\n    fn _test_binary_dunder(dunder: &str) {\n        Python::attach(|py| {\n            let c2 = Py::new(py, RichComparisonToSelf {}).unwrap();\n            py_run!(\n                py,\n                c2,\n                &format!(\"class Other: pass\\nassert c2.__{dunder}__(Other()) is NotImplemented\")\n            );\n        });\n    }\n\n    fn _test_binary_operator(operator: &str, dunder: &str) {\n        _test_binary_dunder(dunder);\n\n        Python::attach(|py| {\n            let c2 = Py::new(py, RichComparisonToSelf {}).unwrap();\n            py_expect_exception!(\n                py,\n                c2,\n                format!(\"class Other: pass\\nc2 {} Other()\", operator),\n                PyTypeError\n            );\n        });\n    }\n\n    fn _test_inplace_binary_operator(operator: &str, dunder: &str) {\n        _test_binary_operator(operator, dunder);\n    }\n\n    #[test]\n    fn equality() {\n        _test_binary_dunder(\"eq\");\n        _test_binary_dunder(\"ne\");\n    }\n\n    #[test]\n    fn ordering() {\n        _test_binary_operator(\"<\", \"lt\");\n        _test_binary_operator(\"<=\", \"le\");\n        _test_binary_operator(\">\", \"gt\");\n        _test_binary_operator(\">=\", \"ge\");\n    }\n\n    #[test]\n    fn bitwise() {\n        _test_binary_operator(\"&\", \"and\");\n        _test_binary_operator(\"|\", \"or\");\n        _test_binary_operator(\"^\", \"xor\");\n        _test_binary_operator(\"<<\", \"lshift\");\n        _test_binary_operator(\">>\", \"rshift\");\n    }\n\n    #[test]\n    fn arith() {\n        _test_binary_operator(\"+\", \"add\");\n        _test_binary_operator(\"-\", \"sub\");\n        _test_binary_operator(\"*\", \"mul\");\n        _test_binary_operator(\"@\", \"matmul\");\n        _test_binary_operator(\"/\", \"truediv\");\n        _test_binary_operator(\"//\", \"floordiv\");\n        _test_binary_operator(\"%\", \"mod\");\n        _test_binary_operator(\"**\", \"pow\");\n    }\n\n    #[test]\n    fn reverse_arith() {\n        _test_binary_dunder(\"radd\");\n        _test_binary_dunder(\"rsub\");\n        _test_binary_dunder(\"rmul\");\n        _test_binary_dunder(\"rmatmul\");\n        _test_binary_dunder(\"rtruediv\");\n        _test_binary_dunder(\"rfloordiv\");\n        _test_binary_dunder(\"rmod\");\n        _test_binary_dunder(\"rdivmod\");\n        _test_binary_dunder(\"rpow\");\n    }\n\n    #[test]\n    fn inplace_bitwise() {\n        _test_inplace_binary_operator(\"&=\", \"iand\");\n        _test_inplace_binary_operator(\"|=\", \"ior\");\n        _test_inplace_binary_operator(\"^=\", \"ixor\");\n        _test_inplace_binary_operator(\"<<=\", \"ilshift\");\n        _test_inplace_binary_operator(\">>=\", \"irshift\");\n    }\n\n    #[test]\n    fn inplace_arith() {\n        _test_inplace_binary_operator(\"+=\", \"iadd\");\n        _test_inplace_binary_operator(\"-=\", \"isub\");\n        _test_inplace_binary_operator(\"*=\", \"imul\");\n        _test_inplace_binary_operator(\"@=\", \"imatmul\");\n        _test_inplace_binary_operator(\"/=\", \"itruediv\");\n        _test_inplace_binary_operator(\"//=\", \"ifloordiv\");\n        _test_inplace_binary_operator(\"%=\", \"imod\");\n        _test_inplace_binary_operator(\"**=\", \"ipow\");\n    }\n}\n"
  },
  {
    "path": "tests/test_buffer.rs",
    "content": "#![cfg(feature = \"macros\")]\n#![cfg(any(not(Py_LIMITED_API), Py_3_11))]\n#![warn(unsafe_op_in_unsafe_fn)]\n\nuse pyo3::{buffer::PyBuffer, exceptions::PyBufferError, ffi, prelude::*};\nuse std::{\n    os::raw::{c_int, c_void},\n    ptr,\n};\n\n#[macro_use]\nmod test_utils;\n\nenum TestGetBufferError {\n    NullShape,\n    NullStrides,\n    IncorrectItemSize,\n    IncorrectFormat,\n    IncorrectAlignment,\n}\n\n#[pyclass]\nstruct TestBufferErrors {\n    buf: Vec<u32>,\n    error: Option<TestGetBufferError>,\n}\n\n#[pymethods]\nimpl TestBufferErrors {\n    unsafe fn __getbuffer__(\n        slf: PyRefMut<'_, Self>,\n        view: *mut ffi::Py_buffer,\n        flags: c_int,\n    ) -> PyResult<()> {\n        if view.is_null() {\n            return Err(PyBufferError::new_err(\"View is null\"));\n        }\n\n        if (flags & ffi::PyBUF_WRITABLE) == ffi::PyBUF_WRITABLE {\n            return Err(PyBufferError::new_err(\"Object is not writable\"));\n        }\n\n        let bytes = &slf.buf;\n\n        unsafe {\n            (*view).buf = bytes.as_ptr() as *mut c_void;\n            (*view).len = bytes.len() as isize;\n            (*view).readonly = 1;\n            (*view).itemsize = std::mem::size_of::<u32>() as isize;\n\n            let msg = c\"I\";\n            (*view).format = msg.as_ptr() as *mut _;\n\n            (*view).ndim = 1;\n            (*view).shape = &mut (*view).len;\n\n            (*view).strides = &mut (*view).itemsize;\n\n            (*view).suboffsets = ptr::null_mut();\n            (*view).internal = ptr::null_mut();\n\n            if let Some(err) = &slf.error {\n                use TestGetBufferError::*;\n                match err {\n                    NullShape => {\n                        (*view).shape = std::ptr::null_mut();\n                    }\n                    NullStrides => {\n                        (*view).strides = std::ptr::null_mut();\n                    }\n                    IncorrectItemSize => {\n                        (*view).itemsize += 1;\n                    }\n                    IncorrectFormat => {\n                        (*view).format = c\"B\".as_ptr() as _;\n                    }\n                    IncorrectAlignment => (*view).buf = (*view).buf.add(1),\n                }\n            }\n\n            (*view).obj = slf.into_ptr();\n        }\n\n        Ok(())\n    }\n}\n\n#[test]\nfn test_get_buffer_errors() {\n    Python::attach(|py| {\n        let instance = Py::new(\n            py,\n            TestBufferErrors {\n                buf: vec![0, 1, 2, 3],\n                error: None,\n            },\n        )\n        .unwrap();\n\n        assert!(PyBuffer::<u32>::get(instance.bind(py)).is_ok());\n\n        instance.borrow_mut(py).error = Some(TestGetBufferError::NullShape);\n        assert_eq!(\n            PyBuffer::<u32>::get(instance.bind(py))\n                .unwrap_err()\n                .to_string(),\n            \"BufferError: shape is null\"\n        );\n\n        instance.borrow_mut(py).error = Some(TestGetBufferError::NullStrides);\n        assert_eq!(\n            PyBuffer::<u32>::get(instance.bind(py))\n                .unwrap_err()\n                .to_string(),\n            \"BufferError: strides is null\"\n        );\n\n        instance.borrow_mut(py).error = Some(TestGetBufferError::IncorrectItemSize);\n        assert_eq!(\n            PyBuffer::<u32>::get(instance.bind(py))\n                .unwrap_err()\n                .to_string(),\n            \"BufferError: buffer contents are not compatible with u32\"\n        );\n\n        instance.borrow_mut(py).error = Some(TestGetBufferError::IncorrectFormat);\n        assert_eq!(\n            PyBuffer::<u32>::get(instance.bind(py))\n                .unwrap_err()\n                .to_string(),\n            \"BufferError: buffer contents are not compatible with u32\"\n        );\n\n        instance.borrow_mut(py).error = Some(TestGetBufferError::IncorrectAlignment);\n        assert_eq!(\n            PyBuffer::<u32>::get(instance.bind(py))\n                .unwrap_err()\n                .to_string(),\n            \"BufferError: buffer contents are insufficiently aligned for u32\"\n        );\n    });\n}\n"
  },
  {
    "path": "tests/test_buffer_protocol.rs",
    "content": "#![cfg(feature = \"macros\")]\n#![cfg(any(not(Py_LIMITED_API), Py_3_11))]\n#![warn(unsafe_op_in_unsafe_fn)]\n\nuse pyo3::buffer::PyBuffer;\nuse pyo3::exceptions::PyBufferError;\nuse pyo3::ffi;\nuse pyo3::prelude::*;\nuse pyo3::types::IntoPyDict;\nuse std::ffi::CString;\nuse std::ffi::{c_int, c_void};\nuse std::ptr;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::Arc;\n\nmod test_utils;\n\n#[pyclass]\nstruct TestBufferClass {\n    vec: Vec<u8>,\n    drop_called: Arc<AtomicBool>,\n}\n\n#[pymethods]\nimpl TestBufferClass {\n    unsafe fn __getbuffer__(\n        slf: Bound<'_, Self>,\n        view: *mut ffi::Py_buffer,\n        flags: c_int,\n    ) -> PyResult<()> {\n        unsafe { fill_view_from_readonly_data(view, flags, &slf.borrow().vec, slf.into_any()) }\n    }\n\n    unsafe fn __releasebuffer__(&self, view: *mut ffi::Py_buffer) {\n        // Release memory held by the format string\n        drop(unsafe { CString::from_raw((*view).format) });\n    }\n}\n\nimpl Drop for TestBufferClass {\n    fn drop(&mut self) {\n        print!(\"dropped\");\n        self.drop_called.store(true, Ordering::Relaxed);\n    }\n}\n\n#[test]\nfn test_buffer() {\n    let drop_called = Arc::new(AtomicBool::new(false));\n\n    Python::attach(|py| {\n        let instance = Py::new(\n            py,\n            TestBufferClass {\n                vec: vec![b' ', b'2', b'3'],\n                drop_called: drop_called.clone(),\n            },\n        )\n        .unwrap();\n        let env = [(\"ob\", instance)].into_py_dict(py).unwrap();\n        py_assert!(py, *env, \"bytes(ob) == b' 23'\");\n    });\n\n    assert!(drop_called.load(Ordering::Relaxed));\n}\n\n#[test]\nfn test_buffer_referenced() {\n    let drop_called = Arc::new(AtomicBool::new(false));\n\n    let buf = {\n        let input = vec![b' ', b'2', b'3'];\n        Python::attach(|py| {\n            let instance = TestBufferClass {\n                vec: input.clone(),\n                drop_called: drop_called.clone(),\n            }\n            .into_pyobject(py)\n            .unwrap();\n\n            let buf = PyBuffer::<u8>::get(&instance).unwrap();\n            assert_eq!(buf.to_vec(py).unwrap(), input);\n            drop(instance);\n            buf\n        })\n    };\n\n    assert!(!drop_called.load(Ordering::Relaxed));\n\n    Python::attach(|_| {\n        drop(buf);\n    });\n\n    assert!(drop_called.load(Ordering::Relaxed));\n}\n\n#[test]\n#[cfg(Py_3_8)] // sys.unraisablehook not available until Python 3.8\nfn test_releasebuffer_unraisable_error() {\n    use pyo3::exceptions::PyValueError;\n    use test_utils::UnraisableCapture;\n\n    #[pyclass]\n    struct ReleaseBufferError {}\n\n    #[pymethods]\n    impl ReleaseBufferError {\n        unsafe fn __getbuffer__(\n            slf: Bound<'_, Self>,\n            view: *mut ffi::Py_buffer,\n            flags: c_int,\n        ) -> PyResult<()> {\n            static BUF_BYTES: &[u8] = b\"hello world\";\n            unsafe { fill_view_from_readonly_data(view, flags, BUF_BYTES, slf.into_any()) }\n        }\n\n        unsafe fn __releasebuffer__(&self, _view: *mut ffi::Py_buffer) -> PyResult<()> {\n            Err(PyValueError::new_err(\"oh dear\"))\n        }\n    }\n\n    Python::attach(|py| {\n        let instance = Py::new(py, ReleaseBufferError {}).unwrap();\n\n        let (err, object) = UnraisableCapture::enter(py, |capture| {\n            let env = [(\"ob\", instance.clone_ref(py))].into_py_dict(py).unwrap();\n\n            assert!(capture.take_capture().is_none());\n\n            py_assert!(py, *env, \"bytes(ob) == b'hello world'\");\n\n            capture.take_capture().unwrap()\n        });\n\n        assert_eq!(err.to_string(), \"ValueError: oh dear\");\n        assert!(object.is(&instance));\n    });\n}\n\n/// # Safety\n///\n/// `view` must be a valid pointer to ffi::Py_buffer, or null\n/// `data` must outlive the Python lifetime of `owner` (i.e. data must be owned by owner, or data\n/// must be static data)\nunsafe fn fill_view_from_readonly_data(\n    view: *mut ffi::Py_buffer,\n    flags: c_int,\n    data: &[u8],\n    owner: Bound<'_, PyAny>,\n) -> PyResult<()> {\n    if view.is_null() {\n        return Err(PyBufferError::new_err(\"View is null\"));\n    }\n\n    if (flags & ffi::PyBUF_WRITABLE) == ffi::PyBUF_WRITABLE {\n        return Err(PyBufferError::new_err(\"Object is not writable\"));\n    }\n\n    unsafe {\n        (*view).obj = owner.into_ptr();\n\n        (*view).buf = data.as_ptr() as *mut c_void;\n        (*view).len = data.len() as isize;\n        (*view).readonly = 1;\n        (*view).itemsize = 1;\n\n        (*view).format = if (flags & ffi::PyBUF_FORMAT) == ffi::PyBUF_FORMAT {\n            let msg = CString::new(\"B\").unwrap();\n            msg.into_raw()\n        } else {\n            ptr::null_mut()\n        };\n\n        (*view).ndim = 1;\n        (*view).shape = if (flags & ffi::PyBUF_ND) == ffi::PyBUF_ND {\n            &mut (*view).len\n        } else {\n            ptr::null_mut()\n        };\n\n        (*view).strides = if (flags & ffi::PyBUF_STRIDES) == ffi::PyBUF_STRIDES {\n            &mut (*view).itemsize\n        } else {\n            ptr::null_mut()\n        };\n\n        (*view).suboffsets = ptr::null_mut();\n        (*view).internal = ptr::null_mut();\n    }\n    Ok(())\n}\n"
  },
  {
    "path": "tests/test_bytes.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\nuse pyo3::types::PyBytes;\n\nmod test_utils;\n\n#[pyfunction]\nfn bytes_pybytes_conversion(bytes: &[u8]) -> &[u8] {\n    bytes\n}\n\n#[test]\nfn test_pybytes_bytes_conversion() {\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(bytes_pybytes_conversion)(py).unwrap();\n        py_assert!(py, f, \"f(b'Hello World') == b'Hello World'\");\n    });\n}\n\n#[pyfunction]\nfn bytes_vec_conversion(py: Python<'_>, bytes: Vec<u8>) -> Bound<'_, PyBytes> {\n    PyBytes::new(py, bytes.as_slice())\n}\n\n#[test]\nfn test_pybytes_vec_conversion() {\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap();\n        py_assert!(py, f, \"f(b'Hello World') == b'Hello World'\");\n    });\n}\n\n#[test]\nfn test_bytearray_vec_conversion() {\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(bytes_vec_conversion)(py).unwrap();\n        py_assert!(py, f, \"f(bytearray(b'Hello World')) == b'Hello World'\");\n    });\n}\n\n#[test]\nfn test_py_as_bytes() {\n    let pyobj: pyo3::Py<pyo3::types::PyBytes> =\n        Python::attach(|py| pyo3::types::PyBytes::new(py, b\"abc\").unbind());\n\n    let data = Python::attach(|py| pyobj.as_bytes(py));\n\n    assert_eq!(data, b\"abc\");\n\n    Python::attach(move |_py| drop(pyobj));\n}\n"
  },
  {
    "path": "tests/test_class_attributes.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\nuse pyo3::py_run;\n\nmod test_utils;\n\n#[pyclass]\nstruct Foo {\n    #[pyo3(get)]\n    x: i32,\n}\n\n#[pyclass]\nstruct Bar {\n    #[pyo3(get)]\n    x: i32,\n}\n\n#[pymethods]\nimpl Foo {\n    #[classattr]\n    const MY_CONST: &'static str = \"foobar\";\n\n    #[classattr]\n    #[pyo3(name = \"RENAMED_CONST\")]\n    const MY_CONST_2: &'static str = \"foobar_2\";\n\n    #[classattr]\n    fn a() -> i32 {\n        5\n    }\n\n    #[classattr]\n    #[pyo3(name = \"B\")]\n    fn b() -> String {\n        \"bar\".to_string()\n    }\n\n    #[classattr]\n    fn bar() -> Bar {\n        Bar { x: 2 }\n    }\n\n    #[classattr]\n    fn a_foo() -> Foo {\n        Foo { x: 1 }\n    }\n\n    #[classattr]\n    fn a_foo_with_py(py: Python<'_>) -> Py<Foo> {\n        Py::new(py, Foo { x: 1 }).unwrap()\n    }\n}\n\n#[test]\nfn class_attributes() {\n    Python::attach(|py| {\n        let foo_obj = py.get_type::<Foo>();\n        py_assert!(py, foo_obj, \"foo_obj.MY_CONST == 'foobar'\");\n        py_assert!(py, foo_obj, \"foo_obj.RENAMED_CONST == 'foobar_2'\");\n        py_assert!(py, foo_obj, \"foo_obj.a == 5\");\n        py_assert!(py, foo_obj, \"foo_obj.B == 'bar'\");\n        py_assert!(py, foo_obj, \"foo_obj.a_foo.x == 1\");\n        py_assert!(py, foo_obj, \"foo_obj.a_foo_with_py.x == 1\");\n    });\n}\n\n#[test]\nfn class_attributes_mutable() {\n    #[pyclass]\n    struct Foo {}\n\n    #[pymethods]\n    impl Foo {\n        #[classattr]\n        const MY_CONST: &'static str = \"foobar\";\n\n        #[classattr]\n        fn a() -> i32 {\n            5\n        }\n    }\n\n    Python::attach(|py| {\n        let obj = py.get_type::<Foo>();\n        py_run!(py, obj, \"obj.MY_CONST = 'BAZ'\");\n        py_run!(py, obj, \"obj.a = 42\");\n        py_assert!(py, obj, \"obj.MY_CONST == 'BAZ'\");\n        py_assert!(py, obj, \"obj.a == 42\");\n    });\n}\n\n#[test]\n#[cfg(any(Py_3_14, all(Py_3_10, not(Py_LIMITED_API))))]\nfn immutable_type_object() {\n    #[pyclass(immutable_type)]\n    struct ImmutableType {}\n\n    #[pymethods]\n    impl ImmutableType {\n        #[classattr]\n        const MY_CONST: &'static str = \"foobar\";\n\n        #[classattr]\n        fn a() -> i32 {\n            5\n        }\n    }\n\n    #[pyclass(immutable_type)]\n    enum SimpleImmutable {\n        Variant = 42,\n    }\n\n    #[pyclass(immutable_type)]\n    enum ComplexImmutable {\n        Variant(u32),\n    }\n\n    Python::attach(|py| {\n        let obj = py.get_type::<ImmutableType>();\n        py_expect_exception!(py, obj, \"obj.MY_CONST = 'FOOBAR'\", PyTypeError);\n        py_expect_exception!(py, obj, \"obj.a = 6\", PyTypeError);\n\n        let obj = py.get_type::<SimpleImmutable>();\n        py_expect_exception!(py, obj, \"obj.Variant = 0\", PyTypeError);\n\n        let obj = py.get_type::<ComplexImmutable>();\n        py_expect_exception!(py, obj, \"obj.Variant = 0\", PyTypeError);\n    });\n}\n\n#[pymethods]\nimpl Bar {\n    #[classattr]\n    fn a_foo() -> Foo {\n        Foo { x: 3 }\n    }\n}\n\n#[test]\nfn recursive_class_attributes() {\n    Python::attach(|py| {\n        let foo_obj = py.get_type::<Foo>();\n        let bar_obj = py.get_type::<Bar>();\n        py_assert!(py, foo_obj, \"foo_obj.a_foo.x == 1\");\n        py_assert!(py, foo_obj, \"foo_obj.bar.x == 2\");\n        py_assert!(py, bar_obj, \"bar_obj.a_foo.x == 3\");\n    });\n}\n\n#[test]\n#[cfg(all(Py_3_8, panic = \"unwind\"))] // sys.unraisablehook not available until Python 3.8\nfn test_fallible_class_attribute() {\n    use pyo3::exceptions::PyValueError;\n    use test_utils::UnraisableCapture;\n\n    #[pyclass]\n    struct BrokenClass;\n\n    #[pymethods]\n    impl BrokenClass {\n        #[classattr]\n        fn fails_to_init() -> PyResult<i32> {\n            Err(PyValueError::new_err(\"failed to create class attribute\"))\n        }\n    }\n\n    Python::attach(|py| {\n        let (err, object) = UnraisableCapture::enter(py, |capture| {\n            // Accessing the type will attempt to initialize the class attributes\n            assert!(std::panic::catch_unwind(|| py.get_type::<BrokenClass>()).is_err());\n\n            capture.take_capture().unwrap()\n        });\n\n        assert!(object.is_none());\n        assert_eq!(\n            err.to_string(),\n            \"RuntimeError: An error occurred while initializing class BrokenClass\"\n        );\n\n        let cause = err.cause(py).unwrap();\n        assert_eq!(\n            cause.to_string(),\n            \"RuntimeError: An error occurred while initializing `BrokenClass.fails_to_init`\"\n        );\n\n        let cause = cause.cause(py).unwrap();\n        assert_eq!(\n            cause.to_string(),\n            \"ValueError: failed to create class attribute\"\n        );\n        assert!(cause.cause(py).is_none());\n    });\n}\n\n#[pyclass(get_all, set_all, rename_all = \"camelCase\")]\nstruct StructWithRenamedFields {\n    first_field: bool,\n    second_field: u8,\n    #[pyo3(name = \"third_field\")]\n    fourth_field: bool,\n}\n\n#[pymethods]\nimpl StructWithRenamedFields {\n    #[new]\n    fn new() -> Self {\n        Self {\n            first_field: true,\n            second_field: 5,\n            fourth_field: false,\n        }\n    }\n}\n\n#[test]\nfn test_renaming_all_struct_fields() {\n    use pyo3::types::PyBool;\n\n    Python::attach(|py| {\n        let struct_class = py.get_type::<StructWithRenamedFields>();\n        let struct_obj = struct_class.call0().unwrap();\n        assert!(struct_obj\n            .setattr(\"firstField\", PyBool::new(py, false))\n            .is_ok());\n        py_assert!(py, struct_obj, \"struct_obj.firstField == False\");\n        py_assert!(py, struct_obj, \"struct_obj.secondField == 5\");\n        assert!(struct_obj\n            .setattr(\"third_field\", PyBool::new(py, true))\n            .is_ok());\n        py_assert!(py, struct_obj, \"struct_obj.third_field == True\");\n    });\n}\n\n#[pyclass(get_all, set_all, new = \"from_fields\")]\nstruct AutoNewCls {\n    a: i32,\n    b: String,\n    c: Option<f64>,\n}\n\n#[test]\nfn new_impl() {\n    Python::attach(|py| {\n        // python should be able to do AutoNewCls(1, \"two\", 3.0)\n        let cls = py.get_type::<AutoNewCls>();\n        pyo3::py_run!(\n            py,\n            cls,\n            \"inst = cls(1, 'two', 3.0); assert inst.a == 1; assert inst.b == 'two'; assert inst.c == 3.0\"\n        );\n    });\n}\n\n#[pyclass(new = \"from_fields\", get_all)]\nstruct Point2d(#[pyo3(name = \"first\")] f64, #[pyo3(name = \"second\")] f64);\n\n#[test]\nfn new_impl_tuple_struct() {\n    Python::attach(|py| {\n        // python should be able to do AutoNewCls(1, \"two\", 3.0)\n        let cls = py.get_type::<Point2d>();\n        pyo3::py_run!(\n            py,\n            cls,\n            \"inst = cls(0.2, 0.3); assert inst.first == 0.2; assert inst.second == 0.3\"\n        );\n    });\n}\n\nmacro_rules! test_case {\n    ($struct_name: ident, $rule: literal, $field_name: ident, $renamed_field_name: literal, $test_name: ident) => {\n        #[pyclass(get_all, set_all, rename_all = $rule)]\n        #[allow(non_snake_case)]\n        struct $struct_name {\n            $field_name: u8,\n        }\n        #[pymethods]\n        impl $struct_name {\n            #[new]\n            fn new() -> Self {\n                Self { $field_name: 0 }\n            }\n        }\n        #[test]\n        fn $test_name() {\n            //use pyo3::types::PyInt;\n\n            Python::attach(|py| {\n                let struct_class = py.get_type::<$struct_name>();\n                let struct_obj = struct_class.call0().unwrap();\n                assert!(struct_obj.setattr($renamed_field_name, 2).is_ok());\n                let attr = struct_obj.getattr($renamed_field_name).unwrap();\n                assert_eq!(2, attr.extract::<u8>().unwrap());\n            });\n        }\n    };\n}\n\ntest_case!(\n    LowercaseTest,\n    \"lowercase\",\n    fieldOne,\n    \"fieldone\",\n    test_rename_all_lowercase\n);\ntest_case!(\n    CamelCaseTest,\n    \"camelCase\",\n    field_one,\n    \"fieldOne\",\n    test_rename_all_camel_case\n);\ntest_case!(\n    KebabCaseTest,\n    \"kebab-case\",\n    field_one,\n    \"field-one\",\n    test_rename_all_kebab_case\n);\ntest_case!(\n    PascalCaseTest,\n    \"PascalCase\",\n    field_one,\n    \"FieldOne\",\n    test_rename_all_pascal_case\n);\ntest_case!(\n    ScreamingSnakeCaseTest,\n    \"SCREAMING_SNAKE_CASE\",\n    field_one,\n    \"FIELD_ONE\",\n    test_rename_all_screaming_snake_case\n);\ntest_case!(\n    ScreamingKebabCaseTest,\n    \"SCREAMING-KEBAB-CASE\",\n    field_one,\n    \"FIELD-ONE\",\n    test_rename_all_screaming_kebab_case\n);\ntest_case!(\n    SnakeCaseTest,\n    \"snake_case\",\n    fieldOne,\n    \"field_one\",\n    test_rename_all_snake_case\n);\ntest_case!(\n    UppercaseTest,\n    \"UPPERCASE\",\n    fieldOne,\n    \"FIELDONE\",\n    test_rename_all_uppercase\n);\n"
  },
  {
    "path": "tests/test_class_basics.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\nuse pyo3::py_run;\nuse pyo3::types::PyType;\n#[cfg(not(target_arch = \"wasm32\"))]\nuse pyo3::PyClass;\n\nmod test_utils;\n\n#[pyclass]\nstruct EmptyClass {}\n\n#[test]\nfn empty_class() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<EmptyClass>();\n        // By default, don't allow creating instances from python.\n        assert!(typeobj.call((), None).is_err());\n\n        py_assert!(py, typeobj, \"typeobj.__name__ == 'EmptyClass'\");\n    });\n}\n\n#[pyclass]\nstruct UnitClass;\n\n#[test]\nfn unit_class() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<UnitClass>();\n        // By default, don't allow creating instances from python.\n        assert!(typeobj.call((), None).is_err());\n\n        py_assert!(py, typeobj, \"typeobj.__name__ == 'UnitClass'\");\n    });\n}\n\n/// Line1\n///Line2\n///  Line3\n// this is not doc string\n#[pyclass]\nstruct ClassWithDocs {\n    /// Property field\n    #[pyo3(get, set)]\n    value: i32,\n\n    /// Read-only property field\n    #[pyo3(get)]\n    readonly: i32,\n\n    /// Write-only property field\n    #[pyo3(set)]\n    writeonly: i32,\n}\n\n#[test]\nfn class_with_docstr() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<ClassWithDocs>();\n        py_run!(\n            py,\n            typeobj,\n            \"assert typeobj.__doc__ == 'Line1\\\\nLine2\\\\n Line3'\"\n        );\n        py_run!(\n            py,\n            typeobj,\n            \"assert typeobj.value.__doc__ == 'Property field'\"\n        );\n        py_run!(\n            py,\n            typeobj,\n            \"assert typeobj.readonly.__doc__ == 'Read-only property field'\"\n        );\n        py_run!(\n            py,\n            typeobj,\n            \"assert typeobj.writeonly.__doc__ == 'Write-only property field'\"\n        );\n    });\n}\n\n#[pyclass(name = \"CustomName\")]\nstruct EmptyClass2 {}\n\n#[pymethods]\nimpl EmptyClass2 {\n    #[pyo3(name = \"custom_fn\")]\n    fn bar(&self) {}\n\n    #[staticmethod]\n    #[pyo3(name = \"custom_static\")]\n    fn bar_static() {}\n\n    #[getter]\n    #[pyo3(name = \"custom_getter\")]\n    fn foo(&self) -> i32 {\n        5\n    }\n}\n\n#[test]\nfn custom_names() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<EmptyClass2>();\n        py_assert!(py, typeobj, \"typeobj.__name__ == 'CustomName'\");\n        py_assert!(py, typeobj, \"typeobj.custom_fn.__name__ == 'custom_fn'\");\n        py_assert!(\n            py,\n            typeobj,\n            \"typeobj.custom_static.__name__ == 'custom_static'\"\n        );\n        py_assert!(\n            py,\n            typeobj,\n            \"typeobj.custom_getter.__name__ == 'custom_getter'\"\n        );\n        py_assert!(py, typeobj, \"not hasattr(typeobj, 'bar')\");\n        py_assert!(py, typeobj, \"not hasattr(typeobj, 'bar_static')\");\n        py_assert!(py, typeobj, \"not hasattr(typeobj, 'foo')\");\n    });\n}\n\n#[pyclass(name = \"loop\")]\nstruct ClassRustKeywords {\n    #[pyo3(name = \"unsafe\", get, set)]\n    unsafe_variable: usize,\n}\n\n#[pymethods]\nimpl ClassRustKeywords {\n    #[pyo3(name = \"struct\")]\n    fn struct_method(&self) {}\n\n    #[staticmethod]\n    #[pyo3(name = \"type\")]\n    fn type_method() {}\n}\n\n#[test]\nfn keyword_names() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<ClassRustKeywords>();\n        py_assert!(py, typeobj, \"typeobj.__name__ == 'loop'\");\n        py_assert!(py, typeobj, \"typeobj.struct.__name__ == 'struct'\");\n        py_assert!(py, typeobj, \"typeobj.type.__name__ == 'type'\");\n        py_assert!(py, typeobj, \"typeobj.unsafe.__name__ == 'unsafe'\");\n        py_assert!(py, typeobj, \"not hasattr(typeobj, 'unsafe_variable')\");\n        py_assert!(py, typeobj, \"not hasattr(typeobj, 'struct_method')\");\n        py_assert!(py, typeobj, \"not hasattr(typeobj, 'type_method')\");\n    });\n}\n\n#[pyclass]\nstruct RawIdents {\n    #[pyo3(get, set)]\n    r#type: i64,\n}\n\n#[pymethods]\nimpl RawIdents {\n    fn r#fn(&self) {}\n}\n\n#[test]\nfn test_raw_idents() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<RawIdents>();\n        py_assert!(py, typeobj, \"not hasattr(typeobj, 'r#fn')\");\n        py_assert!(py, typeobj, \"hasattr(typeobj, 'fn')\");\n        py_assert!(py, typeobj, \"hasattr(typeobj, 'type')\");\n    });\n}\n\n#[pyclass]\nstruct EmptyClassInModule {}\n\n// Ignored because heap types do not show up as being in builtins, instead they\n// raise AttributeError:\n// https://github.com/python/cpython/blob/v3.11.1/Objects/typeobject.c#L541-L570\n#[test]\n#[ignore]\nfn empty_class_in_module() {\n    Python::attach(|py| {\n        let module = PyModule::new(py, \"test_module.nested\").unwrap();\n        module.add_class::<EmptyClassInModule>().unwrap();\n\n        let ty = module.getattr(\"EmptyClassInModule\").unwrap();\n        assert_eq!(\n            ty.getattr(\"__name__\").unwrap().extract::<String>().unwrap(),\n            \"EmptyClassInModule\"\n        );\n\n        let module: String = ty.getattr(\"__module__\").unwrap().extract().unwrap();\n\n        // Rationale: The class can be added to many modules, but will only be initialized once.\n        // We currently have no way of determining a canonical module, so builtins is better\n        // than using whatever calls init first.\n        assert_eq!(module, \"builtins\");\n    });\n}\n\n#[pyclass]\nstruct ClassWithObjectField {\n    // It used to be that PyObject was not supported with (get, set)\n    // - this test is just ensuring it compiles.\n    #[pyo3(get, set)]\n    value: Py<PyAny>,\n}\n\n#[pymethods]\nimpl ClassWithObjectField {\n    #[new]\n    fn new(value: Py<PyAny>) -> ClassWithObjectField {\n        Self { value }\n    }\n}\n\n#[test]\nfn class_with_object_field() {\n    Python::attach(|py| {\n        let ty = py.get_type::<ClassWithObjectField>();\n        py_assert!(py, ty, \"ty(5).value == 5\");\n        py_assert!(py, ty, \"ty(None).value == None\");\n    });\n}\n\n#[pyclass(frozen, eq, hash)]\n#[derive(PartialEq, Hash)]\nstruct ClassWithHash {\n    value: usize,\n}\n\n#[test]\nfn class_with_hash() {\n    Python::attach(|py| {\n        use pyo3::types::IntoPyDict;\n        let class = ClassWithHash { value: 42 };\n        let hash = {\n            use std::hash::{Hash, Hasher};\n            let mut hasher = std::collections::hash_map::DefaultHasher::new();\n            class.hash(&mut hasher);\n            hasher.finish() as isize\n        };\n\n        let env = [\n            (\"obj\", Py::new(py, class).unwrap().into_any()),\n            (\"hsh\", hash.into_pyobject(py).unwrap().into_any().unbind()),\n        ]\n        .into_py_dict(py)\n        .unwrap();\n\n        py_assert!(py, *env, \"hash(obj) == hsh\");\n    });\n}\n\n#[pyclass(unsendable, subclass)]\nstruct UnsendableBase {\n    value: std::rc::Rc<usize>,\n}\n\n#[pymethods]\nimpl UnsendableBase {\n    #[new]\n    fn new(value: usize) -> UnsendableBase {\n        Self {\n            value: std::rc::Rc::new(value),\n        }\n    }\n\n    #[getter]\n    fn value(&self) -> usize {\n        *self.value\n    }\n}\n\n#[pyclass(extends=UnsendableBase)]\nstruct UnsendableChild {}\n\n#[pymethods]\nimpl UnsendableChild {\n    #[new]\n    fn new(value: usize) -> (UnsendableChild, UnsendableBase) {\n        (UnsendableChild {}, UnsendableBase::new(value))\n    }\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\nfn test_unsendable<T: PyClass + 'static>() -> PyResult<()> {\n    let (keep_obj_here, obj) = Python::attach(|py| -> PyResult<_> {\n        let obj: Py<T> = PyType::new::<T>(py).call1((5,))?.extract()?;\n\n        // Accessing the value inside this thread should not panic\n        let caught_panic =\n            std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| -> PyResult<_> {\n                assert_eq!(obj.getattr(py, \"value\")?.extract::<usize>(py)?, 5);\n                Ok(())\n            }))\n            .is_err();\n\n        assert!(!caught_panic);\n\n        Ok((obj.clone_ref(py), obj))\n    })?;\n\n    let caught_panic = std::thread::spawn(move || {\n        // This access must panic\n        Python::attach(move |py| {\n            obj.borrow(py);\n        });\n    })\n    .join();\n\n    Python::attach(|_py| drop(keep_obj_here));\n\n    if let Err(err) = caught_panic {\n        if let Some(msg) = err.downcast_ref::<String>() {\n            panic!(\"{}\", msg);\n        }\n    }\n\n    Ok(())\n}\n\n/// If a class is marked as `unsendable`, it panics when accessed by another thread.\n#[test]\n#[cfg(not(target_arch = \"wasm32\"))]\n#[should_panic(\n    expected = \"test_class_basics::UnsendableBase is unsendable, but sent to another thread\"\n)]\nfn panic_unsendable_base() {\n    test_unsendable::<UnsendableBase>().unwrap();\n}\n\n#[test]\n#[cfg(not(target_arch = \"wasm32\"))]\n#[should_panic(\n    expected = \"test_class_basics::UnsendableBase is unsendable, but sent to another thread\"\n)]\nfn panic_unsendable_child() {\n    test_unsendable::<UnsendableChild>().unwrap();\n}\n\nfn get_length(obj: &Bound<'_, PyAny>) -> PyResult<usize> {\n    let length = obj.len()?;\n\n    Ok(length)\n}\n\nfn is_even(obj: &Bound<'_, PyAny>) -> PyResult<bool> {\n    obj.extract::<i32>().map(|i| i % 2 == 0)\n}\n\n#[pyclass]\nstruct ClassWithFromPyWithMethods {}\n\n#[pymethods]\nimpl ClassWithFromPyWithMethods {\n    fn instance_method(&self, #[pyo3(from_py_with = get_length)] argument: usize) -> usize {\n        argument\n    }\n    #[classmethod]\n    fn classmethod(\n        _cls: &Bound<'_, PyType>,\n        #[pyo3(from_py_with = Bound::<'_, PyAny>::len)] argument: usize,\n    ) -> usize {\n        argument\n    }\n\n    #[staticmethod]\n    fn staticmethod(#[pyo3(from_py_with = get_length)] argument: usize) -> usize {\n        argument\n    }\n\n    fn __contains__(&self, #[pyo3(from_py_with = is_even)] obj: bool) -> bool {\n        obj\n    }\n}\n\n#[test]\nfn test_pymethods_from_py_with() {\n    Python::attach(|py| {\n        let instance = Py::new(py, ClassWithFromPyWithMethods {}).unwrap();\n\n        py_run!(\n            py,\n            instance,\n            r#\"\n        arg = {1: 1, 2: 3}\n\n        assert instance.instance_method(arg) == 2\n        assert instance.classmethod(arg) == 2\n        assert instance.staticmethod(arg) == 2\n\n        assert 42 in instance\n        assert 73 not in instance\n        \"#\n        );\n    })\n}\n\n#[pyclass]\nstruct TupleClass(#[pyo3(get, set, name = \"value\")] i32);\n\n#[test]\nfn test_tuple_struct_class() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<TupleClass>();\n        assert!(typeobj.call((), None).is_err());\n\n        py_assert!(py, typeobj, \"typeobj.__name__ == 'TupleClass'\");\n\n        let instance = Py::new(py, TupleClass(5)).unwrap();\n        py_run!(\n            py,\n            instance,\n            r#\"\n        assert instance.value == 5;\n        instance.value = 1234;\n        assert instance.value == 1234;\n        \"#\n        );\n\n        assert_eq!(instance.borrow(py).0, 1234);\n    });\n}\n\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\n#[pyclass(dict, subclass)]\nstruct DunderDictSupport {\n    // Make sure that dict_offset runs with non-zero sized Self\n    _pad: [u8; 32],\n}\n\n#[test]\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\nfn dunder_dict_support() {\n    Python::attach(|py| {\n        let inst = Py::new(\n            py,\n            DunderDictSupport {\n                _pad: *b\"DEADBEEFDEADBEEFDEADBEEFDEADBEEF\",\n            },\n        )\n        .unwrap();\n        py_run!(\n            py,\n            inst,\n            r#\"\n        inst.a = 1\n        assert inst.a == 1\n    \"#\n        );\n    });\n}\n\n#[test]\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\nfn access_dunder_dict() {\n    Python::attach(|py| {\n        let inst = Py::new(\n            py,\n            DunderDictSupport {\n                _pad: *b\"DEADBEEFDEADBEEFDEADBEEFDEADBEEF\",\n            },\n        )\n        .unwrap();\n        py_run!(\n            py,\n            inst,\n            r#\"\n        inst.a = 1\n        assert inst.__dict__ == {'a': 1}\n    \"#\n        );\n    });\n}\n\n// If the base class has dict support, child class also has dict\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\n#[pyclass(extends=DunderDictSupport)]\nstruct InheritDict {\n    _value: usize,\n}\n\n#[test]\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\nfn inherited_dict() {\n    Python::attach(|py| {\n        let inst = Py::new(\n            py,\n            (\n                InheritDict { _value: 0 },\n                DunderDictSupport {\n                    _pad: *b\"DEADBEEFDEADBEEFDEADBEEFDEADBEEF\",\n                },\n            ),\n        )\n        .unwrap();\n        py_run!(\n            py,\n            inst,\n            r#\"\n        inst.a = 1\n        assert inst.a == 1\n    \"#\n        );\n    });\n}\n\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\n#[pyclass(weakref, dict)]\nstruct WeakRefDunderDictSupport {\n    // Make sure that weaklist_offset runs with non-zero sized Self\n    _pad: [u8; 32],\n}\n\n#[test]\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\nfn weakref_dunder_dict_support() {\n    Python::attach(|py| {\n        let inst = Py::new(\n            py,\n            WeakRefDunderDictSupport {\n                _pad: *b\"DEADBEEFDEADBEEFDEADBEEFDEADBEEF\",\n            },\n        )\n        .unwrap();\n        py_run!(\n            py,\n            inst,\n            \"import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1\"\n        );\n    });\n}\n\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\n#[pyclass(weakref, subclass)]\nstruct WeakRefSupport {\n    _pad: [u8; 32],\n}\n\n#[test]\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\nfn weakref_support() {\n    Python::attach(|py| {\n        let inst = Py::new(\n            py,\n            WeakRefSupport {\n                _pad: *b\"DEADBEEFDEADBEEFDEADBEEFDEADBEEF\",\n            },\n        )\n        .unwrap();\n        py_run!(\n            py,\n            inst,\n            \"import weakref; assert weakref.ref(inst)() is inst\"\n        );\n    });\n}\n\n// If the base class has weakref support, child class also has weakref.\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\n#[pyclass(extends=WeakRefSupport)]\nstruct InheritWeakRef {\n    _value: usize,\n}\n\n#[test]\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\nfn inherited_weakref() {\n    Python::attach(|py| {\n        let inst = Py::new(\n            py,\n            (\n                InheritWeakRef { _value: 0 },\n                WeakRefSupport {\n                    _pad: *b\"DEADBEEFDEADBEEFDEADBEEFDEADBEEF\",\n                },\n            ),\n        )\n        .unwrap();\n        py_run!(\n            py,\n            inst,\n            \"import weakref; assert weakref.ref(inst)() is inst\"\n        );\n    });\n}\n\n#[test]\nfn access_frozen_class_without_gil() {\n    use std::sync::atomic::{AtomicUsize, Ordering};\n\n    #[pyclass(frozen)]\n    struct FrozenCounter {\n        value: AtomicUsize,\n    }\n\n    let py_counter: Py<FrozenCounter> = Python::attach(|py| {\n        let counter = FrozenCounter {\n            value: AtomicUsize::new(0),\n        };\n\n        let cell = Bound::new(py, counter).unwrap();\n\n        cell.get().value.fetch_add(1, Ordering::Relaxed);\n\n        cell.into()\n    });\n\n    assert_eq!(py_counter.get().value.load(Ordering::Relaxed), 1);\n\n    Python::attach(move |_py| drop(py_counter));\n}\n\n#[test]\n#[cfg(Py_3_8)]\n#[cfg_attr(target_arch = \"wasm32\", ignore)]\nfn drop_unsendable_elsewhere() {\n    use std::sync::{\n        atomic::{AtomicBool, Ordering},\n        Arc,\n    };\n    use std::thread::spawn;\n    use test_utils::UnraisableCapture;\n\n    #[pyclass(unsendable)]\n    struct Unsendable {\n        dropped: Arc<AtomicBool>,\n    }\n\n    impl Drop for Unsendable {\n        fn drop(&mut self) {\n            self.dropped.store(true, Ordering::SeqCst);\n        }\n    }\n\n    Python::attach(|py| {\n        let (err, object) = UnraisableCapture::enter(py, |capture| {\n            let dropped = Arc::new(AtomicBool::new(false));\n\n            let unsendable = Py::new(\n                py,\n                Unsendable {\n                    dropped: dropped.clone(),\n                },\n            )\n            .unwrap();\n\n            py.detach(|| {\n                spawn(move || {\n                    Python::attach(move |py| {\n                        drop(unsendable);\n                        // On the free-threaded build, dropping an object on its non-origin thread\n                        // will not immediately drop it because the refcounts need to be merged.\n                        //\n                        // Force GC to ensure the drop happens now on the wrong thread.\n                        py.run(c\"import gc; gc.collect()\", None, None).unwrap();\n                    });\n                })\n                .join()\n                .unwrap();\n            });\n\n            assert!(!dropped.load(Ordering::SeqCst));\n\n            capture.take_capture().unwrap()\n        });\n\n        assert_eq!(err.to_string(), \"RuntimeError: test_class_basics::drop_unsendable_elsewhere::Unsendable is unsendable, but is being dropped on another thread\");\n        assert!(object.is_none());\n    });\n}\n\n#[test]\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\nfn test_unsendable_dict() {\n    #[pyclass(dict, unsendable)]\n    struct UnsendableDictClass {}\n\n    #[pymethods]\n    impl UnsendableDictClass {\n        #[new]\n        fn new() -> Self {\n            UnsendableDictClass {}\n        }\n    }\n\n    Python::attach(|py| {\n        let inst = Py::new(py, UnsendableDictClass {}).unwrap();\n        py_run!(py, inst, \"assert inst.__dict__ == {}\");\n    });\n}\n\n#[test]\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\nfn test_unsendable_dict_with_weakref() {\n    #[pyclass(dict, unsendable, weakref)]\n    struct UnsendableDictClassWithWeakRef {}\n\n    #[pymethods]\n    impl UnsendableDictClassWithWeakRef {\n        #[new]\n        fn new() -> Self {\n            Self {}\n        }\n    }\n\n    Python::attach(|py| {\n        let inst = Py::new(py, UnsendableDictClassWithWeakRef {}).unwrap();\n        py_run!(py, inst, \"assert inst.__dict__ == {}\");\n        py_run!(\n            py,\n            inst,\n            \"import weakref; assert weakref.ref(inst)() is inst; inst.a = 1; assert inst.a == 1\"\n        );\n    });\n}\n\n#[cfg(Py_3_9)]\n#[pyclass(generic)]\nstruct ClassWithRuntimeParametrization {\n    #[pyo3(get, set)]\n    value: Py<PyAny>,\n}\n\n#[cfg(Py_3_9)]\n#[pymethods]\nimpl ClassWithRuntimeParametrization {\n    #[new]\n    fn new(value: Py<PyAny>) -> ClassWithRuntimeParametrization {\n        Self { value }\n    }\n}\n\n#[test]\n#[cfg(Py_3_9)]\nfn test_runtime_parametrization() {\n    Python::attach(|py| {\n        let ty = py.get_type::<ClassWithRuntimeParametrization>();\n        py_assert!(py, ty, \"ty[int] == ty.__class_getitem__((int,))\");\n        py_run!(\n            py,\n            ty,\n            \"import types;\n            assert ty.__class_getitem__((int,)) == types.GenericAlias(ty, (int,))\"\n        );\n    });\n}\n"
  },
  {
    "path": "tests/test_class_comparisons.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\n\nmod test_utils;\n\n#[pyclass(eq, skip_from_py_object)]\n#[derive(Debug, Clone, PartialEq)]\npub enum MyEnum {\n    Variant,\n    OtherVariant,\n}\n\n#[pyclass(eq, ord, skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone, PartialOrd)]\npub enum MyEnumOrd {\n    Variant,\n    OtherVariant,\n}\n\n#[test]\nfn test_enum_eq_enum() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, MyEnum::Variant).unwrap();\n        let var2 = Py::new(py, MyEnum::Variant).unwrap();\n        let other_var = Py::new(py, MyEnum::OtherVariant).unwrap();\n        py_assert!(py, var1 var2, \"var1 == var2\");\n        py_assert!(py, var1 other_var, \"var1 != other_var\");\n        py_assert!(py, var1 var2, \"(var1 != var2) == False\");\n    })\n}\n\n#[test]\nfn test_enum_eq_incomparable() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, MyEnum::Variant).unwrap();\n        py_assert!(py, var1, \"(var1 == 'foo') == False\");\n        py_assert!(py, var1, \"(var1 != 'foo') == True\");\n    })\n}\n\n#[test]\nfn test_enum_ord_comparable_opt_in_only() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, MyEnum::Variant).unwrap();\n        let var2 = Py::new(py, MyEnum::OtherVariant).unwrap();\n        // ordering on simple enums if opt in only, thus raising an error below\n        py_expect_exception!(py, var1 var2, \"(var1 > var2) == False\", PyTypeError);\n    })\n}\n\n#[test]\nfn test_simple_enum_ord_comparable() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, MyEnumOrd::Variant).unwrap();\n        let var2 = Py::new(py, MyEnumOrd::OtherVariant).unwrap();\n        let var3 = Py::new(py, MyEnumOrd::OtherVariant).unwrap();\n        py_assert!(py, var1 var2, \"(var1 > var2) == False\");\n        py_assert!(py, var1 var2, \"(var1 < var2) == True\");\n        py_assert!(py, var1 var2, \"(var1 >= var2) == False\");\n        py_assert!(py, var2 var3, \"(var3 >= var2) == True\");\n        py_assert!(py, var1 var2, \"(var1 <= var2) == True\");\n    })\n}\n\n#[pyclass(eq, ord, skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone, PartialOrd)]\npub enum MyComplexEnumOrd {\n    Variant(i32),\n    OtherVariant(String),\n}\n\n#[pyclass(eq, ord, skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone, PartialOrd)]\npub enum MyComplexEnumOrd2 {\n    Variant { msg: String, idx: u32 },\n    OtherVariant { name: String, idx: u32 },\n}\n\n#[test]\nfn test_complex_enum_ord_comparable() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, MyComplexEnumOrd::Variant(-2)).unwrap();\n        let var2 = Py::new(py, MyComplexEnumOrd::Variant(5)).unwrap();\n        let var3 = Py::new(py, MyComplexEnumOrd::OtherVariant(\"a\".to_string())).unwrap();\n        let var4 = Py::new(py, MyComplexEnumOrd::OtherVariant(\"b\".to_string())).unwrap();\n        py_assert!(py, var1 var2, \"(var1 > var2) == False\");\n        py_assert!(py, var1 var2, \"(var1 < var2) == True\");\n        py_assert!(py, var1 var2, \"(var1 >= var2) == False\");\n        py_assert!(py, var1 var2, \"(var1 <= var2) == True\");\n\n        py_assert!(py, var1 var3, \"(var1 >= var3) == False\");\n        py_assert!(py, var1 var3, \"(var1 <= var3) == True\");\n\n        py_assert!(py, var3 var4, \"(var3 >= var4) == False\");\n        py_assert!(py, var3 var4, \"(var3 <= var4) == True\");\n\n        let var5 = Py::new(\n            py,\n            MyComplexEnumOrd2::Variant {\n                msg: \"hello\".to_string(),\n                idx: 1,\n            },\n        )\n        .unwrap();\n        let var6 = Py::new(\n            py,\n            MyComplexEnumOrd2::Variant {\n                msg: \"hello\".to_string(),\n                idx: 1,\n            },\n        )\n        .unwrap();\n        let var7 = Py::new(\n            py,\n            MyComplexEnumOrd2::Variant {\n                msg: \"goodbye\".to_string(),\n                idx: 7,\n            },\n        )\n        .unwrap();\n        let var8 = Py::new(\n            py,\n            MyComplexEnumOrd2::Variant {\n                msg: \"about\".to_string(),\n                idx: 0,\n            },\n        )\n        .unwrap();\n        let var9 = Py::new(\n            py,\n            MyComplexEnumOrd2::OtherVariant {\n                name: \"albert\".to_string(),\n                idx: 1,\n            },\n        )\n        .unwrap();\n\n        py_assert!(py, var5 var6, \"(var5 == var6) == True\");\n        py_assert!(py, var5 var6, \"(var5 <= var6) == True\");\n        py_assert!(py, var6 var7, \"(var6 <= var7) == False\");\n        py_assert!(py, var6 var7, \"(var6 >= var7) == True\");\n        py_assert!(py, var5 var8, \"(var5 > var8) == True\");\n        py_assert!(py, var8 var9, \"(var9 > var8) == True\");\n    })\n}\n\n#[pyclass(eq, ord, skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone, PartialOrd)]\npub struct Point {\n    x: i32,\n    y: i32,\n    z: i32,\n}\n\n#[test]\nfn test_struct_numeric_ord_comparable() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, Point { x: 10, y: 2, z: 3 }).unwrap();\n        let var2 = Py::new(py, Point { x: 2, y: 2, z: 3 }).unwrap();\n        let var3 = Py::new(py, Point { x: 1, y: 22, z: 4 }).unwrap();\n        let var4 = Py::new(py, Point { x: 1, y: 3, z: 4 }).unwrap();\n        let var5 = Py::new(py, Point { x: 1, y: 3, z: 4 }).unwrap();\n        py_assert!(py, var1 var2, \"(var1 > var2) == True\");\n        py_assert!(py, var1 var2, \"(var1 <= var2) == False\");\n        py_assert!(py, var2 var3, \"(var3 < var2) == True\");\n        py_assert!(py, var3 var4, \"(var3 > var4) == True\");\n        py_assert!(py, var4 var5, \"(var4 == var5) == True\");\n        py_assert!(py, var3 var5, \"(var3 != var5) == True\");\n    })\n}\n\n#[pyclass(eq, ord, skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone, PartialOrd)]\npub struct Person {\n    surname: String,\n    given_name: String,\n}\n\n#[test]\nfn test_struct_string_ord_comparable() {\n    Python::attach(|py| {\n        let var1 = Py::new(\n            py,\n            Person {\n                surname: \"zzz\".to_string(),\n                given_name: \"bob\".to_string(),\n            },\n        )\n        .unwrap();\n        let var2 = Py::new(\n            py,\n            Person {\n                surname: \"aaa\".to_string(),\n                given_name: \"sally\".to_string(),\n            },\n        )\n        .unwrap();\n        let var3 = Py::new(\n            py,\n            Person {\n                surname: \"eee\".to_string(),\n                given_name: \"qqq\".to_string(),\n            },\n        )\n        .unwrap();\n        let var4 = Py::new(\n            py,\n            Person {\n                surname: \"ddd\".to_string(),\n                given_name: \"aaa\".to_string(),\n            },\n        )\n        .unwrap();\n\n        py_assert!(py, var1 var2, \"(var1 > var2) == True\");\n        py_assert!(py, var1 var2, \"(var1 <= var2) == False\");\n        py_assert!(py, var1 var3, \"(var1 >= var3) == True\");\n        py_assert!(py, var2 var3, \"(var2 >= var3) == False\");\n        py_assert!(py, var3 var4, \"(var3 >= var4) == True\");\n        py_assert!(py, var3 var4, \"(var3 != var4) == True\");\n    })\n}\n\n#[pyclass(eq, ord, skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone)]\npub struct Record {\n    name: String,\n    title: String,\n    idx: u32,\n}\n\nimpl PartialOrd for Record {\n    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {\n        Some(self.idx.partial_cmp(&other.idx).unwrap())\n    }\n}\n\n#[test]\nfn test_struct_custom_ord_comparable() {\n    Python::attach(|py| {\n        let var1 = Py::new(\n            py,\n            Record {\n                name: \"zzz\".to_string(),\n                title: \"bbb\".to_string(),\n                idx: 9,\n            },\n        )\n        .unwrap();\n        let var2 = Py::new(\n            py,\n            Record {\n                name: \"ddd\".to_string(),\n                title: \"aaa\".to_string(),\n                idx: 1,\n            },\n        )\n        .unwrap();\n        let var3 = Py::new(\n            py,\n            Record {\n                name: \"vvv\".to_string(),\n                title: \"ggg\".to_string(),\n                idx: 19,\n            },\n        )\n        .unwrap();\n        let var4 = Py::new(\n            py,\n            Record {\n                name: \"vvv\".to_string(),\n                title: \"ggg\".to_string(),\n                idx: 19,\n            },\n        )\n        .unwrap();\n\n        py_assert!(py, var1 var2, \"(var1 > var2) == True\");\n        py_assert!(py, var1 var2, \"(var1 <= var2) == False\");\n        py_assert!(py, var1 var3, \"(var1 >= var3) == False\");\n        py_assert!(py, var2 var3, \"(var2 >= var3) == False\");\n        py_assert!(py, var3 var4, \"(var3 == var4) == True\");\n        py_assert!(py, var2 var4, \"(var2 != var4) == True\");\n    })\n}\n"
  },
  {
    "path": "tests/test_class_conversion.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\n\n#[macro_use]\nmod test_utils;\n\n#[pyclass(from_py_object)]\n#[derive(Clone, Debug, PartialEq)]\nstruct Cloneable {\n    x: i32,\n}\n\n#[test]\nfn test_cloneable_pyclass() {\n    let c = Cloneable { x: 10 };\n\n    Python::attach(|py| {\n        let py_c = Py::new(py, c.clone()).unwrap();\n\n        let c2: Cloneable = py_c.extract(py).unwrap();\n        assert_eq!(c, c2);\n        {\n            let rc: PyRef<'_, Cloneable> = py_c.extract(py).unwrap();\n            assert_eq!(&c, &*rc);\n            // Drops PyRef before taking PyRefMut\n        }\n        let mrc: PyRefMut<'_, Cloneable> = py_c.extract(py).unwrap();\n        assert_eq!(&c, &*mrc);\n    });\n}\n\n#[pyclass(subclass)]\n#[derive(Default)]\nstruct BaseClass {\n    value: i32,\n}\n\n#[pymethods]\nimpl BaseClass {\n    fn foo(&self) -> &'static str {\n        \"BaseClass\"\n    }\n}\n\n#[pyclass(extends=BaseClass)]\nstruct SubClass {}\n\n#[pymethods]\nimpl SubClass {\n    fn foo(&self) -> &'static str {\n        \"SubClass\"\n    }\n}\n\n#[pyclass]\nstruct PolymorphicContainer {\n    #[pyo3(get, set)]\n    inner: Py<BaseClass>,\n}\n\n#[test]\nfn test_polymorphic_container_stores_base_class() {\n    Python::attach(|py| {\n        let p = Py::new(\n            py,\n            PolymorphicContainer {\n                inner: Py::new(py, BaseClass::default()).unwrap(),\n            },\n        )\n        .unwrap();\n\n        py_assert!(py, p, \"p.inner.foo() == 'BaseClass'\");\n    });\n}\n\n#[test]\nfn test_polymorphic_container_stores_sub_class() {\n    Python::attach(|py| {\n        let p = Py::new(\n            py,\n            PolymorphicContainer {\n                inner: Py::new(py, BaseClass::default()).unwrap(),\n            },\n        )\n        .unwrap();\n\n        p.bind(py)\n            .setattr(\n                \"inner\",\n                Py::new(\n                    py,\n                    PyClassInitializer::from(BaseClass::default()).add_subclass(SubClass {}),\n                )\n                .unwrap(),\n            )\n            .unwrap();\n\n        py_assert!(py, p, \"p.inner.foo() == 'SubClass'\");\n    });\n}\n\n#[test]\nfn test_polymorphic_container_does_not_accept_other_types() {\n    Python::attach(|py| {\n        let p = Py::new(\n            py,\n            PolymorphicContainer {\n                inner: Py::new(py, BaseClass::default()).unwrap(),\n            },\n        )\n        .unwrap();\n\n        let setattr = |value: Bound<'_, PyAny>| p.bind(py).setattr(\"inner\", value);\n\n        assert!(setattr(1i32.into_pyobject(py).unwrap().into_any()).is_err());\n        assert!(setattr(py.None().into_bound(py)).is_err());\n        assert!(setattr((1i32, 2i32).into_pyobject(py).unwrap().into_any()).is_err());\n    });\n}\n\n#[test]\nfn test_pyref_as_base() {\n    Python::attach(|py| {\n        let cell = Bound::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap();\n\n        // First try PyRefMut\n        let sub: PyRefMut<'_, SubClass> = cell.borrow_mut();\n        let mut base: PyRefMut<'_, BaseClass> = sub.into_super();\n        assert_eq!(120, base.value);\n        base.value = 999;\n        assert_eq!(999, base.value);\n        drop(base);\n\n        // Repeat for PyRef\n        let sub: PyRef<'_, SubClass> = cell.borrow();\n        let base: PyRef<'_, BaseClass> = sub.into_super();\n        assert_eq!(999, base.value);\n    });\n}\n\n#[test]\nfn test_pycell_deref() {\n    Python::attach(|py| {\n        let obj = Bound::new(py, (SubClass {}, BaseClass { value: 120 })).unwrap();\n\n        // Should be able to deref as PyAny\n        assert_eq!(\n            obj.call_method0(\"foo\")\n                .and_then(|e| e.extract::<String>())\n                .unwrap(),\n            \"SubClass\"\n        );\n    });\n}\n"
  },
  {
    "path": "tests/test_class_formatting.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\nuse pyo3::py_run;\nuse std::fmt::{Display, Formatter};\n\nmod test_utils;\n\n#[pyclass(eq, str)]\n#[derive(Debug, PartialEq)]\npub enum MyEnum2 {\n    Variant,\n    OtherVariant,\n}\n\nimpl Display for MyEnum2 {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{self:?}\")\n    }\n}\n\n#[pyclass(eq, str)]\n#[derive(Debug, PartialEq)]\npub enum MyEnum3 {\n    #[pyo3(name = \"AwesomeVariant\")]\n    Variant,\n    OtherVariant,\n}\n\nimpl Display for MyEnum3 {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        let variant = match self {\n            MyEnum3::Variant => \"AwesomeVariant\",\n            MyEnum3::OtherVariant => \"OtherVariant\",\n        };\n        write!(f, \"MyEnum.{variant}\")\n    }\n}\n\n#[test]\nfn test_enum_class_fmt() {\n    Python::attach(|py| {\n        let var2 = Py::new(py, MyEnum2::Variant).unwrap();\n        let var3 = Py::new(py, MyEnum3::Variant).unwrap();\n        let var4 = Py::new(py, MyEnum3::OtherVariant).unwrap();\n        py_assert!(py, var2, \"str(var2) == 'Variant'\");\n        py_assert!(py, var3, \"str(var3) == 'MyEnum.AwesomeVariant'\");\n        py_assert!(py, var4, \"str(var4) == 'MyEnum.OtherVariant'\");\n    })\n}\n\n#[pyclass(str = \"X: {x}, Y: {y}, Z: {z}\", skip_from_py_object)]\n#[derive(PartialEq, Eq, Clone, PartialOrd)]\npub struct Point {\n    x: i32,\n    y: i32,\n    z: i32,\n}\n\n#[test]\nfn test_custom_struct_custom_str() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, Point { x: 1, y: 2, z: 3 }).unwrap();\n        py_assert!(py, var1, \"str(var1) == 'X: 1, Y: 2, Z: 3'\");\n    })\n}\n\n#[pyclass(str, skip_from_py_object)]\n#[derive(PartialEq, Eq, Clone, PartialOrd)]\npub struct Point2 {\n    x: i32,\n    y: i32,\n    z: i32,\n}\n\nimpl Display for Point2 {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"({}, {}, {})\", self.x, self.y, self.z)\n    }\n}\n\n#[test]\nfn test_struct_str() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, Point2 { x: 1, y: 2, z: 3 }).unwrap();\n        py_assert!(py, var1, \"str(var1) == '(1, 2, 3)'\");\n    })\n}\n\n#[pyclass(str)]\n#[derive(PartialEq, Debug)]\nenum ComplexEnumWithStr {\n    A(u32),\n    B { msg: String },\n}\n\nimpl Display for ComplexEnumWithStr {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{self:?}\")\n    }\n}\n\n#[test]\nfn test_custom_complex_enum_str() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, ComplexEnumWithStr::A(45)).unwrap();\n        let var2 = Py::new(\n            py,\n            ComplexEnumWithStr::B {\n                msg: \"Hello\".to_string(),\n            },\n        )\n        .unwrap();\n        py_assert!(py, var1, \"str(var1) == 'A(45)'\");\n        py_assert!(py, var2, \"str(var2) == 'B { msg: \\\"Hello\\\" }'\");\n    })\n}\n\n#[pyclass(str = \"{0}, {1}, {2}\")]\n#[derive(PartialEq)]\nstruct Coord(u32, u32, u32);\n\n#[pyclass(str = \"{{{0}, {1}, {2}}}\")]\n#[derive(PartialEq)]\nstruct Coord2(u32, u32, u32);\n\n#[test]\nfn test_str_representation_by_position() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, Coord(1, 2, 3)).unwrap();\n        let var2 = Py::new(py, Coord2(1, 2, 3)).unwrap();\n        py_assert!(py, var1, \"str(var1) == '1, 2, 3'\");\n        py_assert!(py, var2, \"str(var2) == '{1, 2, 3}'\");\n    })\n}\n\n#[pyclass(str = \"name: {name}: {name}, idn: {idn:03} with message: {msg}\")]\n#[derive(PartialEq, Debug)]\nstruct Point4 {\n    name: String,\n    msg: String,\n    idn: u32,\n}\n\n#[test]\nfn test_mixed_and_repeated_str_formats() {\n    Python::attach(|py| {\n        let var1 = Py::new(\n            py,\n            Point4 {\n                name: \"aaa\".to_string(),\n                msg: \"hello\".to_string(),\n                idn: 1,\n            },\n        )\n        .unwrap();\n        py_run!(\n            py,\n            var1,\n            r#\"\n        assert str(var1) == 'name: aaa: aaa, idn: 001 with message: hello'\n        \"#\n        );\n    })\n}\n\n#[pyclass(str = \"type: {r#type}\")]\nstruct Foo {\n    r#type: u32,\n}\n\n#[test]\nfn test_raw_identifier_struct_custom_str() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, Foo { r#type: 3 }).unwrap();\n        py_assert!(py, var1, \"str(var1) == 'type: 3'\");\n    })\n}\n"
  },
  {
    "path": "tests/test_class_init.rs",
    "content": "#![cfg(feature = \"macros\")]\r\n\r\nuse pyo3::prelude::*;\r\n\r\n#[pyclass(subclass)]\r\nstruct Base {\r\n    num: u32,\r\n}\r\n\r\n#[pymethods]\r\nimpl Base {\r\n    #[new]\r\n    fn new() -> Self {\r\n        Self { num: 0 }\r\n    }\r\n\r\n    fn __init__(&mut self) {\r\n        self.num += 42\r\n    }\r\n}\r\n\r\n#[test]\r\nfn test_base_init() {\r\n    Python::attach(|py| {\r\n        let typeobj = py.get_type::<Base>();\r\n        let obj = typeobj.call((), None).unwrap().cast_into::<Base>().unwrap();\r\n        // check __init__ was called\r\n        assert_eq!(obj.borrow().num, 42);\r\n    });\r\n}\r\n\r\n#[pyclass(extends=Base)]\r\nstruct SubWithoutInit;\r\n\r\n#[pymethods]\r\nimpl SubWithoutInit {\r\n    #[new]\r\n    fn new() -> (Self, Base) {\r\n        (Self, Base::new())\r\n    }\r\n}\r\n\r\n#[test]\r\nfn test_subclass_without_init_calls_base_init() {\r\n    Python::attach(|py| {\r\n        let typeobj = py.get_type::<SubWithoutInit>();\r\n        let obj = typeobj\r\n            .call((), None)\r\n            .unwrap()\r\n            .cast_into::<SubWithoutInit>()\r\n            .unwrap();\r\n        // check Base.__init__ was called\r\n        assert_eq!(obj.as_super().borrow().num, 42);\r\n    });\r\n}\r\n\r\n#[pyclass(extends=Base)]\r\nstruct SubWithInit;\r\n\r\n#[pymethods]\r\nimpl SubWithInit {\r\n    #[new]\r\n    fn new() -> (Self, Base) {\r\n        (Self, Base::new())\r\n    }\r\n\r\n    fn __init__(mut slf: pyo3::PyClassGuardMut<'_, Self>) {\r\n        slf.as_super().__init__(); // need to call super __init__ manually\r\n        slf.as_super().num += 1;\r\n    }\r\n}\r\n\r\n#[test]\r\nfn test_subclass_with_init() {\r\n    Python::attach(|py| {\r\n        let typeobj = py.get_type::<SubWithInit>();\r\n        let obj = typeobj\r\n            .call((), None)\r\n            .unwrap()\r\n            .cast_into::<SubWithInit>()\r\n            .unwrap();\r\n        // check SubWithInit.__init__ was called, and Base.__init__ was only called once (through\r\n        // SubWithInit.__init__)\r\n        assert_eq!(obj.as_super().borrow().num, 43);\r\n    });\r\n}\r\n"
  },
  {
    "path": "tests/test_class_new.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::exceptions::PyValueError;\nuse pyo3::prelude::*;\nuse pyo3::sync::PyOnceLock;\nuse pyo3::types::IntoPyDict;\n\n#[pyclass]\nstruct EmptyClassWithNew {}\n\n#[pymethods]\nimpl EmptyClassWithNew {\n    #[new]\n    fn new() -> EmptyClassWithNew {\n        EmptyClassWithNew {}\n    }\n}\n\n#[test]\nfn empty_class_with_new() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<EmptyClassWithNew>();\n        assert!(typeobj\n            .call((), None)\n            .unwrap()\n            .cast::<EmptyClassWithNew>()\n            .is_ok());\n\n        // Calling with arbitrary args or kwargs is not ok\n        assert!(typeobj.call((\"some\", \"args\"), None).is_err());\n        assert!(typeobj\n            .call((), Some(&[(\"some\", \"kwarg\")].into_py_dict(py).unwrap()))\n            .is_err());\n    });\n}\n\n#[pyclass]\nstruct UnitClassWithNew;\n\n#[pymethods]\nimpl UnitClassWithNew {\n    #[new]\n    fn new() -> Self {\n        Self\n    }\n}\n\n#[test]\nfn unit_class_with_new() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<UnitClassWithNew>();\n        assert!(typeobj\n            .call((), None)\n            .unwrap()\n            .cast::<UnitClassWithNew>()\n            .is_ok());\n    });\n}\n\n#[pyclass]\nstruct TupleClassWithNew(i32);\n\n#[pymethods]\nimpl TupleClassWithNew {\n    #[new]\n    fn new(arg: i32) -> Self {\n        Self(arg)\n    }\n}\n\n#[test]\nfn tuple_class_with_new() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<TupleClassWithNew>();\n        let wrp = typeobj.call((42,), None).unwrap();\n        let obj = wrp.cast::<TupleClassWithNew>().unwrap();\n        let obj_ref = obj.borrow();\n        assert_eq!(obj_ref.0, 42);\n    });\n}\n\n#[pyclass]\n#[derive(Debug)]\nstruct NewWithOneArg {\n    data: i32,\n}\n\n#[pymethods]\nimpl NewWithOneArg {\n    #[new]\n    fn new(arg: i32) -> NewWithOneArg {\n        NewWithOneArg { data: arg }\n    }\n}\n\n#[test]\nfn new_with_one_arg() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<NewWithOneArg>();\n        let wrp = typeobj.call((42,), None).unwrap();\n        let obj = wrp.cast::<NewWithOneArg>().unwrap();\n        let obj_ref = obj.borrow();\n        assert_eq!(obj_ref.data, 42);\n    });\n}\n\n#[pyclass]\nstruct NewWithTwoArgs {\n    data1: i32,\n    data2: i32,\n}\n\n#[pymethods]\nimpl NewWithTwoArgs {\n    #[new]\n    fn new(arg1: i32, arg2: i32) -> Self {\n        NewWithTwoArgs {\n            data1: arg1,\n            data2: arg2,\n        }\n    }\n}\n\n#[test]\nfn new_with_two_args() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<NewWithTwoArgs>();\n        let wrp = typeobj\n            .call((10, 20), None)\n            .map_err(|e| e.display(py))\n            .unwrap();\n        let obj = wrp.cast::<NewWithTwoArgs>().unwrap();\n        let obj_ref = obj.borrow();\n        assert_eq!(obj_ref.data1, 10);\n        assert_eq!(obj_ref.data2, 20);\n    });\n}\n\n#[pyclass(subclass)]\nstruct SuperClass {\n    #[pyo3(get)]\n    from_rust: bool,\n}\n\n#[pymethods]\nimpl SuperClass {\n    #[new]\n    fn new() -> Self {\n        SuperClass { from_rust: true }\n    }\n}\n\n/// Checks that `subclass.__new__` works correctly.\n/// See https://github.com/PyO3/pyo3/issues/947 for the corresponding bug.\n#[test]\nfn subclass_new() {\n    Python::attach(|py| {\n        let super_cls = py.get_type::<SuperClass>();\n        let source = pyo3_ffi::c_str!(\n            r#\"\nclass Class(SuperClass):\n    def __new__(cls):\n        return super().__new__(cls)  # This should return an instance of Class\n\n    @property\n    def from_rust(self):\n        return False\nc = Class()\nassert c.from_rust is False\n\"#\n        );\n        let globals = PyModule::import(py, \"__main__\").unwrap().dict();\n        globals.set_item(\"SuperClass\", super_cls).unwrap();\n        py.run(source, Some(&globals), None)\n            .map_err(|e| e.display(py))\n            .unwrap();\n    });\n}\n\n#[pyclass]\n#[derive(Debug)]\nstruct NewWithCustomError {}\n\nstruct CustomError;\n\nimpl From<CustomError> for PyErr {\n    fn from(_error: CustomError) -> PyErr {\n        PyValueError::new_err(\"custom error\")\n    }\n}\n\n#[pymethods]\nimpl NewWithCustomError {\n    #[new]\n    fn new() -> Result<NewWithCustomError, CustomError> {\n        Err(CustomError)\n    }\n}\n\n#[test]\nfn new_with_custom_error() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<NewWithCustomError>();\n        let err = typeobj.call0().unwrap_err();\n        assert_eq!(err.to_string(), \"ValueError: custom error\");\n    });\n}\n\n#[pyclass]\nstruct NewExisting {\n    #[pyo3(get)]\n    num: usize,\n}\n\n#[pymethods]\nimpl NewExisting {\n    #[new]\n    fn new(py: pyo3::Python<'_>, val: usize) -> pyo3::Py<NewExisting> {\n        static PRE_BUILT: PyOnceLock<[pyo3::Py<NewExisting>; 2]> = PyOnceLock::new();\n        let existing = PRE_BUILT.get_or_init(py, || {\n            [\n                pyo3::Py::new(py, NewExisting { num: 0 }).unwrap(),\n                pyo3::Py::new(py, NewExisting { num: 1 }).unwrap(),\n            ]\n        });\n\n        if val < existing.len() {\n            return existing[val].clone_ref(py);\n        }\n\n        pyo3::Py::new(py, NewExisting { num: val }).unwrap()\n    }\n}\n\n#[test]\nfn test_new_existing() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<NewExisting>();\n\n        let obj1 = typeobj.call1((0,)).unwrap();\n        let obj2 = typeobj.call1((0,)).unwrap();\n        let obj3 = typeobj.call1((1,)).unwrap();\n        let obj4 = typeobj.call1((1,)).unwrap();\n        let obj5 = typeobj.call1((2,)).unwrap();\n        let obj6 = typeobj.call1((2,)).unwrap();\n\n        assert_eq!(obj1.getattr(\"num\").unwrap().extract::<u32>().unwrap(), 0);\n        assert_eq!(obj2.getattr(\"num\").unwrap().extract::<u32>().unwrap(), 0);\n        assert_eq!(obj3.getattr(\"num\").unwrap().extract::<u32>().unwrap(), 1);\n        assert_eq!(obj4.getattr(\"num\").unwrap().extract::<u32>().unwrap(), 1);\n        assert_eq!(obj5.getattr(\"num\").unwrap().extract::<u32>().unwrap(), 2);\n        assert_eq!(obj6.getattr(\"num\").unwrap().extract::<u32>().unwrap(), 2);\n\n        assert!(obj1.is(&obj2));\n        assert!(obj3.is(&obj4));\n        assert!(!obj1.is(&obj3));\n        assert!(!obj1.is(&obj5));\n        assert!(!obj5.is(&obj6));\n    });\n}\n\n#[pyclass]\nstruct NewReturnsPy;\n\n#[pymethods]\nimpl NewReturnsPy {\n    #[new]\n    fn new(py: Python<'_>) -> PyResult<Py<NewReturnsPy>> {\n        Py::new(py, NewReturnsPy)\n    }\n}\n\n#[test]\nfn test_new_returns_py() {\n    Python::attach(|py| {\n        let type_ = py.get_type::<NewReturnsPy>();\n        let obj = type_.call0().unwrap();\n        assert!(obj.is_exact_instance_of::<NewReturnsPy>());\n    })\n}\n\n#[pyclass]\nstruct NewReturnsBound;\n\n#[pymethods]\nimpl NewReturnsBound {\n    #[new]\n    fn new(py: Python<'_>) -> PyResult<Bound<'_, NewReturnsBound>> {\n        Bound::new(py, NewReturnsBound)\n    }\n}\n\n#[test]\nfn test_new_returns_bound() {\n    Python::attach(|py| {\n        let type_ = py.get_type::<NewReturnsBound>();\n        let obj = type_.call0().unwrap();\n        assert!(obj.is_exact_instance_of::<NewReturnsBound>());\n    })\n}\n\n#[pyo3::pyclass]\nstruct NewClassMethod {\n    #[pyo3(get)]\n    cls: pyo3::Py<PyAny>,\n}\n\n#[pyo3::pymethods]\nimpl NewClassMethod {\n    #[new]\n    #[classmethod]\n    fn new(cls: &pyo3::Bound<'_, pyo3::types::PyType>) -> Self {\n        Self {\n            cls: cls.clone().into_any().unbind(),\n        }\n    }\n}\n\n#[test]\nfn test_new_class_method() {\n    pyo3::Python::attach(|py| {\n        let cls = py.get_type::<NewClassMethod>();\n        pyo3::py_run!(py, cls, \"assert cls().cls is cls\");\n    });\n}\n"
  },
  {
    "path": "tests/test_compile_error.rs",
    "content": "#![cfg(feature = \"macros\")]\n\n#[cfg(not(target_arch = \"wasm32\"))] // Not possible to invoke compiler from wasm\n#[test]\nfn test_compile_errors() {\n    let t = trybuild::TestCases::new();\n\n    t.compile_fail(\"tests/ui/deprecated_pyfn.rs\");\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    t.compile_fail(\"tests/ui/invalid_property_args.rs\");\n    t.compile_fail(\"tests/ui/invalid_proto_pymethods.rs\");\n    #[cfg(not(all(Py_LIMITED_API, not(Py_3_10))))] // to avoid PyFunctionArgument for &str\n    t.compile_fail(\"tests/ui/invalid_pyclass_args.rs\");\n    t.compile_fail(\"tests/ui/invalid_pyclass_doc.rs\");\n    t.compile_fail(\"tests/ui/invalid_pyclass_enum.rs\");\n    t.compile_fail(\"tests/ui/invalid_pyclass_init.rs\");\n    t.compile_fail(\"tests/ui/invalid_pyclass_item.rs\");\n    #[cfg(Py_3_9)]\n    t.compile_fail(\"tests/ui/invalid_pyclass_generic.rs\");\n    #[cfg(Py_3_9)]\n    t.compile_fail(\"tests/ui/pyclass_generic_enum.rs\");\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    #[cfg(not(all(Py_LIMITED_API, not(Py_3_10))))] // to avoid PyFunctionArgument for &str\n    t.compile_fail(\"tests/ui/invalid_pyfunction_argument.rs\");\n    t.compile_fail(\"tests/ui/invalid_pyfunction_definition.rs\");\n    t.compile_fail(\"tests/ui/invalid_pyfunction_signatures.rs\");\n    #[cfg(any(not(Py_LIMITED_API), Py_3_11))]\n    t.compile_fail(\"tests/ui/invalid_pymethods_buffer.rs\");\n    // The output is not stable across abi3 / not abi3 and features\n    #[cfg(all(not(Py_LIMITED_API), feature = \"full\"))]\n    t.compile_fail(\"tests/ui/invalid_pymethods_duplicates.rs\");\n    t.compile_fail(\"tests/ui/invalid_pymethod_enum.rs\");\n    t.compile_fail(\"tests/ui/invalid_pymethod_names.rs\");\n    t.compile_fail(\"tests/ui/invalid_pymodule_args.rs\");\n    t.compile_fail(\"tests/ui/invalid_pycallargs.rs\");\n    t.compile_fail(\"tests/ui/reject_generics.rs\");\n    t.compile_fail(\"tests/ui/invalid_closure.rs\");\n    t.compile_fail(\"tests/ui/pyclass_send.rs\");\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    t.compile_fail(\"tests/ui/invalid_annotation.rs\");\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    t.compile_fail(\"tests/ui/invalid_annotation_return.rs\");\n    t.compile_fail(\"tests/ui/invalid_argument_attributes.rs\");\n    t.compile_fail(\"tests/ui/invalid_intopy_derive.rs\");\n    #[cfg(not(windows))]\n    t.compile_fail(\"tests/ui/invalid_intopy_with.rs\");\n    t.compile_fail(\"tests/ui/invalid_frompy_derive.rs\");\n    t.compile_fail(\"tests/ui/static_ref.rs\");\n    t.compile_fail(\"tests/ui/wrong_aspyref_lifetimes.rs\");\n    #[cfg(not(feature = \"uuid\"))]\n    t.compile_fail(\"tests/ui/invalid_pyfunctions.rs\");\n    t.compile_fail(\"tests/ui/invalid_pymethods.rs\");\n    // output changes with async feature\n    #[cfg(all(not(Py_3_12), Py_LIMITED_API, feature = \"experimental-async\"))]\n    t.compile_fail(\"tests/ui/abi3_nativetype_inheritance.rs\");\n    #[cfg(not(feature = \"experimental-async\"))]\n    t.compile_fail(\"tests/ui/invalid_async.rs\");\n    t.compile_fail(\"tests/ui/invalid_intern_arg.rs\");\n    t.compile_fail(\"tests/ui/invalid_frozen_pyclass_borrow.rs\");\n    #[cfg(not(any(feature = \"hashbrown\", feature = \"indexmap\")))]\n    t.compile_fail(\"tests/ui/invalid_pymethod_receiver.rs\");\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    t.compile_fail(\"tests/ui/missing_intopy.rs\");\n    // adding extra error conversion impls changes the output\n    #[cfg(not(any(windows, feature = \"eyre\", feature = \"anyhow\", Py_LIMITED_API)))]\n    t.compile_fail(\"tests/ui/invalid_result_conversion.rs\");\n    t.compile_fail(\"tests/ui/not_send.rs\");\n    t.compile_fail(\"tests/ui/not_send2.rs\");\n    t.compile_fail(\"tests/ui/get_set_all.rs\");\n    t.compile_fail(\"tests/ui/traverse.rs\");\n    t.compile_fail(\"tests/ui/invalid_pymodule_in_root.rs\");\n    t.compile_fail(\"tests/ui/invalid_pymodule_glob.rs\");\n    t.compile_fail(\"tests/ui/invalid_pymodule_trait.rs\");\n    t.compile_fail(\"tests/ui/invalid_pymodule_two_pymodule_init.rs\");\n    #[cfg(all(feature = \"experimental-async\", not(feature = \"experimental-inspect\")))]\n    #[cfg(any(not(Py_LIMITED_API), Py_3_10))] // to avoid PyFunctionArgument for &str\n    t.compile_fail(\"tests/ui/invalid_cancel_handle.rs\");\n    t.pass(\"tests/ui/pymodule_missing_docs.rs\");\n    #[cfg(not(any(Py_LIMITED_API, feature = \"experimental-inspect\")))]\n    t.pass(\"tests/ui/forbid_unsafe.rs\");\n    #[cfg(all(Py_LIMITED_API, not(feature = \"experimental-async\")))]\n    // output changes with async feature\n    t.compile_fail(\"tests/ui/abi3_inheritance.rs\");\n    #[cfg(all(Py_LIMITED_API, not(Py_3_9)))]\n    t.compile_fail(\"tests/ui/abi3_weakref.rs\");\n    #[cfg(all(Py_LIMITED_API, not(Py_3_9)))]\n    t.compile_fail(\"tests/ui/abi3_dict.rs\");\n    #[cfg(not(feature = \"experimental-inspect\"))]\n    t.compile_fail(\"tests/ui/duplicate_pymodule_submodule.rs\");\n    #[cfg(all(not(Py_LIMITED_API), Py_3_11))]\n    t.compile_fail(\"tests/ui/invalid_base_class.rs\");\n    #[cfg(any(not(Py_3_10), all(not(Py_3_14), Py_LIMITED_API)))]\n    t.compile_fail(\"tests/ui/immutable_type.rs\");\n    t.pass(\"tests/ui/ambiguous_associated_items.rs\");\n    t.pass(\"tests/ui/pyclass_probe.rs\");\n    t.compile_fail(\"tests/ui/invalid_pyfunction_warn.rs\");\n    t.compile_fail(\"tests/ui/invalid_pymethods_warn.rs\");\n}\n"
  },
  {
    "path": "tests/test_coroutine.rs",
    "content": "#![cfg(feature = \"experimental-async\")]\n#![cfg(not(target_arch = \"wasm32\"))]\nuse std::{ffi::CString, task::Poll, thread, time::Duration};\n\nuse futures::{channel::oneshot, future::poll_fn, FutureExt};\n#[cfg(not(target_has_atomic = \"64\"))]\nuse portable_atomic::{AtomicBool, Ordering};\nuse pyo3::{\n    coroutine::CancelHandle,\n    prelude::*,\n    py_run,\n    types::{IntoPyDict, PyDict, PyTuple, PyType},\n};\n#[cfg(target_has_atomic = \"64\")]\nuse std::sync::atomic::{AtomicBool, Ordering};\n\nmod test_utils;\n\nfn handle_windows(test: &str) -> String {\n    let set_event_loop_policy = r#\"\n    import asyncio, sys\n    if sys.platform == \"win32\":\n        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())\n    \"#;\n    pyo3::impl_::unindent::unindent(set_event_loop_policy) + &pyo3::impl_::unindent::unindent(test)\n}\n\n#[test]\nfn noop_coroutine() {\n    #[pyfunction]\n    async fn noop() -> usize {\n        42\n    }\n    Python::attach(|py| {\n        let noop = wrap_pyfunction!(noop, py).unwrap();\n        let test = \"import asyncio; assert asyncio.run(noop()) == 42\";\n        py_run!(py, noop, &handle_windows(test));\n    })\n}\n\n#[test]\nfn test_async_function_returns_unit_none() {\n    #[pyfunction]\n    async fn returns_unit() {}\n\n    Python::attach(|py| {\n        let returns_unit = wrap_pyfunction!(returns_unit, py).unwrap();\n        let test = \"import asyncio; assert asyncio.run(returns_unit()) is None\";\n        pyo3::py_run!(py, returns_unit, &handle_windows(test));\n    });\n}\n\n#[test]\nfn test_coroutine_qualname() {\n    #[pyfunction]\n    async fn my_fn() {}\n    #[pyclass]\n    struct MyClass;\n    #[pymethods]\n    impl MyClass {\n        #[new]\n        fn new() -> Self {\n            Self\n        }\n        // TODO use &self when possible\n        async fn my_method(_self: Py<Self>) {}\n        #[classmethod]\n        async fn my_classmethod(_cls: Py<PyType>) {}\n        #[staticmethod]\n        async fn my_staticmethod() {}\n    }\n    Python::attach(|py| {\n        let test = r#\"\n        for coro, name, qualname in [\n            (my_fn(), \"my_fn\", \"my_fn\"),\n            (MyClass().my_method(), \"my_method\", \"MyClass.my_method\"),\n            #(MyClass().my_classmethod(), \"my_classmethod\", \"MyClass.my_classmethod\"),\n            (MyClass.my_staticmethod(), \"my_staticmethod\", \"MyClass.my_staticmethod\"),\n        ]:\n            assert coro.__name__ == name and coro.__qualname__ == qualname\n        \"#;\n        let locals = [\n            (\"my_fn\", wrap_pyfunction!(my_fn, py).unwrap().as_any()),\n            (\"MyClass\", py.get_type::<MyClass>().as_any()),\n        ]\n        .into_py_dict(py)\n        .unwrap();\n        py_run!(py, *locals, &handle_windows(test));\n    })\n}\n\n#[test]\nfn sleep_0_like_coroutine() {\n    #[pyfunction]\n    async fn sleep_0() -> usize {\n        let mut waken = false;\n        poll_fn(|cx| {\n            if !waken {\n                cx.waker().wake_by_ref();\n                waken = true;\n                return Poll::Pending;\n            }\n            Poll::Ready(42)\n        })\n        .await\n    }\n    Python::attach(|py| {\n        let sleep_0 = wrap_pyfunction!(sleep_0, py).unwrap();\n        let test = \"import asyncio; assert asyncio.run(sleep_0()) == 42\";\n        py_run!(py, sleep_0, &handle_windows(test));\n    })\n}\n\n#[pyfunction]\nasync fn sleep(seconds: f64) -> usize {\n    let (tx, rx) = oneshot::channel();\n    thread::spawn(move || {\n        thread::sleep(Duration::from_secs_f64(seconds));\n        tx.send(42).unwrap();\n    });\n    rx.await.unwrap()\n}\n\n#[test]\nfn sleep_coroutine() {\n    Python::attach(|py| {\n        let sleep = wrap_pyfunction!(sleep, py).unwrap();\n        let test = r#\"import asyncio; assert asyncio.run(sleep(0.1)) == 42\"#;\n        py_run!(py, sleep, &handle_windows(test));\n    })\n}\n\n#[pyfunction]\nasync fn return_tuple() -> (usize, usize) {\n    (42, 43)\n}\n\n#[test]\nfn tuple_coroutine() {\n    Python::attach(|py| {\n        let func = wrap_pyfunction!(return_tuple, py).unwrap();\n        let test = r#\"import asyncio; assert asyncio.run(func()) == (42, 43)\"#;\n        py_run!(py, func, &handle_windows(test));\n    })\n}\n\n#[test]\nfn cancelled_coroutine() {\n    Python::attach(|py| {\n        let sleep = wrap_pyfunction!(sleep, py).unwrap();\n        let test = r#\"\n        import asyncio\n        async def main():\n            task = asyncio.create_task(sleep(999))\n            await asyncio.sleep(0)\n            task.cancel()\n            await task\n        asyncio.run(main())\n        \"#;\n        let globals = PyDict::new(py);\n        globals.set_item(\"sleep\", sleep).unwrap();\n        let err = py\n            .run(\n                &CString::new(pyo3::impl_::unindent::unindent(&handle_windows(test))).unwrap(),\n                Some(&globals),\n                None,\n            )\n            .unwrap_err();\n        assert_eq!(\n            err.value(py).get_type().qualname().unwrap(),\n            \"CancelledError\"\n        );\n    })\n}\n\n#[test]\nfn coroutine_cancel_handle() {\n    #[pyfunction]\n    async fn cancellable_sleep(\n        seconds: f64,\n        #[pyo3(cancel_handle)] mut cancel: CancelHandle,\n    ) -> usize {\n        futures::select! {\n            _ = sleep(seconds).fuse() => 42,\n            _ = cancel.cancelled().fuse() => 0,\n        }\n    }\n    Python::attach(|py| {\n        let cancellable_sleep = wrap_pyfunction!(cancellable_sleep, py).unwrap();\n        let test = r#\"\n        import asyncio;\n        async def main():\n            task = asyncio.create_task(cancellable_sleep(999))\n            await asyncio.sleep(0)\n            task.cancel()\n            return await task\n        assert asyncio.run(main()) == 0\n        \"#;\n        let globals = PyDict::new(py);\n        globals\n            .set_item(\"cancellable_sleep\", cancellable_sleep)\n            .unwrap();\n        py.run(\n            &CString::new(pyo3::impl_::unindent::unindent(&handle_windows(test))).unwrap(),\n            Some(&globals),\n            None,\n        )\n        .unwrap();\n    })\n}\n\n#[test]\nfn coroutine_is_cancelled() {\n    #[pyfunction]\n    async fn sleep_loop(#[pyo3(cancel_handle)] cancel: CancelHandle) {\n        while !cancel.is_cancelled() {\n            sleep(0.001).await;\n        }\n    }\n    Python::attach(|py| {\n        let sleep_loop = wrap_pyfunction!(sleep_loop, py).unwrap();\n        let test = r#\"\n        import asyncio;\n        async def main():\n            task = asyncio.create_task(sleep_loop())\n            await asyncio.sleep(0)\n            task.cancel()\n            await task\n        asyncio.run(main())\n        \"#;\n        let globals = PyDict::new(py);\n        globals.set_item(\"sleep_loop\", sleep_loop).unwrap();\n        py.run(\n            &CString::new(pyo3::impl_::unindent::unindent(&handle_windows(test))).unwrap(),\n            Some(&globals),\n            None,\n        )\n        .unwrap();\n    })\n}\n\n#[test]\nfn coroutine_panic() {\n    #[pyfunction]\n    async fn panic() {\n        panic!(\"test panic\");\n    }\n    Python::attach(|py| {\n        let panic = wrap_pyfunction!(panic, py).unwrap();\n        let test = r#\"\n        import asyncio\n        coro = panic()\n        try:\n            asyncio.run(coro)\n        except BaseException as err:\n            assert type(err).__name__ == \"PanicException\"\n            assert str(err) == \"test panic\"\n        else:\n            assert False\n        try:\n            coro.send(None)\n        except RuntimeError as err:\n            assert str(err) == \"cannot reuse already awaited coroutine\"\n        else:\n            assert False;\n        \"#;\n        py_run!(py, panic, &handle_windows(test));\n    })\n}\n\n#[test]\nfn test_async_method_receiver() {\n    #[pyclass]\n    struct Counter(usize);\n    #[pymethods]\n    impl Counter {\n        #[new]\n        fn new() -> Self {\n            Self(0)\n        }\n        async fn get(&self, resolve: bool) -> usize {\n            if !resolve {\n                // hang the future to test borrow checking\n                std::future::pending().await\n            }\n            self.0\n        }\n        async fn incr(&mut self, resolve: bool) -> usize {\n            if !resolve {\n                // hang the future to test borrow checking\n                std::future::pending().await\n            }\n            self.0 += 1;\n            self.0\n        }\n    }\n\n    static IS_DROPPED: AtomicBool = AtomicBool::new(false);\n\n    impl Drop for Counter {\n        fn drop(&mut self) {\n            IS_DROPPED.store(true, Ordering::SeqCst);\n        }\n    }\n\n    Python::attach(|py| {\n        let test = r#\"\n        import asyncio\n\n        obj = Counter()\n\n        assert asyncio.run(obj.get(True)) == 0\n        assert asyncio.run(obj.incr(True)) == 1\n\n        for left in [obj.get, obj.incr]:\n            for right in [obj.get, obj.incr]:\n                # first future will not resolve to hold the borrow\n                coro1 = left(False)\n                coro2 = right(True)\n                try:\n                    asyncio.run(asyncio.gather(coro1, coro2))\n                except RuntimeError as err:\n                    ran = False\n                else:\n                    ran = True\n                if left is obj.incr or right is obj.incr:\n                    assert not ran, \"mutable method calls should not run concurrently with other method calls\"\n        \"#;\n        let locals = [(\"Counter\", py.get_type::<Counter>())]\n            .into_py_dict(py)\n            .unwrap();\n        py_run!(py, *locals, test);\n    });\n\n    assert!(IS_DROPPED.load(Ordering::SeqCst));\n}\n\n#[test]\nfn test_async_method_receiver_with_other_args() {\n    #[pyclass]\n    struct Value(i32);\n    #[pymethods]\n    impl Value {\n        #[new]\n        fn new() -> Self {\n            Self(0)\n        }\n        async fn get_value_plus_with(&self, v1: i32, v2: i32) -> i32 {\n            self.0 + v1 + v2\n        }\n        async fn set_value(&mut self, new_value: i32) -> i32 {\n            self.0 = new_value;\n            self.0\n        }\n    }\n\n    Python::attach(|py| {\n        let test = r#\"\n        import asyncio\n\n        v = Value()\n        assert asyncio.run(v.get_value_plus_with(3, 0)) == 3\n        assert asyncio.run(v.set_value(10)) == 10\n        assert asyncio.run(v.get_value_plus_with(1, 1)) == 12\n        \"#;\n        let locals = [(\"Value\", py.get_type::<Value>())]\n            .into_py_dict(py)\n            .unwrap();\n        py_run!(py, *locals, test);\n    });\n}\n\n#[test]\nfn test_async_fn_borrowed_values() {\n    #[pyclass]\n    struct Data {\n        value: String,\n    }\n    #[pymethods]\n    impl Data {\n        #[new]\n        fn new(value: String) -> Self {\n            Self { value }\n        }\n        async fn borrow_value(&self) -> &str {\n            &self.value\n        }\n        async fn borrow_value_or_default<'a>(&'a self, default: &'a str) -> &'a str {\n            if self.value.is_empty() {\n                default\n            } else {\n                &self.value\n            }\n        }\n    }\n    Python::attach(|py| {\n        let test = r#\"\n        import asyncio\n\n        v = Data('hello')\n        assert asyncio.run(v.borrow_value()) == 'hello'\n        assert asyncio.run(v.borrow_value_or_default('')) == 'hello'\n\n        v_empty = Data('')\n        assert asyncio.run(v_empty.borrow_value_or_default('default')) == 'default'\n        \"#;\n        let locals = [(\"Data\", py.get_type::<Data>())].into_py_dict(py).unwrap();\n        py_run!(py, *locals, test);\n    });\n}\n\n#[test]\nfn test_async_fn_class_values() {\n    #[pyclass]\n    struct Value(i32);\n\n    #[pymethods]\n    impl Value {\n        #[new]\n        fn new(x: i32) -> Self {\n            Self(x)\n        }\n\n        #[getter]\n        fn value(&self) -> i32 {\n            self.0\n        }\n    }\n\n    #[pyfunction]\n    async fn add_two_values(obj: &Value, obj2: &Value) -> Value {\n        Value(obj.0 + obj2.0)\n    }\n\n    Python::attach(|py| {\n        let test = r#\"\n        import asyncio\n\n        v1 = Value(1)\n        v2 = Value(2)\n        assert asyncio.run(add_two_values(v1, v2)).value == 3\n        \"#;\n        let locals = [\n            (\"Value\", py.get_type::<Value>().into_any()),\n            (\n                \"add_two_values\",\n                wrap_pyfunction!(add_two_values, py).unwrap().into_any(),\n            ),\n        ]\n        .into_py_dict(py)\n        .unwrap();\n        py_run!(py, *locals, test);\n    });\n}\n\n#[test]\nfn test_async_function_args_kwargs() {\n    #[pyfunction(signature = (*args, **kwargs))]\n    async fn args_kwargs(\n        args: Py<PyTuple>,\n        kwargs: Option<Py<PyDict>>,\n    ) -> (Py<PyTuple>, Option<Py<PyDict>>) {\n        (args, kwargs)\n    }\n\n    Python::attach(|py| {\n        let test = r#\"\n        import asyncio\n\n        assert asyncio.run(args_kwargs(1, 2, a=3, b=4)) == ((1, 2), {'a': 3, 'b': 4})\n        \"#;\n        let locals = [(\n            \"args_kwargs\",\n            wrap_pyfunction!(args_kwargs, py).unwrap().into_any(),\n        )]\n        .into_py_dict(py)\n        .unwrap();\n        py_run!(py, *locals, test);\n    });\n}\n"
  },
  {
    "path": "tests/test_datetime.rs",
    "content": "#![cfg(not(Py_LIMITED_API))]\n\nuse pyo3::prelude::*;\nuse pyo3::types::{IntoPyDict, PyDate, PyDateTime, PyTime, PyTzInfo};\nuse pyo3_ffi::PyDateTime_IMPORT;\nuse std::ffi::CString;\n\nfn _get_subclasses<'py>(\n    py: Python<'py>,\n    py_type: &str,\n    args: &str,\n) -> PyResult<(Bound<'py, PyAny>, Bound<'py, PyAny>, Bound<'py, PyAny>)> {\n    // Import the class from Python and create some subclasses\n    let datetime = py.import(\"datetime\")?;\n\n    let locals = [(py_type, datetime.getattr(py_type)?)]\n        .into_py_dict(py)\n        .unwrap();\n\n    let make_subclass_py = CString::new(format!(\"class Subklass({py_type}):\\n    pass\"))?;\n\n    let make_sub_subclass_py = c\"class SubSubklass(Subklass):\\n    pass\";\n\n    py.run(&make_subclass_py, None, Some(&locals))?;\n    py.run(make_sub_subclass_py, None, Some(&locals))?;\n\n    // Construct an instance of the base class\n    let obj = py.eval(\n        &CString::new(format!(\"{py_type}({args})\"))?,\n        None,\n        Some(&locals),\n    )?;\n\n    // Construct an instance of the subclass\n    let sub_obj = py.eval(\n        &CString::new(format!(\"Subklass({args})\"))?,\n        None,\n        Some(&locals),\n    )?;\n\n    // Construct an instance of the sub-subclass\n    let sub_sub_obj = py.eval(\n        &CString::new(format!(\"SubSubklass({args})\"))?,\n        None,\n        Some(&locals),\n    )?;\n\n    Ok((obj, sub_obj, sub_sub_obj))\n}\n\nmacro_rules! assert_check_exact {\n    ($check_func:ident, $check_func_exact:ident, $obj: expr) => {\n        unsafe {\n            use pyo3::ffi::*;\n            assert_ne!($check_func(($obj).as_ptr()), 0);\n            assert_ne!($check_func_exact(($obj).as_ptr()), 0);\n        }\n    };\n}\n\nmacro_rules! assert_check_only {\n    ($check_func:ident, $check_func_exact:ident, $obj: expr) => {\n        unsafe {\n            use pyo3::ffi::*;\n            assert_ne!($check_func(($obj).as_ptr()), 0);\n            assert_eq!($check_func_exact(($obj).as_ptr()), 0);\n        }\n    };\n}\n\n#[test]\nfn test_date_check() {\n    Python::attach(|py| {\n        let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, \"date\", \"2018, 1, 1\").unwrap();\n        unsafe { PyDateTime_IMPORT() }\n        assert_check_exact!(PyDate_Check, PyDate_CheckExact, obj);\n        assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_obj);\n        assert_check_only!(PyDate_Check, PyDate_CheckExact, sub_sub_obj);\n        assert!(obj.is_instance_of::<PyDate>());\n        assert!(!obj.is_instance_of::<PyTime>());\n        assert!(!obj.is_instance_of::<PyDateTime>());\n    });\n}\n\n#[test]\nfn test_time_check() {\n    Python::attach(|py| {\n        let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, \"time\", \"12, 30, 15\").unwrap();\n        unsafe { PyDateTime_IMPORT() }\n\n        assert_check_exact!(PyTime_Check, PyTime_CheckExact, obj);\n        assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_obj);\n        assert_check_only!(PyTime_Check, PyTime_CheckExact, sub_sub_obj);\n        assert!(!obj.is_instance_of::<PyDate>());\n        assert!(obj.is_instance_of::<PyTime>());\n        assert!(!obj.is_instance_of::<PyDateTime>());\n    });\n}\n\n#[test]\nfn test_datetime_check() {\n    Python::attach(|py| {\n        let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, \"datetime\", \"2018, 1, 1, 13, 30, 15\")\n            .map_err(|e| e.display(py))\n            .unwrap();\n        unsafe { PyDateTime_IMPORT() }\n\n        assert_check_only!(PyDate_Check, PyDate_CheckExact, obj);\n        assert_check_exact!(PyDateTime_Check, PyDateTime_CheckExact, obj);\n        assert_check_only!(PyDateTime_Check, PyDateTime_CheckExact, sub_obj);\n        assert_check_only!(PyDateTime_Check, PyDateTime_CheckExact, sub_sub_obj);\n        assert!(obj.is_instance_of::<PyDate>());\n        assert!(!obj.is_instance_of::<PyTime>());\n        assert!(obj.is_instance_of::<PyDateTime>());\n    });\n}\n\n#[test]\nfn test_delta_check() {\n    Python::attach(|py| {\n        let (obj, sub_obj, sub_sub_obj) = _get_subclasses(py, \"timedelta\", \"1, -3\").unwrap();\n        unsafe { PyDateTime_IMPORT() }\n\n        assert_check_exact!(PyDelta_Check, PyDelta_CheckExact, obj);\n        assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_obj);\n        assert_check_only!(PyDelta_Check, PyDelta_CheckExact, sub_sub_obj);\n    });\n}\n\n#[test]\nfn test_datetime_utc() {\n    use assert_approx_eq::assert_approx_eq;\n    use pyo3::types::PyDateTime;\n\n    Python::attach(|py| {\n        let utc = PyTzInfo::utc(py).unwrap();\n\n        let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap();\n\n        let locals = [(\"dt\", dt)].into_py_dict(py).unwrap();\n\n        let offset: f32 = py\n            .eval(c\"dt.utcoffset().total_seconds()\", None, Some(&locals))\n            .unwrap()\n            .extract()\n            .unwrap();\n        assert_approx_eq!(offset, 0f32);\n    });\n}\n\nstatic INVALID_DATES: &[(i32, u8, u8)] = &[\n    (-1, 1, 1),\n    (0, 1, 1),\n    (10000, 1, 1),\n    (2 << 30, 1, 1),\n    (2018, 0, 1),\n    (2018, 13, 1),\n    (2018, 1, 0),\n    (2017, 2, 29),\n    (2018, 1, 32),\n];\n\nstatic INVALID_TIMES: &[(u8, u8, u8, u32)] =\n    &[(25, 0, 0, 0), (255, 0, 0, 0), (0, 60, 0, 0), (0, 0, 61, 0)];\n\n#[test]\nfn test_pydate_out_of_bounds() {\n    use pyo3::types::PyDate;\n\n    Python::attach(|py| {\n        for val in INVALID_DATES {\n            let (year, month, day) = val;\n            let dt = PyDate::new(py, *year, *month, *day);\n            dt.unwrap_err();\n        }\n    });\n}\n\n#[test]\nfn test_pytime_out_of_bounds() {\n    use pyo3::types::PyTime;\n\n    Python::attach(|py| {\n        for val in INVALID_TIMES {\n            let (hour, minute, second, microsecond) = val;\n            let dt = PyTime::new(py, *hour, *minute, *second, *microsecond, None);\n            dt.unwrap_err();\n        }\n    });\n}\n\n#[test]\nfn test_pydatetime_out_of_bounds() {\n    use pyo3::types::PyDateTime;\n    use std::iter;\n\n    Python::attach(|py| {\n        let valid_time = (0, 0, 0, 0);\n        let valid_date = (2018, 1, 1);\n\n        let invalid_dates = INVALID_DATES.iter().zip(iter::repeat(&valid_time));\n        let invalid_times = iter::repeat(&valid_date).zip(INVALID_TIMES.iter());\n\n        let vals = invalid_dates.chain(invalid_times);\n\n        for val in vals {\n            let (date, time) = val;\n            let (year, month, day) = date;\n            let (hour, minute, second, microsecond) = time;\n            let dt = PyDateTime::new(\n                py,\n                *year,\n                *month,\n                *day,\n                *hour,\n                *minute,\n                *second,\n                *microsecond,\n                None,\n            );\n            dt.unwrap_err();\n        }\n    });\n}\n"
  },
  {
    "path": "tests/test_datetime_import.rs",
    "content": "#![cfg(not(Py_LIMITED_API))]\n\nuse pyo3::{prelude::*, types::PyDate};\nuse tempfile::Builder;\n\n#[test]\n#[should_panic(expected = \"module 'datetime' has no attribute 'datetime_CAPI'\")]\nfn test_bad_datetime_module_panic() {\n    // Create an empty temporary directory\n    // with an empty \"datetime\" module which we'll put on the sys.path\n    let tmpdir = Builder::new()\n        .prefix(\"pyo3_test_data_check\")\n        .tempdir()\n        .unwrap();\n    std::fs::File::create(tmpdir.path().join(\"datetime.py\")).unwrap();\n\n    Python::attach(|py: Python<'_>| {\n        let sys = py.import(\"sys\").unwrap();\n        sys.getattr(\"path\")\n            .unwrap()\n            .call_method1(\"insert\", (0, tmpdir.path().as_os_str()))\n            .unwrap();\n\n        // This should panic because the \"datetime\" module is empty\n        PyDate::new(py, 2018, 1, 1).unwrap();\n    });\n    tmpdir.close().unwrap();\n}\n"
  },
  {
    "path": "tests/test_declarative_module.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse std::sync::OnceLock;\n\nuse pyo3::create_exception;\nuse pyo3::exceptions::PyException;\nuse pyo3::prelude::*;\nuse pyo3::sync::OnceLockExt;\n\nmod test_utils;\n\nmod some_module {\n    use pyo3::create_exception;\n    use pyo3::exceptions::PyException;\n    use pyo3::prelude::*;\n\n    #[pyclass]\n    pub struct SomePyClass;\n\n    create_exception!(some_module, SomeException, PyException);\n}\n\n#[pyclass]\nstruct ValueClass {\n    value: usize,\n}\n\n#[pymethods]\nimpl ValueClass {\n    #[new]\n    fn new(value: usize) -> Self {\n        Self { value }\n    }\n}\n\n#[pyclass(module = \"module\")]\npub struct LocatedClass {}\n\n#[pyfunction]\nfn double(x: usize) -> usize {\n    x * 2\n}\n\ncreate_exception!(\n    declarative_module,\n    MyError,\n    PyException,\n    \"Some description.\"\n);\n\n#[pymodule(submodule)]\nmod external_submodule {}\n\n/// A module written using declarative syntax.\n#[pymodule]\nmod declarative_module {\n    #[pymodule_export]\n    use super::declarative_submodule;\n    #[pymodule_export]\n    // This is not a real constraint but to test cfg attribute support\n    #[cfg(not(Py_LIMITED_API))]\n    use super::LocatedClass;\n    use super::*;\n    #[pymodule_export]\n    use super::{declarative_module2, double, MyError, ValueClass as Value};\n\n    // test for #4036\n    #[pymodule_export]\n    use super::some_module::SomePyClass;\n\n    // test for #4036\n    #[pymodule_export]\n    use super::some_module::SomeException;\n\n    #[pymodule_export]\n    use super::external_submodule;\n\n    #[pymodule_export]\n    const FOO: u32 = 42;\n\n    #[pymodule_export]\n    #[cfg(Py_LIMITED_API)]\n    const BAR: &str = \"BAR\";\n\n    #[pymodule_export]\n    #[expect(non_upper_case_globals)]\n    const r#type: char = '!';\n\n    #[expect(unused)]\n    const NOT_EXPORTED: &str = \"not exported\";\n\n    #[pymodule]\n    mod inner {\n        use super::*;\n\n        #[pyfunction]\n        fn triple(x: usize) -> usize {\n            x * 3\n        }\n\n        #[pyclass(name = \"Struct\")]\n        struct Struct;\n\n        #[pymethods]\n        impl Struct {\n            #[new]\n            fn new() -> Self {\n                Self\n            }\n        }\n\n        #[pyclass(module = \"foo\")]\n        struct StructInCustomModule;\n\n        #[pyclass(eq, eq_int, name = \"Enum\")]\n        #[derive(PartialEq)]\n        enum Enum {\n            A,\n            B,\n        }\n\n        #[pyclass(eq, eq_int, module = \"foo\")]\n        #[derive(PartialEq)]\n        enum EnumInCustomModule {\n            A,\n            B,\n        }\n    }\n\n    #[pymodule]\n    #[pyo3(module = \"custom_root\")]\n    mod inner_custom_root {\n        use super::*;\n\n        #[pyclass]\n        struct Struct;\n    }\n\n    #[pyo3::prelude::pymodule]\n    mod full_path_inner {}\n\n    #[pymodule_init]\n    fn init(m: &Bound<'_, PyModule>) -> PyResult<()> {\n        m.add(\"double2\", m.getattr(\"double\")?)\n    }\n}\n\n#[pyfunction]\nfn double_value(v: &ValueClass) -> usize {\n    v.value * 2\n}\n\n#[pymodule(module = \"declarative_module\")]\nmod declarative_submodule {\n    #[pymodule_export]\n    use super::{double, double_value};\n}\n\n#[pymodule(name = \"declarative_module_renamed\")]\nmod declarative_module2 {\n    #[pymodule_export]\n    use super::double;\n}\n\nfn declarative_module(py: Python<'_>) -> &Bound<'_, PyModule> {\n    static MODULE: OnceLock<Py<PyModule>> = OnceLock::new();\n\n    MODULE\n        .get_or_init_py_attached(py, || pyo3::wrap_pymodule!(declarative_module)(py))\n        .bind(py)\n}\n\n#[test]\nfn test_declarative_module() {\n    Python::attach(|py| {\n        let m = declarative_module(py);\n        py_assert!(\n            py,\n            m,\n            \"m.__doc__ == 'A module written using declarative syntax.'\"\n        );\n\n        py_assert!(py, m, \"m.double(2) == 4\");\n        py_assert!(py, m, \"m.inner.triple(3) == 9\");\n        py_assert!(py, m, \"m.declarative_submodule.double(4) == 8\");\n        py_assert!(\n            py,\n            m,\n            \"m.declarative_submodule.double_value(m.ValueClass(1)) == 2\"\n        );\n        py_assert!(py, m, \"str(m.MyError('foo')) == 'foo'\");\n        py_assert!(py, m, \"m.declarative_module_renamed.double(2) == 4\");\n        #[cfg(Py_LIMITED_API)]\n        py_assert!(py, m, \"not hasattr(m, 'LocatedClass')\");\n        #[cfg(not(Py_LIMITED_API))]\n        py_assert!(py, m, \"hasattr(m, 'LocatedClass')\");\n        py_assert!(py, m, \"isinstance(m.inner.Struct(), m.inner.Struct)\");\n        py_assert!(py, m, \"isinstance(m.inner.Enum.A, m.inner.Enum)\");\n        py_assert!(py, m, \"hasattr(m, 'external_submodule')\");\n        py_assert!(py, m, \"m.FOO == 42\");\n        #[cfg(Py_LIMITED_API)]\n        py_assert!(py, m, \"m.BAR == 'BAR'\");\n        #[cfg(not(Py_LIMITED_API))]\n        py_assert!(py, m, \"not hasattr(m, 'BAR')\");\n        py_assert!(py, m, \"m.type == '!'\");\n        py_assert!(py, m, \"not hasattr(m, 'NOT_EXPORTED')\");\n\n        // submodule dunder name and attribute name\n        // declarative_module.inner is declared inside\n        py_assert!(py, m, \"m.inner.__name__ == 'declarative_module.inner'\");\n        py_assert!(py, m, \"'inner' in m.__dict__\");\n        py_assert!(py, m, \"'declarative_module.inner' not in m.__dict__\");\n\n        // since declarative_submodule is declared outside, but the parent module name is passed\n        py_assert!(\n            py,\n            m,\n            \"m.declarative_submodule.__name__ == 'declarative_module.declarative_submodule'\"\n        );\n        py_assert!(py, m, \"'declarative_submodule' in m.__dict__\");\n        py_assert!(\n            py,\n            m,\n            \"'declarative_module.declarative_submodule' not in m.__dict__\"\n        );\n    })\n}\n\n#[pymodule]\nmod r#type {\n    #[pymodule_export]\n    use super::double;\n}\n\n#[test]\nfn test_raw_ident_module() {\n    Python::attach(|py| {\n        let m = pyo3::wrap_pymodule!(r#type)(py).into_bound(py);\n        py_assert!(py, m, \"m.double(2) == 4\");\n    })\n}\n\n#[test]\nfn test_module_names() {\n    Python::attach(|py| {\n        let m = declarative_module(py);\n        py_assert!(\n            py,\n            m,\n            \"m.inner.Struct.__module__ == 'declarative_module.inner'\"\n        );\n        py_assert!(py, m, \"m.inner.StructInCustomModule.__module__ == 'foo'\");\n        py_assert!(\n            py,\n            m,\n            \"m.inner.Enum.__module__ == 'declarative_module.inner'\"\n        );\n        py_assert!(py, m, \"m.inner.EnumInCustomModule.__module__ == 'foo'\");\n        py_assert!(\n            py,\n            m,\n            \"m.inner_custom_root.Struct.__module__ == 'custom_root.inner_custom_root'\"\n        );\n    })\n}\n\n#[test]\nfn test_inner_module_full_path() {\n    Python::attach(|py| {\n        let m = declarative_module(py);\n        py_assert!(py, m, \"m.full_path_inner\");\n    })\n}\n"
  },
  {
    "path": "tests/test_default_impls.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\n\nmod test_utils;\n\n// Test default generated __repr__.\n#[pyclass(eq, eq_int)]\n#[derive(PartialEq)]\nenum TestDefaultRepr {\n    Var,\n}\n\n#[test]\nfn test_default_slot_exists() {\n    Python::attach(|py| {\n        let test_object = Py::new(py, TestDefaultRepr::Var).unwrap();\n        py_assert!(\n            py,\n            test_object,\n            \"repr(test_object) == 'TestDefaultRepr.Var'\"\n        );\n    })\n}\n\n#[pyclass(eq, eq_int)]\n#[derive(PartialEq)]\nenum OverrideSlot {\n    Var,\n}\n\n#[pymethods]\nimpl OverrideSlot {\n    fn __repr__(&self) -> &str {\n        \"overridden\"\n    }\n}\n\n#[test]\nfn test_override_slot() {\n    Python::attach(|py| {\n        let test_object = Py::new(py, OverrideSlot::Var).unwrap();\n        py_assert!(py, test_object, \"repr(test_object) == 'overridden'\");\n    })\n}\n"
  },
  {
    "path": "tests/test_enum.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\nuse pyo3::py_run;\nuse pyo3::types::PyString;\n\nmod test_utils;\n\n#[pyclass(eq, eq_int, from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone)]\npub enum MyEnum {\n    Variant,\n    OtherVariant,\n}\n\n#[test]\nfn test_enum_class_attr() {\n    Python::attach(|py| {\n        let my_enum = py.get_type::<MyEnum>();\n        let var = Py::new(py, MyEnum::Variant).unwrap();\n        py_assert!(py, my_enum var, \"my_enum.Variant == var\");\n    })\n}\n\n#[test]\nfn test_enum_eq_enum() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, MyEnum::Variant).unwrap();\n        let var2 = Py::new(py, MyEnum::Variant).unwrap();\n        let other_var = Py::new(py, MyEnum::OtherVariant).unwrap();\n        py_assert!(py, var1 var2, \"var1 == var2\");\n        py_assert!(py, var1 other_var, \"var1 != other_var\");\n        py_assert!(py, var1 var2, \"(var1 != var2) == False\");\n    })\n}\n\n#[test]\nfn test_enum_eq_incomparable() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, MyEnum::Variant).unwrap();\n        py_assert!(py, var1, \"(var1 == 'foo') == False\");\n        py_assert!(py, var1, \"(var1 != 'foo') == True\");\n    })\n}\n\n#[pyfunction]\nfn return_enum() -> MyEnum {\n    MyEnum::Variant\n}\n\n#[test]\nfn test_return_enum() {\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(return_enum)(py).unwrap();\n        let mynum = py.get_type::<MyEnum>();\n\n        py_run!(py, f mynum, \"assert f() == mynum.Variant\");\n        py_run!(py, f mynum, \"assert f() is mynum.Variant\");\n    });\n}\n\n#[pyfunction]\nfn enum_arg(e: MyEnum) {\n    assert_eq!(MyEnum::OtherVariant, e)\n}\n\n#[test]\nfn test_enum_arg() {\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(enum_arg)(py).unwrap();\n        let mynum = py.get_type::<MyEnum>();\n\n        py_run!(py, f mynum, \"f(mynum.OtherVariant)\")\n    })\n}\n\n#[pyclass(eq, eq_int, skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone)]\nenum CustomDiscriminant {\n    One = 1,\n    Two = 2,\n}\n\n#[test]\nfn test_custom_discriminant() {\n    Python::attach(|py| {\n        #[allow(non_snake_case)]\n        let CustomDiscriminant = py.get_type::<CustomDiscriminant>();\n        let one = Py::new(py, CustomDiscriminant::One).unwrap();\n        let two = Py::new(py, CustomDiscriminant::Two).unwrap();\n        py_run!(py, CustomDiscriminant one two, r#\"\n        assert CustomDiscriminant.One == one\n        assert CustomDiscriminant.Two == two\n        assert CustomDiscriminant.One == 1\n        assert CustomDiscriminant.Two == 2\n        assert one != two\n        assert CustomDiscriminant.One != 2\n        assert CustomDiscriminant.Two != 1\n        \"#);\n    })\n}\n\n#[test]\nfn test_enum_to_int() {\n    Python::attach(|py| {\n        let one = Py::new(py, CustomDiscriminant::One).unwrap();\n        py_assert!(py, one, \"int(one) == 1\");\n        let v = Py::new(py, MyEnum::Variant).unwrap();\n        let v_value = MyEnum::Variant as isize;\n        py_run!(py, v v_value, \"int(v) == v_value\");\n    })\n}\n\n#[test]\nfn test_enum_compare_int() {\n    Python::attach(|py| {\n        let one = Py::new(py, CustomDiscriminant::One).unwrap();\n        py_run!(\n            py,\n            one,\n            r#\"\n            assert one == 1\n            assert 1 == one\n            assert one != 2\n        \"#\n        )\n    })\n}\n\n#[pyclass(eq, eq_int, skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone)]\n#[repr(u8)]\nenum SmallEnum {\n    V = 1,\n}\n\n#[test]\nfn test_enum_compare_int_no_throw_when_overflow() {\n    Python::attach(|py| {\n        let v = Py::new(py, SmallEnum::V).unwrap();\n        py_assert!(py, v, \"v != 1<<30\")\n    })\n}\n\n#[pyclass(eq, eq_int, skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone)]\n#[repr(usize)]\n#[allow(clippy::enum_clike_unportable_variant)]\nenum BigEnum {\n    V = usize::MAX,\n}\n\n#[test]\nfn test_big_enum_no_overflow() {\n    Python::attach(|py| {\n        let usize_max = usize::MAX;\n        let v = Py::new(py, BigEnum::V).unwrap();\n\n        py_assert!(py, usize_max v, \"v == usize_max\");\n        py_assert!(py, usize_max v, \"int(v) == usize_max\");\n    })\n}\n\n#[pyclass(eq, eq_int, skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone)]\n#[repr(u16, align(8))]\nenum TestReprParse {\n    V,\n}\n\n#[test]\nfn test_repr_parse() {\n    assert_eq!(std::mem::align_of::<TestReprParse>(), 8);\n}\n\n#[pyclass(eq, eq_int, name = \"MyEnum\", skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone)]\npub enum RenameEnum {\n    Variant,\n}\n\n#[test]\nfn test_rename_enum_repr_correct() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, RenameEnum::Variant).unwrap();\n        py_assert!(py, var1, \"repr(var1) == 'MyEnum.Variant'\");\n    })\n}\n\n#[pyclass(eq, eq_int, skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone)]\npub enum RenameVariantEnum {\n    #[pyo3(name = \"VARIANT\")]\n    Variant,\n}\n\n#[test]\nfn test_rename_variant_repr_correct() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, RenameVariantEnum::Variant).unwrap();\n        py_assert!(py, var1, \"repr(var1) == 'RenameVariantEnum.VARIANT'\");\n    })\n}\n\n#[pyclass(eq, eq_int, rename_all = \"SCREAMING_SNAKE_CASE\", skip_from_py_object)]\n#[derive(Debug, PartialEq, Eq, Clone)]\n#[expect(clippy::enum_variant_names)]\nenum RenameAllVariantsEnum {\n    VariantOne,\n    VariantTwo,\n    #[pyo3(name = \"VariantThree\")]\n    VariantFour,\n}\n\n#[test]\nfn test_renaming_all_enum_variants() {\n    Python::attach(|py| {\n        let enum_obj = py.get_type::<RenameAllVariantsEnum>();\n        py_assert!(py, enum_obj, \"enum_obj.VARIANT_ONE == enum_obj.VARIANT_ONE\");\n        py_assert!(py, enum_obj, \"enum_obj.VARIANT_TWO == enum_obj.VARIANT_TWO\");\n        py_assert!(\n            py,\n            enum_obj,\n            \"enum_obj.VariantThree == enum_obj.VariantThree\"\n        );\n    });\n}\n\n#[pyclass(module = \"custom_module\")]\n#[derive(Debug)]\nenum CustomModuleComplexEnum {\n    Variant(),\n    Py(Py<PyAny>),\n}\n\n#[test]\nfn test_custom_module() {\n    Python::attach(|py| {\n        let enum_obj = py.get_type::<CustomModuleComplexEnum>();\n        py_assert!(\n            py,\n            enum_obj,\n            \"enum_obj.Variant.__module__ == 'custom_module'\"\n        );\n    });\n}\n\n#[pyclass(eq, skip_from_py_object)]\n#[derive(Debug, Clone, PartialEq)]\npub enum EqOnly {\n    VariantA,\n    VariantB,\n}\n\n#[test]\nfn test_simple_enum_eq_only() {\n    Python::attach(|py| {\n        let var1 = Py::new(py, EqOnly::VariantA).unwrap();\n        let var2 = Py::new(py, EqOnly::VariantA).unwrap();\n        let var3 = Py::new(py, EqOnly::VariantB).unwrap();\n        py_assert!(py, var1 var2, \"var1 == var2\");\n        py_assert!(py, var1 var3, \"var1 != var3\");\n    })\n}\n\n#[pyclass(frozen, eq, eq_int, hash)]\n#[derive(PartialEq, Hash)]\nenum SimpleEnumWithHash {\n    A,\n    B,\n}\n\n#[test]\nfn test_simple_enum_with_hash() {\n    Python::attach(|py| {\n        use pyo3::types::IntoPyDict;\n        let class = SimpleEnumWithHash::A;\n        let hash = {\n            use std::hash::{Hash, Hasher};\n            let mut hasher = std::collections::hash_map::DefaultHasher::new();\n            class.hash(&mut hasher);\n            hasher.finish() as isize\n        };\n\n        let env = [\n            (\"obj\", Py::new(py, class).unwrap().into_any()),\n            (\"hsh\", hash.into_pyobject(py).unwrap().into_any().unbind()),\n        ]\n        .into_py_dict(py)\n        .unwrap();\n\n        py_assert!(py, *env, \"hash(obj) == hsh\");\n    });\n}\n\n#[pyclass(eq, hash)]\n#[derive(PartialEq, Hash)]\nenum ComplexEnumWithHash {\n    A(u32),\n    B { msg: String },\n}\n\n#[test]\nfn test_complex_enum_with_hash() {\n    Python::attach(|py| {\n        use pyo3::types::IntoPyDict;\n        let class = ComplexEnumWithHash::B {\n            msg: String::from(\"Hello\"),\n        };\n        let hash = {\n            use std::hash::{Hash, Hasher};\n            let mut hasher = std::collections::hash_map::DefaultHasher::new();\n            class.hash(&mut hasher);\n            hasher.finish() as isize\n        };\n\n        let env = [\n            (\"obj\", Py::new(py, class).unwrap().into_any()),\n            (\"hsh\", hash.into_pyobject(py).unwrap().into_any().unbind()),\n        ]\n        .into_py_dict(py)\n        .unwrap();\n\n        py_assert!(py, *env, \"hash(obj) == hsh\");\n    });\n}\n\n#[test]\nfn custom_eq() {\n    #[pyclass(frozen)]\n    #[derive(PartialEq)]\n    pub enum CustomPyEq {\n        A,\n        B,\n    }\n\n    #[pymethods]\n    impl CustomPyEq {\n        fn __eq__(&self, other: &Bound<'_, PyAny>) -> bool {\n            if let Ok(rhs) = other.cast::<PyString>() {\n                rhs.to_cow().is_ok_and(|rhs| self.__str__() == rhs)\n            } else if let Ok(rhs) = other.cast::<Self>() {\n                self == rhs.get()\n            } else {\n                false\n            }\n        }\n\n        fn __str__(&self) -> String {\n            match self {\n                CustomPyEq::A => \"A\".to_string(),\n                CustomPyEq::B => \"B\".to_string(),\n            }\n        }\n    }\n\n    Python::attach(|py| {\n        let a = Bound::new(py, CustomPyEq::A).unwrap();\n        let b = Bound::new(py, CustomPyEq::B).unwrap();\n\n        assert!(a.as_any().eq(&a).unwrap());\n        assert!(a.as_any().eq(\"A\").unwrap());\n        assert!(a.as_any().ne(&b).unwrap());\n        assert!(a.as_any().ne(\"B\").unwrap());\n\n        assert!(b.as_any().eq(&b).unwrap());\n        assert!(b.as_any().eq(\"B\").unwrap());\n        assert!(b.as_any().ne(&a).unwrap());\n        assert!(b.as_any().ne(\"A\").unwrap());\n    })\n}\n\n#[pyclass(skip_from_py_object)]\n#[derive(Clone, Copy)]\npub enum ComplexEnumWithRaw {\n    Raw { r#type: i32 },\n}\n\n// Cover simple field lookups with raw identifiers\n#[test]\nfn complex_enum_with_raw() {\n    Python::attach(|py| {\n        let complex = ComplexEnumWithRaw::Raw { r#type: 314159 };\n\n        py_assert!(py, complex, \"complex.type == 314159\");\n    });\n}\n\n// Cover pattern matching with raw identifiers\n#[test]\n#[cfg(Py_3_10)]\nfn complex_enum_with_raw_pattern_match() {\n    Python::attach(|py| {\n        let complex = ComplexEnumWithRaw::Raw { r#type: 314159 };\n        let cls = py.get_type::<ComplexEnumWithRaw>();\n\n        // Cover destructuring by pattern matching\n        py_run!(py, cls complex, r#\"\n        match complex:\n            case cls.Raw(type=ty):\n                assert ty == 314159\n            case _:\n                assert False, \"no matching variant found\"\n        \"#);\n    });\n}\n\n#[test]\nfn complex_enum_variant_qualname() {\n    #[pyclass(skip_from_py_object)]\n    pub enum ComplexEnum {\n        A(i32),\n        B { msg: String },\n    }\n\n    Python::attach(|py| {\n        let cls = py.get_type::<ComplexEnum>();\n        py_assert!(py, cls, \"cls.A.__qualname__ == 'ComplexEnum.A'\");\n        py_assert!(py, cls, \"cls.B.__qualname__ == 'ComplexEnum.B'\");\n    });\n}\n\n#[test]\nfn complex_enum_renamed_variant_qualname() {\n    #[pyclass(name = \"ComplexEnum\", skip_from_py_object)]\n    pub enum PyComplexEnum {\n        #[pyo3(name = \"A\")]\n        PyA(i32),\n        B {\n            msg: String,\n        },\n    }\n\n    Python::attach(|py| {\n        let cls = py.get_type::<PyComplexEnum>();\n        py_assert!(py, cls, \"cls.A.__qualname__ == 'ComplexEnum.A'\");\n        py_assert!(py, cls, \"cls.B.__qualname__ == 'ComplexEnum.B'\");\n    });\n}\n"
  },
  {
    "path": "tests/test_exceptions.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\nuse pyo3::{exceptions, py_run};\nuse std::error::Error;\nuse std::fmt;\n#[cfg(not(target_os = \"windows\"))]\nuse std::fs::File;\n\nmod test_utils;\n\n#[pyfunction]\n#[cfg(not(target_os = \"windows\"))]\nfn fail_to_open_file() -> PyResult<()> {\n    File::open(\"not_there.txt\")?;\n    Ok(())\n}\n\n#[test]\n#[cfg_attr(target_arch = \"wasm32\", ignore)] // Not sure why this fails.\n#[cfg(not(target_os = \"windows\"))]\nfn test_filenotfounderror() {\n    Python::attach(|py| {\n        let fail_to_open_file = wrap_pyfunction!(fail_to_open_file)(py).unwrap();\n\n        py_run!(\n            py,\n            fail_to_open_file,\n            r#\"\n        try:\n            fail_to_open_file()\n        except FileNotFoundError as e:\n            assert str(e) == \"No such file or directory (os error 2)\"\n        \"#\n        );\n    });\n}\n\n#[derive(Debug)]\nstruct CustomError;\n\nimpl Error for CustomError {}\n\nimpl fmt::Display for CustomError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"Oh no!\")\n    }\n}\n\nimpl std::convert::From<CustomError> for PyErr {\n    fn from(err: CustomError) -> PyErr {\n        exceptions::PyOSError::new_err(err.to_string())\n    }\n}\n\nfn fail_with_custom_error() -> Result<(), CustomError> {\n    Err(CustomError)\n}\n\n#[pyfunction]\nfn call_fail_with_custom_error() -> PyResult<()> {\n    fail_with_custom_error()?;\n    Ok(())\n}\n\n#[test]\nfn test_custom_error() {\n    Python::attach(|py| {\n        let call_fail_with_custom_error =\n            wrap_pyfunction!(call_fail_with_custom_error)(py).unwrap();\n\n        py_run!(\n            py,\n            call_fail_with_custom_error,\n            r#\"\n        try:\n            call_fail_with_custom_error()\n        except OSError as e:\n            assert str(e) == \"Oh no!\"\n        \"#\n        );\n    });\n}\n\n#[test]\nfn test_exception_nosegfault() {\n    use std::net::TcpListener;\n    fn io_err() -> PyResult<()> {\n        TcpListener::bind(\"no:address\")?;\n        Ok(())\n    }\n    fn parse_int() -> PyResult<()> {\n        \"@_@\".parse::<i64>()?;\n        Ok(())\n    }\n    assert!(io_err().is_err());\n    assert!(parse_int().is_err());\n}\n\n#[test]\n#[cfg(Py_3_8)]\nfn test_write_unraisable() {\n    use pyo3::{exceptions::PyRuntimeError, types::PyNotImplemented};\n    use test_utils::UnraisableCapture;\n\n    Python::attach(|py| {\n        UnraisableCapture::enter(py, |capture| {\n            let err = PyRuntimeError::new_err(\"foo\");\n            err.write_unraisable(py, None);\n\n            let (err, object) = capture.take_capture().unwrap();\n\n            assert_eq!(err.to_string(), \"RuntimeError: foo\");\n            assert!(object.is_none());\n\n            let err = PyRuntimeError::new_err(\"bar\");\n            err.write_unraisable(py, Some(&PyNotImplemented::get(py)));\n\n            let (err, object) = capture.take_capture().unwrap();\n\n            assert_eq!(err.to_string(), \"RuntimeError: bar\");\n            assert!(object.is(PyNotImplemented::get(py)));\n        });\n    });\n}\n"
  },
  {
    "path": "tests/test_field_cfg.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\n\n#[pyclass]\nstruct CfgClass {\n    #[pyo3(get, set)]\n    #[cfg(any())]\n    pub a: u32,\n    #[pyo3(get, set)]\n    // This is always true\n    #[cfg(any(\n        target_family = \"unix\",\n        target_family = \"windows\",\n        target_family = \"wasm\"\n    ))]\n    pub b: u32,\n}\n\n#[pyclass(eq, eq_int)]\n#[derive(PartialEq)]\nenum CfgSimpleEnum {\n    #[cfg(any())]\n    DisabledVariant,\n    #[cfg(not(any()))]\n    EnabledVariant,\n}\n\n#[test]\nfn test_cfg() {\n    Python::attach(|py| {\n        let cfg = CfgClass { b: 3 };\n        let py_cfg = Py::new(py, cfg).unwrap();\n        assert!(py_cfg.bind(py).getattr(\"a\").is_err());\n        let b: u32 = py_cfg.bind(py).getattr(\"b\").unwrap().extract().unwrap();\n        assert_eq!(b, 3);\n    });\n}\n\n#[test]\nfn test_cfg_simple_enum() {\n    Python::attach(|py| {\n        let simple = py.get_type::<CfgSimpleEnum>();\n        pyo3::py_run!(\n            py,\n            simple,\n            r#\"\n            assert hasattr(simple, \"EnabledVariant\")\n            assert not hasattr(simple, \"DisabledVariant\")\n        \"#\n        );\n    })\n}\n"
  },
  {
    "path": "tests/test_frompy_intopy_roundtrip.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::types::{PyDict, PyString};\nuse pyo3::{prelude::*, IntoPyObject, IntoPyObjectExt, IntoPyObjectRef};\nuse std::collections::HashMap;\nuse std::hash::Hash;\n\n#[macro_use]\nmod test_utils;\n\n#[derive(Debug, Clone, IntoPyObject, IntoPyObjectRef, FromPyObject)]\npub struct A<'py> {\n    #[pyo3(item)]\n    s: String,\n    #[pyo3(item)]\n    t: Bound<'py, PyString>,\n    #[pyo3(item(\"foo\"))]\n    p: Bound<'py, PyAny>,\n}\n\n#[test]\nfn test_named_fields_struct() {\n    Python::attach(|py| {\n        let a = A {\n            s: \"Hello\".into(),\n            t: PyString::new(py, \"World\"),\n            p: 42i32.into_pyobject(py).unwrap().into_any(),\n        };\n        let pya = (&a).into_pyobject(py).unwrap();\n        let new_a = pya.extract::<A<'_>>().unwrap();\n\n        assert_eq!(a.s, new_a.s);\n        assert_eq!(a.t.to_cow().unwrap(), new_a.t.to_cow().unwrap());\n        assert_eq!(\n            a.p.extract::<i32>().unwrap(),\n            new_a.p.extract::<i32>().unwrap()\n        );\n\n        let pya = a.clone().into_pyobject(py).unwrap();\n        let new_a = pya.extract::<A<'_>>().unwrap();\n\n        assert_eq!(a.s, new_a.s);\n        assert_eq!(a.t.to_cow().unwrap(), new_a.t.to_cow().unwrap());\n        assert_eq!(\n            a.p.extract::<i32>().unwrap(),\n            new_a.p.extract::<i32>().unwrap()\n        );\n    });\n}\n\n#[derive(Debug, Clone, PartialEq, IntoPyObject, IntoPyObjectRef, FromPyObject)]\n#[pyo3(transparent)]\npub struct B {\n    test: String,\n}\n\n#[test]\nfn test_transparent_named_field_struct() {\n    Python::attach(|py| {\n        let b = B {\n            test: \"test\".into(),\n        };\n        let pyb = (&b).into_pyobject(py).unwrap();\n        let new_b = pyb.extract::<B>().unwrap();\n        assert_eq!(b, new_b);\n\n        let pyb = b.clone().into_pyobject(py).unwrap();\n        let new_b = pyb.extract::<B>().unwrap();\n        assert_eq!(b, new_b);\n    });\n}\n\n#[derive(Debug, Clone, PartialEq, IntoPyObject, IntoPyObjectRef, FromPyObject)]\n#[pyo3(transparent)]\npub struct D<T> {\n    test: T,\n}\n\n#[test]\nfn test_generic_transparent_named_field_struct() {\n    Python::attach(|py| {\n        let d = D {\n            test: String::from(\"test\"),\n        };\n        let pyd = (&d).into_pyobject(py).unwrap();\n        let new_d = pyd.extract::<D<String>>().unwrap();\n        assert_eq!(d, new_d);\n\n        let d = D { test: 1usize };\n        let pyd = (&d).into_pyobject(py).unwrap();\n        let new_d = pyd.extract::<D<usize>>().unwrap();\n        assert_eq!(d, new_d);\n\n        let d = D {\n            test: String::from(\"test\"),\n        };\n        let pyd = d.clone().into_pyobject(py).unwrap();\n        let new_d = pyd.extract::<D<String>>().unwrap();\n        assert_eq!(d, new_d);\n\n        let d = D { test: 1usize };\n        let pyd = d.clone().into_pyobject(py).unwrap();\n        let new_d = pyd.extract::<D<usize>>().unwrap();\n        assert_eq!(d, new_d);\n    });\n}\n\n#[derive(Debug, IntoPyObject, IntoPyObjectRef, FromPyObject)]\npub struct GenericWithBound<K: Hash + Eq, V>(HashMap<K, V>);\n\n#[test]\nfn test_generic_with_bound() {\n    Python::attach(|py| {\n        let mut hash_map = HashMap::<String, i32>::new();\n        hash_map.insert(\"1\".into(), 1);\n        hash_map.insert(\"2\".into(), 2);\n        let map = GenericWithBound(hash_map);\n        let py_map = (&map).into_pyobject(py).unwrap();\n        assert_eq!(py_map.len(), 2);\n        assert_eq!(\n            py_map\n                .get_item(\"1\")\n                .unwrap()\n                .unwrap()\n                .extract::<i32>()\n                .unwrap(),\n            1\n        );\n        assert_eq!(\n            py_map\n                .get_item(\"2\")\n                .unwrap()\n                .unwrap()\n                .extract::<i32>()\n                .unwrap(),\n            2\n        );\n        assert!(py_map.get_item(\"3\").unwrap().is_none());\n\n        let py_map = map.into_pyobject(py).unwrap();\n        assert_eq!(py_map.len(), 2);\n        assert_eq!(\n            py_map\n                .get_item(\"1\")\n                .unwrap()\n                .unwrap()\n                .extract::<i32>()\n                .unwrap(),\n            1\n        );\n        assert_eq!(\n            py_map\n                .get_item(\"2\")\n                .unwrap()\n                .unwrap()\n                .extract::<i32>()\n                .unwrap(),\n            2\n        );\n        assert!(py_map.get_item(\"3\").unwrap().is_none());\n    });\n}\n\n#[derive(Debug, Clone, PartialEq, IntoPyObject, IntoPyObjectRef, FromPyObject)]\npub struct Tuple(String, usize);\n\n#[test]\nfn test_tuple_struct() {\n    Python::attach(|py| {\n        let tup = Tuple(String::from(\"test\"), 1);\n        let tuple = (&tup).into_pyobject(py).unwrap();\n        let new_tup = tuple.extract::<Tuple>().unwrap();\n        assert_eq!(tup, new_tup);\n\n        let tuple = tup.clone().into_pyobject(py).unwrap();\n        let new_tup = tuple.extract::<Tuple>().unwrap();\n        assert_eq!(tup, new_tup);\n    });\n}\n\n#[derive(Debug, Clone, PartialEq, IntoPyObject, IntoPyObjectRef, FromPyObject)]\npub struct TransparentTuple(String);\n\n#[test]\nfn test_transparent_tuple_struct() {\n    Python::attach(|py| {\n        let tup = TransparentTuple(String::from(\"test\"));\n        let tuple = (&tup).into_pyobject(py).unwrap();\n        let new_tup = tuple.extract::<TransparentTuple>().unwrap();\n        assert_eq!(tup, new_tup);\n\n        let tuple = tup.clone().into_pyobject(py).unwrap();\n        let new_tup = tuple.extract::<TransparentTuple>().unwrap();\n        assert_eq!(tup, new_tup);\n    });\n}\n\n#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]\npub struct IntWrapper(u32);\n\nfn int_wrapper_into_py<'py>(\n    v: std::borrow::Cow<'_, IntWrapper>,\n    py: Python<'py>,\n) -> PyResult<Bound<'py, PyAny>> {\n    v.0.into_bound_py_any(py)\n}\n\nfn int_wrapper_from_py(v: &Bound<'_, PyAny>) -> PyResult<IntWrapper> {\n    v.extract().map(IntWrapper)\n}\n\n#[derive(Debug, Clone, PartialEq, IntoPyObject, IntoPyObjectRef, FromPyObject)]\npub enum Foo {\n    TupleVar(usize, String),\n    StructVar {\n        #[pyo3(item)]\n        test: char,\n        #[pyo3(item, into_py_with=int_wrapper_into_py, from_py_with=int_wrapper_from_py)]\n        int: IntWrapper,\n    },\n    #[pyo3(transparent)]\n    TransparentTuple(usize),\n    #[pyo3(transparent)]\n    TransparentStructVar {\n        a: Option<String>,\n    },\n    #[pyo3(rename_all = \"camelCase\", from_item_all)]\n    RenameAll {\n        long_field_name: [u16; 2],\n        other_field: Option<String>,\n    },\n}\n\n#[test]\nfn test_enum() {\n    Python::attach(|py| {\n        let tuple_var = Foo::TupleVar(1, \"test\".into());\n        let foo = (&tuple_var).into_pyobject(py).unwrap();\n        assert_eq!(tuple_var, foo.extract::<Foo>().unwrap());\n\n        let foo = tuple_var.clone().into_pyobject(py).unwrap();\n        assert_eq!(tuple_var, foo.extract::<Foo>().unwrap());\n\n        let struct_var = Foo::StructVar {\n            test: 'b',\n            int: IntWrapper(42),\n        };\n        let foo = (&struct_var)\n            .into_pyobject(py)\n            .unwrap()\n            .cast_into::<PyDict>()\n            .unwrap();\n        assert_eq!(struct_var, foo.extract::<Foo>().unwrap());\n\n        let foo = struct_var\n            .clone()\n            .into_pyobject(py)\n            .unwrap()\n            .cast_into::<PyDict>()\n            .unwrap();\n\n        assert_eq!(struct_var, foo.extract::<Foo>().unwrap());\n\n        let transparent_tuple = Foo::TransparentTuple(1);\n        let foo = (&transparent_tuple).into_pyobject(py).unwrap();\n        assert_eq!(transparent_tuple, foo.extract::<Foo>().unwrap());\n\n        let foo = transparent_tuple.clone().into_pyobject(py).unwrap();\n        assert_eq!(transparent_tuple, foo.extract::<Foo>().unwrap());\n\n        let transparent_struct_var = Foo::TransparentStructVar { a: None };\n        let foo = (&transparent_struct_var).into_pyobject(py).unwrap();\n        assert_eq!(transparent_struct_var, foo.extract::<Foo>().unwrap());\n\n        let foo = transparent_struct_var.clone().into_pyobject(py).unwrap();\n        assert_eq!(transparent_struct_var, foo.extract::<Foo>().unwrap());\n\n        let rename_all_struct_var = Foo::RenameAll {\n            long_field_name: [1, 2],\n            other_field: None,\n        };\n        let foo = (&rename_all_struct_var).into_pyobject(py).unwrap();\n        assert_eq!(rename_all_struct_var, foo.extract::<Foo>().unwrap());\n\n        let foo = rename_all_struct_var.clone().into_pyobject(py).unwrap();\n        assert_eq!(rename_all_struct_var, foo.extract::<Foo>().unwrap());\n    });\n}\n"
  },
  {
    "path": "tests/test_frompyobject.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::exceptions::PyValueError;\nuse pyo3::prelude::*;\nuse pyo3::types::{IntoPyDict, PyDict, PyList, PyString, PyTuple};\n\n#[macro_use]\nmod test_utils;\n\n/// Helper function that concatenates the error message from\n/// each error in the traceback into a single string that can\n/// be tested.\nfn extract_traceback(py: Python<'_>, mut error: PyErr) -> String {\n    let mut error_msg = error.to_string();\n    while let Some(cause) = error.cause(py) {\n        error_msg.push_str(\": \");\n        error_msg.push_str(&cause.to_string());\n        error = cause\n    }\n    error_msg\n}\n\n#[derive(Debug, FromPyObject)]\npub struct A<'py> {\n    #[pyo3(attribute)]\n    s: String,\n    #[pyo3(item)]\n    t: Bound<'py, PyString>,\n    #[pyo3(attribute(\"foo\"))]\n    p: Bound<'py, PyAny>,\n}\n\n#[pyclass]\npub struct PyA {\n    #[pyo3(get)]\n    s: String,\n    #[pyo3(get)]\n    foo: Option<String>,\n}\n\n#[pymethods]\nimpl PyA {\n    fn __getitem__(&self, key: String) -> pyo3::PyResult<String> {\n        if key == \"t\" {\n            Ok(\"bar\".into())\n        } else {\n            Err(PyValueError::new_err(\"Failed\"))\n        }\n    }\n}\n\n#[test]\nfn test_named_fields_struct() {\n    Python::attach(|py| {\n        let pya = PyA {\n            s: \"foo\".into(),\n            foo: None,\n        };\n        let py_c = Py::new(py, pya).unwrap();\n        let a = py_c\n            .extract::<A<'_>>(py)\n            .expect(\"Failed to extract A from PyA\");\n        assert_eq!(a.s, \"foo\");\n        assert_eq!(a.t.to_string_lossy(), \"bar\");\n        assert!(a.p.is_none());\n    });\n}\n\n#[derive(Debug, FromPyObject)]\n#[pyo3(transparent)]\npub struct B {\n    test: String,\n}\n\n#[test]\nfn test_transparent_named_field_struct() {\n    Python::attach(|py| {\n        let test = \"test\".into_pyobject(py).unwrap();\n        let b = test\n            .extract::<B>()\n            .expect(\"Failed to extract B from String\");\n        assert_eq!(b.test, \"test\");\n        let test = 1i32.into_pyobject(py).unwrap();\n        let b = test.extract::<B>();\n        assert!(b.is_err());\n    });\n}\n\n#[derive(Debug, FromPyObject)]\n#[pyo3(transparent)]\npub struct D<T> {\n    test: T,\n}\n\n#[test]\nfn test_generic_transparent_named_field_struct() {\n    Python::attach(|py| {\n        let test = \"test\".into_pyobject(py).unwrap();\n        let d = test\n            .extract::<D<String>>()\n            .expect(\"Failed to extract D<String> from String\");\n        assert_eq!(d.test, \"test\");\n        let test = 1usize.into_pyobject(py).unwrap();\n        let d = test\n            .extract::<D<usize>>()\n            .expect(\"Failed to extract D<usize> from String\");\n        assert_eq!(d.test, 1);\n    });\n}\n\n#[derive(Debug, FromPyObject)]\npub struct GenericWithBound<K: std::hash::Hash + Eq, V>(std::collections::HashMap<K, V>);\n\n#[test]\nfn test_generic_with_bound() {\n    Python::attach(|py| {\n        let dict = [(\"1\", 1), (\"2\", 2)].into_py_dict(py).unwrap();\n        let map = dict.extract::<GenericWithBound<String, i32>>().unwrap().0;\n        assert_eq!(map.len(), 2);\n        assert_eq!(map[\"1\"], 1);\n        assert_eq!(map[\"2\"], 2);\n        assert!(!map.contains_key(\"3\"));\n    });\n}\n\n#[derive(Debug, FromPyObject)]\npub struct E<T, T2> {\n    test: T,\n    test2: T2,\n}\n\n#[pyclass(skip_from_py_object)]\n#[derive(Clone)]\npub struct PyE {\n    #[pyo3(get)]\n    test: String,\n    #[pyo3(get)]\n    test2: usize,\n}\n\n#[test]\nfn test_generic_named_fields_struct() {\n    Python::attach(|py| {\n        let pye = PyE {\n            test: \"test\".into(),\n            test2: 2,\n        }\n        .into_pyobject(py)\n        .unwrap();\n\n        let e = pye\n            .extract::<E<String, usize>>()\n            .expect(\"Failed to extract E<String, usize> from PyE\");\n        assert_eq!(e.test, \"test\");\n        assert_eq!(e.test2, 2);\n        let e = pye.extract::<E<usize, usize>>();\n        assert!(e.is_err());\n    });\n}\n\n#[derive(Debug, FromPyObject)]\npub struct C {\n    #[pyo3(attribute(\"test\"))]\n    test: String,\n}\n\n#[test]\nfn test_named_field_with_ext_fn() {\n    Python::attach(|py| {\n        let pyc = PyE {\n            test: \"foo\".into(),\n            test2: 0,\n        }\n        .into_pyobject(py)\n        .unwrap();\n        let c = pyc.extract::<C>().expect(\"Failed to extract C from PyE\");\n        assert_eq!(c.test, \"foo\");\n    });\n}\n\n#[derive(Debug, FromPyObject)]\npub struct Tuple(String, usize);\n\n#[test]\nfn test_tuple_struct() {\n    Python::attach(|py| {\n        let tup = PyTuple::new(\n            py,\n            &[\n                1i32.into_pyobject(py).unwrap().into_any(),\n                \"test\".into_pyobject(py).unwrap().into_any(),\n            ],\n        )\n        .unwrap();\n        let tup = tup.extract::<Tuple>();\n        assert!(tup.is_err());\n        let tup = PyTuple::new(\n            py,\n            &[\n                \"test\".into_pyobject(py).unwrap().into_any(),\n                1i32.into_pyobject(py).unwrap().into_any(),\n            ],\n        )\n        .unwrap();\n        let tup = tup\n            .extract::<Tuple>()\n            .expect(\"Failed to extract Tuple from PyTuple\");\n        assert_eq!(tup.0, \"test\");\n        assert_eq!(tup.1, 1);\n    });\n}\n\n#[derive(Debug, FromPyObject)]\npub struct TransparentTuple(String);\n\n#[test]\nfn test_transparent_tuple_struct() {\n    Python::attach(|py| {\n        let tup = 1i32.into_pyobject(py).unwrap();\n        let tup = tup.extract::<TransparentTuple>();\n        assert!(tup.is_err());\n        let test = \"test\".into_pyobject(py).unwrap();\n        let tup = test\n            .extract::<TransparentTuple>()\n            .expect(\"Failed to extract TransparentTuple from PyTuple\");\n        assert_eq!(tup.0, \"test\");\n    });\n}\n\n#[pyclass]\nstruct PyBaz {\n    #[pyo3(get)]\n    tup: (String, String),\n    #[pyo3(get)]\n    e: PyE,\n}\n\n#[derive(Debug, FromPyObject)]\n#[expect(dead_code)]\nstruct Baz<U, T> {\n    e: E<U, T>,\n    tup: Tuple,\n}\n\n#[test]\nfn test_struct_nested_type_errors() {\n    Python::attach(|py| {\n        let pybaz = PyBaz {\n            tup: (\"test\".into(), \"test\".into()),\n            e: PyE {\n                test: \"foo\".into(),\n                test2: 0,\n            },\n        }\n        .into_pyobject(py)\n        .unwrap();\n\n        let test = pybaz.extract::<Baz<String, usize>>();\n        assert!(test.is_err());\n        assert_eq!(\n            extract_traceback(py,test.unwrap_err()),\n            \"TypeError: failed to extract field Baz.tup: TypeError: failed to extract field Tuple.1: \\\n         TypeError: \\'str\\' object cannot be interpreted as an integer\"\n        );\n    });\n}\n\n#[test]\nfn test_struct_nested_type_errors_with_generics() {\n    Python::attach(|py| {\n        let pybaz = PyBaz {\n            tup: (\"test\".into(), \"test\".into()),\n            e: PyE {\n                test: \"foo\".into(),\n                test2: 0,\n            },\n        }\n        .into_pyobject(py)\n        .unwrap();\n\n        let test = pybaz.extract::<Baz<usize, usize>>();\n        assert!(test.is_err());\n        assert_eq!(\n            extract_traceback(py, test.unwrap_err()),\n            \"TypeError: failed to extract field Baz.e: TypeError: failed to extract field E.test: \\\n         TypeError: \\'str\\' object cannot be interpreted as an integer\",\n        );\n    });\n}\n\n#[test]\nfn test_transparent_struct_error_message() {\n    Python::attach(|py| {\n        let tup = 1i32.into_pyobject(py).unwrap();\n        let tup = tup.extract::<B>();\n        assert!(tup.is_err());\n        assert_eq!(\n            extract_traceback(py, tup.unwrap_err()),\n            \"TypeError: failed to extract field B.test: TypeError: \\'int\\' object is not an \\\n         instance of \\'str\\'\"\n        );\n    });\n}\n\n#[test]\nfn test_tuple_struct_error_message() {\n    Python::attach(|py| {\n        let tup = (1, \"test\").into_pyobject(py).unwrap();\n        let tup = tup.extract::<Tuple>();\n        assert!(tup.is_err());\n        assert_eq!(\n            extract_traceback(py, tup.unwrap_err()),\n            \"TypeError: failed to extract field Tuple.0: TypeError: \\'int\\' object is not an \\\n         instance of \\'str\\'\"\n        );\n    });\n}\n\n#[test]\nfn test_transparent_tuple_error_message() {\n    Python::attach(|py| {\n        let tup = 1i32.into_pyobject(py).unwrap();\n        let tup = tup.extract::<TransparentTuple>();\n        assert!(tup.is_err());\n        assert_eq!(\n            extract_traceback(py, tup.unwrap_err()),\n            \"TypeError: failed to extract field TransparentTuple.0: TypeError: 'int' object \\\n         is not an instance of 'str'\",\n        );\n    });\n}\n\n#[pyclass]\nstruct RenameAllCls {}\n\n#[pymethods]\nimpl RenameAllCls {\n    #[getter]\n    #[pyo3(name = \"someField\")]\n    fn some_field(&self) -> &'static str {\n        \"Foo\"\n    }\n\n    #[getter]\n    #[pyo3(name = \"customNumber\")]\n    fn custom_number(&self) -> i32 {\n        42\n    }\n\n    fn __getitem__(&self, key: &str) -> PyResult<f32> {\n        match key {\n            \"otherField\" => Ok(42.0),\n            _ => Err(pyo3::exceptions::PyKeyError::new_err(\"foo\")),\n        }\n    }\n}\n\n#[test]\nfn test_struct_rename_all() {\n    #[derive(FromPyObject)]\n    #[pyo3(rename_all = \"camelCase\")]\n    struct RenameAll {\n        some_field: String,\n        #[pyo3(item)]\n        other_field: f32,\n        #[pyo3(attribute(\"customNumber\"))]\n        custom_name: i32,\n    }\n\n    Python::attach(|py| {\n        let RenameAll {\n            some_field,\n            other_field,\n            custom_name,\n        } = RenameAllCls {}\n            .into_pyobject(py)\n            .unwrap()\n            .extract()\n            .unwrap();\n\n        assert_eq!(some_field, \"Foo\");\n        assert_eq!(other_field, 42.0);\n        assert_eq!(custom_name, 42);\n    });\n}\n\n#[test]\nfn test_enum_rename_all() {\n    #[derive(FromPyObject)]\n    #[pyo3(rename_all = \"camelCase\")]\n    enum RenameAll {\n        Foo {\n            some_field: String,\n            #[pyo3(item)]\n            other_field: f32,\n            #[pyo3(attribute(\"customNumber\"))]\n            custom_name: i32,\n        },\n    }\n\n    Python::attach(|py| {\n        let RenameAll::Foo {\n            some_field,\n            other_field,\n            custom_name,\n        } = RenameAllCls {}\n            .into_pyobject(py)\n            .unwrap()\n            .extract()\n            .unwrap();\n\n        assert_eq!(some_field, \"Foo\");\n        assert_eq!(other_field, 42.0);\n        assert_eq!(custom_name, 42);\n    });\n}\n\n#[derive(Debug, FromPyObject)]\npub enum Foo<'py> {\n    TupleVar(usize, String),\n    StructVar {\n        test: Bound<'py, PyString>,\n    },\n    #[pyo3(transparent)]\n    TransparentTuple(usize),\n    #[pyo3(transparent)]\n    TransparentStructVar {\n        a: Option<String>,\n    },\n    StructVarGetAttrArg {\n        #[pyo3(attribute(\"bla\"))]\n        a: bool,\n    },\n    StructWithGetItem {\n        #[pyo3(item)]\n        a: String,\n    },\n    StructWithGetItemArg {\n        #[pyo3(item(\"foo\"))]\n        a: String,\n    },\n}\n\n#[pyclass]\npub struct PyBool {\n    #[pyo3(get)]\n    bla: bool,\n}\n\n#[test]\nfn test_enum() {\n    Python::attach(|py| {\n        let tup = PyTuple::new(\n            py,\n            &[\n                1i32.into_pyobject(py).unwrap().into_any(),\n                \"test\".into_pyobject(py).unwrap().into_any(),\n            ],\n        )\n        .unwrap();\n        let f = tup\n            .extract::<Foo<'_>>()\n            .expect(\"Failed to extract Foo from tuple\");\n        match f {\n            Foo::TupleVar(test, test2) => {\n                assert_eq!(test, 1);\n                assert_eq!(test2, \"test\");\n            }\n            _ => panic!(\"Expected extracting Foo::TupleVar, got {f:?}\"),\n        }\n\n        let pye = PyE {\n            test: \"foo\".into(),\n            test2: 0,\n        }\n        .into_pyobject(py)\n        .unwrap();\n        let f = pye\n            .extract::<Foo<'_>>()\n            .expect(\"Failed to extract Foo from PyE\");\n        match f {\n            Foo::StructVar { test } => assert_eq!(test.to_string_lossy(), \"foo\"),\n            _ => panic!(\"Expected extracting Foo::StructVar, got {f:?}\"),\n        }\n\n        let int = 1i32.into_pyobject(py).unwrap();\n        let f = int\n            .extract::<Foo<'_>>()\n            .expect(\"Failed to extract Foo from int\");\n        match f {\n            Foo::TransparentTuple(test) => assert_eq!(test, 1),\n            _ => panic!(\"Expected extracting Foo::TransparentTuple, got {f:?}\"),\n        }\n        let none = py.None();\n        let f = none\n            .extract::<Foo<'_>>(py)\n            .expect(\"Failed to extract Foo from int\");\n        match f {\n            Foo::TransparentStructVar { a } => assert!(a.is_none()),\n            _ => panic!(\"Expected extracting Foo::TransparentStructVar, got {f:?}\"),\n        }\n\n        let pybool = PyBool { bla: true }.into_pyobject(py).unwrap();\n        let f = pybool\n            .extract::<Foo<'_>>()\n            .expect(\"Failed to extract Foo from PyBool\");\n        match f {\n            Foo::StructVarGetAttrArg { a } => assert!(a),\n            _ => panic!(\"Expected extracting Foo::StructVarGetAttrArg, got {f:?}\"),\n        }\n\n        let dict = PyDict::new(py);\n        dict.set_item(\"a\", \"test\").expect(\"Failed to set item\");\n        let f = dict\n            .extract::<Foo<'_>>()\n            .expect(\"Failed to extract Foo from dict\");\n        match f {\n            Foo::StructWithGetItem { a } => assert_eq!(a, \"test\"),\n            _ => panic!(\"Expected extracting Foo::StructWithGetItem, got {f:?}\"),\n        }\n\n        let dict = PyDict::new(py);\n        dict.set_item(\"foo\", \"test\").expect(\"Failed to set item\");\n        let f = dict\n            .extract::<Foo<'_>>()\n            .expect(\"Failed to extract Foo from dict\");\n        match f {\n            Foo::StructWithGetItemArg { a } => assert_eq!(a, \"test\"),\n            _ => panic!(\"Expected extracting Foo::StructWithGetItemArg, got {f:?}\"),\n        }\n    });\n}\n\n#[test]\nfn test_enum_error() {\n    Python::attach(|py| {\n        let dict = PyDict::new(py);\n        let err = dict.extract::<Foo<'_>>().unwrap_err();\n        assert_eq!(\n            err.to_string(),\n            \"\\\nTypeError: failed to extract enum Foo ('TupleVar | StructVar | TransparentTuple | TransparentStructVar | StructVarGetAttrArg | StructWithGetItem | StructWithGetItemArg')\n- variant TupleVar (TupleVar): TypeError: 'dict' object is not an instance of 'tuple'\n- variant StructVar (StructVar): AttributeError: 'dict' object has no attribute 'test'\n- variant TransparentTuple (TransparentTuple): TypeError: failed to extract field Foo::TransparentTuple.0, caused by TypeError: 'dict' object cannot be interpreted as an integer\n- variant TransparentStructVar (TransparentStructVar): TypeError: failed to extract field Foo::TransparentStructVar.a, caused by TypeError: 'dict' object is not an instance of 'str'\n- variant StructVarGetAttrArg (StructVarGetAttrArg): AttributeError: 'dict' object has no attribute 'bla'\n- variant StructWithGetItem (StructWithGetItem): KeyError: 'a'\n- variant StructWithGetItemArg (StructWithGetItemArg): KeyError: 'foo'\"\n        );\n\n        let tup = PyTuple::empty(py);\n        let err = tup.extract::<Foo<'_>>().unwrap_err();\n        assert_eq!(\n            err.to_string(),\n            \"\\\nTypeError: failed to extract enum Foo ('TupleVar | StructVar | TransparentTuple | TransparentStructVar | StructVarGetAttrArg | StructWithGetItem | StructWithGetItemArg')\n- variant TupleVar (TupleVar): ValueError: expected tuple of length 2, but got tuple of length 0\n- variant StructVar (StructVar): AttributeError: 'tuple' object has no attribute 'test'\n- variant TransparentTuple (TransparentTuple): TypeError: failed to extract field Foo::TransparentTuple.0, caused by TypeError: 'tuple' object cannot be interpreted as an integer\n- variant TransparentStructVar (TransparentStructVar): TypeError: failed to extract field Foo::TransparentStructVar.a, caused by TypeError: 'tuple' object is not an instance of 'str'\n- variant StructVarGetAttrArg (StructVarGetAttrArg): AttributeError: 'tuple' object has no attribute 'bla'\n- variant StructWithGetItem (StructWithGetItem): TypeError: tuple indices must be integers or slices, not str\n- variant StructWithGetItemArg (StructWithGetItemArg): TypeError: tuple indices must be integers or slices, not str\"\n        );\n    });\n}\n\n#[derive(Debug, FromPyObject)]\nenum EnumWithCatchAll<'py> {\n    #[expect(dead_code)]\n    #[pyo3(transparent)]\n    Foo(Foo<'py>),\n    #[pyo3(transparent)]\n    CatchAll(Bound<'py, PyAny>),\n}\n\n#[test]\nfn test_enum_catch_all() {\n    Python::attach(|py| {\n        let dict = PyDict::new(py);\n        let f = dict\n            .extract::<EnumWithCatchAll<'_>>()\n            .expect(\"Failed to extract EnumWithCatchAll from dict\");\n        match f {\n            EnumWithCatchAll::CatchAll(any) => {\n                let d = any.extract::<Bound<'_, PyDict>>().expect(\"Expected pydict\");\n                assert!(d.is_empty());\n            }\n            _ => panic!(\"Expected extracting EnumWithCatchAll::CatchAll, got {f:?}\"),\n        }\n    });\n}\n\n#[derive(Debug, FromPyObject)]\npub enum Bar {\n    #[pyo3(annotation = \"str\")]\n    A(String),\n    #[pyo3(annotation = \"uint\")]\n    B(usize),\n    #[pyo3(annotation = \"int\", transparent)]\n    C(isize),\n}\n\n#[test]\nfn test_err_rename() {\n    Python::attach(|py| {\n        let dict = PyDict::new(py);\n        let f = dict.extract::<Bar>();\n        assert!(f.is_err());\n        assert_eq!(\n            f.unwrap_err().to_string(),\n            \"\\\nTypeError: failed to extract enum Bar ('str | uint | int')\n- variant A (str): TypeError: failed to extract field Bar::A.0, caused by TypeError: 'dict' object is not an instance of 'str'\n- variant B (uint): TypeError: failed to extract field Bar::B.0, caused by TypeError: 'dict' object cannot be interpreted as an integer\n- variant C (int): TypeError: failed to extract field Bar::C.0, caused by TypeError: 'dict' object cannot be interpreted as an integer\"\n        );\n    });\n}\n\n#[derive(Debug, FromPyObject)]\npub struct Zap {\n    #[pyo3(item)]\n    name: String,\n\n    #[pyo3(from_py_with = Bound::<'_, PyAny>::len, item(\"my_object\"))]\n    some_object_length: usize,\n}\n\n#[test]\nfn test_from_py_with() {\n    Python::attach(|py| {\n        let py_zap = py\n            .eval(\n                cr#\"{\"name\": \"whatever\", \"my_object\": [1, 2, 3]}\"#,\n                None,\n                None,\n            )\n            .expect(\"failed to create dict\");\n\n        let zap = py_zap.extract::<Zap>().unwrap();\n\n        assert_eq!(zap.name, \"whatever\");\n        assert_eq!(zap.some_object_length, 3usize);\n    });\n}\n\n#[derive(Debug, FromPyObject)]\npub struct ZapTuple(\n    String,\n    #[pyo3(from_py_with = Bound::<'_, PyAny>::len)] usize,\n);\n\n#[test]\nfn test_from_py_with_tuple_struct() {\n    Python::attach(|py| {\n        let py_zap = py\n            .eval(cr#\"(\"whatever\", [1, 2, 3])\"#, None, None)\n            .expect(\"failed to create tuple\");\n\n        let zap = py_zap.extract::<ZapTuple>().unwrap();\n\n        assert_eq!(zap.0, \"whatever\");\n        assert_eq!(zap.1, 3usize);\n    });\n}\n\n#[test]\nfn test_from_py_with_tuple_struct_error() {\n    Python::attach(|py| {\n        let py_zap = py\n            .eval(cr#\"(\"whatever\", [1, 2, 3], \"third\")\"#, None, None)\n            .expect(\"failed to create tuple\");\n\n        let f = py_zap.extract::<ZapTuple>();\n\n        assert!(f.is_err());\n        assert_eq!(\n            f.unwrap_err().to_string(),\n            \"ValueError: expected tuple of length 2, but got tuple of length 3\"\n        );\n    });\n}\n\n#[derive(Debug, FromPyObject, PartialEq, Eq)]\npub enum ZapEnum {\n    Zip(#[pyo3(from_py_with = Bound::<'_, PyAny>::len)] usize),\n    Zap(\n        String,\n        #[pyo3(from_py_with = Bound::<'_, PyAny>::len)] usize,\n    ),\n}\n\n#[test]\nfn test_from_py_with_enum() {\n    Python::attach(|py| {\n        let py_zap = py\n            .eval(cr#\"(\"whatever\", [1, 2, 3])\"#, None, None)\n            .expect(\"failed to create tuple\");\n\n        let zap = py_zap.extract::<ZapEnum>().unwrap();\n        let expected_zap = ZapEnum::Zip(2);\n\n        assert_eq!(zap, expected_zap);\n    });\n}\n\n#[derive(Debug, FromPyObject, PartialEq, Eq)]\n#[pyo3(transparent)]\npub struct TransparentFromPyWith {\n    #[pyo3(from_py_with = Bound::<'_, PyAny>::len)]\n    len: usize,\n}\n\n#[test]\nfn test_transparent_from_py_with() {\n    Python::attach(|py| {\n        let result = PyList::new(py, [1, 2, 3])\n            .unwrap()\n            .extract::<TransparentFromPyWith>()\n            .unwrap();\n        let expected = TransparentFromPyWith { len: 3 };\n\n        assert_eq!(result, expected);\n    });\n}\n\n#[derive(Debug, FromPyObject, PartialEq, Eq)]\npub struct WithKeywordAttr {\n    r#box: usize,\n}\n\n#[pyclass]\npub struct WithKeywordAttrC {\n    #[pyo3(get)]\n    r#box: usize,\n}\n\n#[test]\nfn test_with_keyword_attr() {\n    Python::attach(|py| {\n        let cls = WithKeywordAttrC { r#box: 3 }.into_pyobject(py).unwrap();\n        let result = cls.extract::<WithKeywordAttr>().unwrap();\n        let expected = WithKeywordAttr { r#box: 3 };\n        assert_eq!(result, expected);\n    });\n}\n\n#[derive(Debug, FromPyObject, PartialEq, Eq)]\npub struct WithKeywordItem {\n    #[pyo3(item)]\n    r#box: usize,\n}\n\n#[test]\nfn test_with_keyword_item() {\n    Python::attach(|py| {\n        let dict = PyDict::new(py);\n        dict.set_item(\"box\", 3).unwrap();\n        let result = dict.extract::<WithKeywordItem>().unwrap();\n        let expected = WithKeywordItem { r#box: 3 };\n        assert_eq!(result, expected);\n    });\n}\n\n#[derive(Debug, FromPyObject, PartialEq, Eq)]\npub struct WithDefaultItem {\n    #[pyo3(item, default)]\n    opt: Option<usize>,\n    #[pyo3(item)]\n    value: usize,\n}\n\n#[test]\nfn test_with_default_item() {\n    Python::attach(|py| {\n        let dict = PyDict::new(py);\n        dict.set_item(\"value\", 3).unwrap();\n        let result = dict.extract::<WithDefaultItem>().unwrap();\n        let expected = WithDefaultItem {\n            value: 3,\n            opt: None,\n        };\n        assert_eq!(result, expected);\n    });\n}\n\n#[derive(Debug, FromPyObject, PartialEq, Eq)]\npub struct WithExplicitDefaultItem {\n    #[pyo3(item, default = 1)]\n    opt: usize,\n    #[pyo3(item)]\n    value: usize,\n}\n\n#[test]\nfn test_with_explicit_default_item() {\n    Python::attach(|py| {\n        let dict = PyDict::new(py);\n        dict.set_item(\"value\", 3).unwrap();\n        let result = dict.extract::<WithExplicitDefaultItem>().unwrap();\n        let expected = WithExplicitDefaultItem { value: 3, opt: 1 };\n        assert_eq!(result, expected);\n    });\n}\n\n#[derive(Debug, FromPyObject, PartialEq, Eq)]\npub struct WithDefaultItemAndConversionFunction {\n    #[pyo3(item, default, from_py_with = Bound::<'_, PyAny>::len)]\n    opt: usize,\n    #[pyo3(item)]\n    value: usize,\n}\n\n#[test]\nfn test_with_default_item_and_conversion_function() {\n    Python::attach(|py| {\n        // Filled case\n        let dict = PyDict::new(py);\n        dict.set_item(\"opt\", (1,)).unwrap();\n        dict.set_item(\"value\", 3).unwrap();\n        let result = dict\n            .extract::<WithDefaultItemAndConversionFunction>()\n            .unwrap();\n        let expected = WithDefaultItemAndConversionFunction { opt: 1, value: 3 };\n        assert_eq!(result, expected);\n\n        // Empty case\n        let dict = PyDict::new(py);\n        dict.set_item(\"value\", 3).unwrap();\n        let result = dict\n            .extract::<WithDefaultItemAndConversionFunction>()\n            .unwrap();\n        let expected = WithDefaultItemAndConversionFunction { opt: 0, value: 3 };\n        assert_eq!(result, expected);\n\n        // Error case\n        let dict = PyDict::new(py);\n        dict.set_item(\"value\", 3).unwrap();\n        dict.set_item(\"opt\", 1).unwrap();\n        assert!(dict\n            .extract::<WithDefaultItemAndConversionFunction>()\n            .is_err());\n    });\n}\n\n#[derive(Debug, FromPyObject, PartialEq, Eq)]\npub enum WithDefaultItemEnum {\n    #[pyo3(from_item_all)]\n    Foo {\n        a: usize,\n        #[pyo3(default)]\n        b: usize,\n    },\n    NeverUsedA {\n        a: usize,\n    },\n}\n\n#[test]\nfn test_with_default_item_enum() {\n    Python::attach(|py| {\n        // A and B filled\n        let dict = PyDict::new(py);\n        dict.set_item(\"a\", 1).unwrap();\n        dict.set_item(\"b\", 2).unwrap();\n        let result = dict.extract::<WithDefaultItemEnum>().unwrap();\n        let expected = WithDefaultItemEnum::Foo { a: 1, b: 2 };\n        assert_eq!(result, expected);\n\n        // A filled\n        let dict = PyDict::new(py);\n        dict.set_item(\"a\", 1).unwrap();\n        let result = dict.extract::<WithDefaultItemEnum>().unwrap();\n        let expected = WithDefaultItemEnum::Foo { a: 1, b: 0 };\n        assert_eq!(result, expected);\n    });\n}\n"
  },
  {
    "path": "tests/test_gc.rs",
    "content": "#![cfg(feature = \"macros\")]\n#![warn(unsafe_op_in_unsafe_fn)]\n\nuse pyo3::class::PyTraverseError;\nuse pyo3::class::PyVisit;\nuse pyo3::ffi;\nuse pyo3::prelude::*;\n#[cfg(not(Py_GIL_DISABLED))]\nuse pyo3::py_run;\n#[cfg(not(target_arch = \"wasm32\"))]\nuse std::cell::Cell;\nuse std::sync::atomic::{AtomicBool, Ordering};\nuse std::sync::Once;\nuse std::sync::{Arc, Mutex};\n\nmod test_utils;\n\n#[pyclass(freelist = 2)]\nstruct ClassWithFreelist {}\n\n#[test]\nfn class_with_freelist() {\n    let ptr = Python::attach(|py| {\n        let inst = Py::new(py, ClassWithFreelist {}).unwrap();\n        let _inst2 = Py::new(py, ClassWithFreelist {}).unwrap();\n        let ptr = inst.as_ptr();\n        drop(inst);\n        ptr\n    });\n\n    Python::attach(|py| {\n        let inst3 = Py::new(py, ClassWithFreelist {}).unwrap();\n        assert_eq!(ptr, inst3.as_ptr());\n\n        let inst4 = Py::new(py, ClassWithFreelist {}).unwrap();\n        assert_ne!(ptr, inst4.as_ptr())\n    });\n}\n\n#[pyclass(freelist = 2)]\n#[cfg(not(target_arch = \"wasm32\"))]\nstruct ClassWithFreelistAndData {\n    data: Option<usize>,\n}\n\n#[cfg(not(target_arch = \"wasm32\"))]\nfn spin_freelist(py: Python<'_>, data: usize) {\n    for _ in 0..500 {\n        let inst1 = Py::new(py, ClassWithFreelistAndData { data: Some(data) }).unwrap();\n        let inst2 = Py::new(py, ClassWithFreelistAndData { data: Some(data) }).unwrap();\n        assert_eq!(inst1.borrow(py).data, Some(data));\n        assert_eq!(inst2.borrow(py).data, Some(data));\n    }\n}\n\n#[test]\n#[cfg(not(target_arch = \"wasm32\"))]\nfn multithreaded_class_with_freelist() {\n    std::thread::scope(|s| {\n        s.spawn(|| {\n            Python::attach(|py| spin_freelist(py, 12));\n        });\n        s.spawn(|| {\n            Python::attach(|py| spin_freelist(py, 0x4d3d3d3));\n        });\n    });\n}\n\n/// Helper function to create a pair of objects that can be used to test drops;\n/// the first object is a guard that records when it has been dropped, the second\n/// object is a check that can be used to assert that the guard has been dropped.\nfn drop_check() -> (DropGuard, DropCheck) {\n    let flag = Arc::new(Once::new());\n    (DropGuard(flag.clone()), DropCheck(flag))\n}\n\n/// Helper structure that records when it has been dropped in the cor\nstruct DropGuard(Arc<Once>);\nimpl Drop for DropGuard {\n    fn drop(&mut self) {\n        self.0.call_once(|| ());\n    }\n}\n\nstruct DropCheck(Arc<Once>);\nimpl DropCheck {\n    #[track_caller]\n    fn assert_not_dropped(&self) {\n        assert!(!self.0.is_completed());\n    }\n\n    #[track_caller]\n    fn assert_dropped(&self) {\n        assert!(self.0.is_completed());\n    }\n\n    #[track_caller]\n    fn assert_drops_with_gc(&self, object: *mut pyo3::ffi::PyObject) {\n        // running the GC might take a few cycles to collect an object\n        for _ in 0..100 {\n            if self.0.is_completed() {\n                return;\n            }\n\n            Python::attach(|py| {\n                py.run(c\"import gc; gc.collect()\", None, None).unwrap();\n            });\n            #[cfg(Py_GIL_DISABLED)]\n            {\n                // on the free-threaded build, the GC might be running in a separate thread, allow\n                // some time for this\n                std::thread::sleep(std::time::Duration::from_millis(5));\n            }\n        }\n\n        panic!(\n            \"Object was not dropped after 100 GC cycles, refcount is {}\",\n            // this could be garbage, but it's in a test and we're just printing the value\n            unsafe { ffi::Py_REFCNT(object) }\n        );\n    }\n}\n\n#[test]\nfn data_is_dropped() {\n    #[pyclass]\n    struct DataIsDropped {\n        _guard1: DropGuard,\n        _guard2: DropGuard,\n    }\n\n    let (guard1, check1) = drop_check();\n    let (guard2, check2) = drop_check();\n\n    Python::attach(|py| {\n        let data_is_dropped = DataIsDropped {\n            _guard1: guard1,\n            _guard2: guard2,\n        };\n        let inst = Py::new(py, data_is_dropped).unwrap();\n        check1.assert_not_dropped();\n        check2.assert_not_dropped();\n        drop(inst);\n    });\n\n    check1.assert_dropped();\n    check2.assert_dropped();\n}\n\n#[pyclass(subclass)]\nstruct CycleWithClear {\n    cycle: Option<Py<PyAny>>,\n    _guard: DropGuard,\n}\n\n#[pymethods]\nimpl CycleWithClear {\n    fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n        visit.call(&self.cycle)\n    }\n\n    fn __clear__(slf: &Bound<'_, Self>) {\n        slf.borrow_mut().cycle = None;\n    }\n}\n\n#[test]\nfn test_cycle_clear() {\n    let (guard, check) = drop_check();\n\n    let ptr = Python::attach(|py| {\n        let inst = Bound::new(\n            py,\n            CycleWithClear {\n                cycle: None,\n                _guard: guard,\n            },\n        )\n        .unwrap();\n\n        inst.borrow_mut().cycle = Some(inst.clone().into_any().unbind());\n\n        // gc.get_objects can create references to partially initialized objects,\n        // leading to races on the free-threaded build.\n        // see https://github.com/python/cpython/issues/130421#issuecomment-2682924142\n        #[cfg(not(Py_GIL_DISABLED))]\n        py_run!(py, inst, \"import gc; assert inst in gc.get_objects()\");\n        check.assert_not_dropped();\n        inst.as_ptr()\n    });\n\n    check.assert_drops_with_gc(ptr);\n}\n\n/// Test that traversing `None` of `Option<Py<T>>` does not cause a segfault\n#[test]\nfn gc_null_traversal() {\n    #[pyclass]\n    struct GcNullTraversal {\n        cycle: Option<Py<Self>>,\n        null: Option<Py<Self>>,\n    }\n\n    #[pymethods]\n    impl GcNullTraversal {\n        fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n            visit.call(&self.cycle)?;\n            visit.call(&self.null)?; // Should not segfault\n            Ok(())\n        }\n\n        fn __clear__(&mut self) {\n            self.cycle = None;\n            self.null = None;\n        }\n    }\n\n    Python::attach(|py| {\n        let obj = Py::new(\n            py,\n            GcNullTraversal {\n                cycle: None,\n                null: None,\n            },\n        )\n        .unwrap();\n        obj.borrow_mut(py).cycle = Some(obj.clone_ref(py));\n\n        // the object doesn't have to be cleaned up, it just needs to be traversed.\n        py.run(c\"import gc; gc.collect()\", None, None).unwrap();\n    });\n}\n\n#[test]\nfn inheritance_with_new_methods_with_drop() {\n    #[pyclass(subclass)]\n    struct BaseClassWithDrop {\n        guard: Option<DropGuard>,\n    }\n\n    #[pymethods]\n    impl BaseClassWithDrop {\n        #[new]\n        fn new() -> BaseClassWithDrop {\n            BaseClassWithDrop { guard: None }\n        }\n    }\n\n    #[pyclass(extends = BaseClassWithDrop)]\n    struct SubClassWithDrop {\n        guard: Option<DropGuard>,\n    }\n\n    #[pymethods]\n    impl SubClassWithDrop {\n        #[new]\n        fn new() -> (Self, BaseClassWithDrop) {\n            (\n                SubClassWithDrop { guard: None },\n                BaseClassWithDrop { guard: None },\n            )\n        }\n    }\n\n    let (guard_base, check_base) = drop_check();\n    let (guard_sub, check_sub) = drop_check();\n\n    Python::attach(|py| {\n        let typeobj = py.get_type::<SubClassWithDrop>();\n        let inst = typeobj\n            .call((), None)\n            .unwrap()\n            .cast_into::<SubClassWithDrop>()\n            .unwrap();\n\n        inst.as_super().borrow_mut().guard = Some(guard_base);\n        inst.borrow_mut().guard = Some(guard_sub);\n\n        check_base.assert_not_dropped();\n        check_sub.assert_not_dropped();\n    });\n\n    check_base.assert_dropped();\n    check_sub.assert_dropped();\n}\n\n#[test]\nfn gc_during_borrow() {\n    #[pyclass]\n    struct TraversableClass {\n        traversed: AtomicBool,\n    }\n\n    impl TraversableClass {\n        fn new() -> Self {\n            Self {\n                traversed: AtomicBool::new(false),\n            }\n        }\n    }\n\n    #[pymethods]\n    impl TraversableClass {\n        fn __clear__(&mut self) {}\n\n        #[expect(clippy::unnecessary_wraps)]\n        fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n            self.traversed.store(true, Ordering::Relaxed);\n            Ok(())\n        }\n    }\n\n    Python::attach(|py| {\n        // get the traverse function\n        let ty = py.get_type::<TraversableClass>();\n        let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() };\n\n        // create an object and check that traversing it works normally\n        // when it's not borrowed\n        let cell = Bound::new(py, TraversableClass::new()).unwrap();\n        assert!(!cell.borrow().traversed.load(Ordering::Relaxed));\n        unsafe { traverse(cell.as_ptr(), novisit, std::ptr::null_mut()) };\n        assert!(cell.borrow().traversed.load(Ordering::Relaxed));\n\n        // create an object and check that it is not traversed if the GC\n        // is invoked while it is already borrowed mutably\n        let cell2 = Bound::new(py, TraversableClass::new()).unwrap();\n        let guard = cell2.borrow_mut();\n        assert!(!guard.traversed.load(Ordering::Relaxed));\n        unsafe { traverse(cell2.as_ptr(), novisit, std::ptr::null_mut()) };\n        assert!(!guard.traversed.load(Ordering::Relaxed));\n        drop(guard);\n    });\n}\n\n#[test]\nfn traverse_partial() {\n    #[pyclass]\n    struct PartialTraverse {\n        member: Py<PyAny>,\n    }\n\n    impl PartialTraverse {\n        fn new(py: Python<'_>) -> Self {\n            Self { member: py.None() }\n        }\n    }\n\n    #[pymethods]\n    impl PartialTraverse {\n        fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n            visit.call(&self.member)?;\n            // In the test, we expect this to never be hit\n            unreachable!()\n        }\n    }\n\n    Python::attach(|py| {\n        // get the traverse function\n        let ty = py.get_type::<PartialTraverse>();\n        let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() };\n\n        // confirm that traversing errors\n        let obj = Py::new(py, PartialTraverse::new(py)).unwrap();\n        assert_eq!(\n            unsafe { traverse(obj.as_ptr(), visit_error, std::ptr::null_mut()) },\n            -1\n        );\n    })\n}\n\n#[test]\n#[cfg(panic = \"unwind\")]\nfn traverse_panic() {\n    #[pyclass]\n    struct PanickyTraverse {\n        member: Py<PyAny>,\n    }\n\n    impl PanickyTraverse {\n        fn new(py: Python<'_>) -> Self {\n            Self { member: py.None() }\n        }\n    }\n\n    #[pymethods]\n    impl PanickyTraverse {\n        fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n            visit.call(&self.member)?;\n            panic!(\"at the disco\");\n        }\n    }\n\n    Python::attach(|py| {\n        // get the traverse function\n        let ty = py.get_type::<PanickyTraverse>();\n        let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() };\n\n        // confirm that traversing errors\n        let obj = Py::new(py, PanickyTraverse::new(py)).unwrap();\n        assert_eq!(\n            unsafe { traverse(obj.as_ptr(), novisit, std::ptr::null_mut()) },\n            -1\n        );\n    })\n}\n\n#[test]\n#[cfg(panic = \"unwind\")]\nfn tries_gil_in_traverse() {\n    #[pyclass]\n    struct TriesGILInTraverse {}\n\n    #[pymethods]\n    impl TriesGILInTraverse {\n        fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n            Python::attach(|_py| Ok(()))\n        }\n    }\n\n    Python::attach(|py| {\n        // get the traverse function\n        let ty = py.get_type::<TriesGILInTraverse>();\n        let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() };\n\n        // confirm that traversing panicks\n        let obj = Py::new(py, TriesGILInTraverse {}).unwrap();\n        assert_eq!(\n            unsafe { traverse(obj.as_ptr(), novisit, std::ptr::null_mut()) },\n            -1\n        );\n    })\n}\n\n#[test]\nfn traverse_cannot_be_hijacked() {\n    #[pyclass]\n    struct HijackedTraverse {\n        traversed: AtomicBool,\n        hijacked: AtomicBool,\n    }\n\n    impl HijackedTraverse {\n        fn new() -> Self {\n            Self {\n                traversed: AtomicBool::new(false),\n                hijacked: AtomicBool::new(false),\n            }\n        }\n\n        fn traversed_and_hijacked(&self) -> (bool, bool) {\n            (\n                self.traversed.load(Ordering::Acquire),\n                self.hijacked.load(Ordering::Acquire),\n            )\n        }\n    }\n\n    #[pymethods]\n    impl HijackedTraverse {\n        #[expect(clippy::unnecessary_wraps)]\n        fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n            self.traversed.store(true, Ordering::Release);\n            Ok(())\n        }\n    }\n\n    #[allow(dead_code, reason = \"used to test the trait method is not used\")]\n    trait Traversable {\n        fn __traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>;\n    }\n\n    impl Traversable for PyRef<'_, HijackedTraverse> {\n        fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n            self.hijacked.store(true, Ordering::Release);\n            Ok(())\n        }\n    }\n\n    Python::attach(|py| {\n        // get the traverse function\n        let ty = py.get_type::<HijackedTraverse>();\n        let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() };\n\n        let cell = Bound::new(py, HijackedTraverse::new()).unwrap();\n        assert_eq!(cell.borrow().traversed_and_hijacked(), (false, false));\n        unsafe { traverse(cell.as_ptr(), novisit, std::ptr::null_mut()) };\n        assert_eq!(cell.borrow().traversed_and_hijacked(), (true, false));\n    })\n}\n\n#[pyclass]\nstruct DropDuringTraversal {\n    cycle: Mutex<Option<Py<Self>>>,\n    _guard: DropGuard,\n}\n\n#[pymethods]\nimpl DropDuringTraversal {\n    #[expect(clippy::unnecessary_wraps)]\n    fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n        let mut cycle_ref = self.cycle.lock().unwrap();\n        *cycle_ref = None;\n        Ok(())\n    }\n}\n\n#[cfg(not(pyo3_disable_reference_pool))]\n#[test]\nfn drop_during_traversal_with_gil() {\n    let (guard, check) = drop_check();\n\n    let ptr = Python::attach(|py| {\n        let cycle = Mutex::new(None);\n        let inst = Py::new(\n            py,\n            DropDuringTraversal {\n                cycle,\n                _guard: guard,\n            },\n        )\n        .unwrap();\n\n        *inst.borrow_mut(py).cycle.lock().unwrap() = Some(inst.clone_ref(py));\n\n        check.assert_not_dropped();\n        let ptr = inst.as_ptr();\n        drop(inst); // drop the object while holding the GIL\n\n        #[cfg(not(Py_GIL_DISABLED))]\n        {\n            // other thread might have caused GC on free-threaded build\n            check.assert_not_dropped();\n        }\n\n        ptr\n    });\n\n    check.assert_drops_with_gc(ptr);\n}\n\n#[cfg(not(pyo3_disable_reference_pool))]\n#[test]\nfn drop_during_traversal_without_gil() {\n    let (guard, check) = drop_check();\n\n    let inst = Python::attach(|py| {\n        let cycle = Mutex::new(None);\n        let inst = Py::new(\n            py,\n            DropDuringTraversal {\n                cycle,\n                _guard: guard,\n            },\n        )\n        .unwrap();\n\n        *inst.borrow_mut(py).cycle.lock().unwrap() = Some(inst.clone_ref(py));\n\n        check.assert_not_dropped();\n        inst\n    });\n\n    let ptr = inst.as_ptr();\n    drop(inst); // drop the object without holding the GIL\n\n    check.assert_drops_with_gc(ptr);\n}\n\n#[test]\n#[cfg(not(target_arch = \"wasm32\"))] // We are building wasm Python with pthreads disabled\nfn unsendable_are_not_traversed_on_foreign_thread() {\n    #[pyclass(unsendable)]\n    struct UnsendableTraversal {\n        traversed: Cell<bool>,\n    }\n\n    #[pymethods]\n    impl UnsendableTraversal {\n        fn __clear__(&mut self) {}\n\n        #[expect(clippy::unnecessary_wraps)]\n        fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n            self.traversed.set(true);\n            Ok(())\n        }\n    }\n\n    #[derive(Clone, Copy)]\n    struct SendablePtr(*mut pyo3::ffi::PyObject);\n\n    unsafe impl Send for SendablePtr {}\n\n    Python::attach(|py| {\n        let ty = py.get_type::<UnsendableTraversal>();\n        let traverse = unsafe { get_type_traverse(ty.as_type_ptr()).unwrap() };\n\n        let obj = Bound::new(\n            py,\n            UnsendableTraversal {\n                traversed: Cell::new(false),\n            },\n        )\n        .unwrap();\n\n        let ptr = SendablePtr(obj.as_ptr());\n\n        std::thread::spawn(move || {\n            // traversal on foreign thread is a no-op\n            assert_eq!(\n                unsafe { traverse({ ptr }.0, novisit, std::ptr::null_mut()) },\n                0\n            );\n        })\n        .join()\n        .unwrap();\n\n        assert!(!obj.borrow().traversed.get());\n\n        // traversal on home thread still works\n        assert_eq!(\n            unsafe { traverse({ ptr }.0, novisit, std::ptr::null_mut()) },\n            0\n        );\n\n        assert!(obj.borrow().traversed.get());\n    });\n}\n\n#[test]\nfn test_traverse_subclass() {\n    #[pyclass(extends = CycleWithClear)]\n    struct SubOverrideTraverse {}\n\n    #[pymethods]\n    impl SubOverrideTraverse {\n        #[expect(clippy::unnecessary_wraps)]\n        fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n            // subclass traverse overrides the base class traverse\n            Ok(())\n        }\n    }\n\n    let (guard, check) = drop_check();\n\n    Python::attach(|py| {\n        let base = CycleWithClear {\n            cycle: None,\n            _guard: guard,\n        };\n        let obj = Bound::new(\n            py,\n            PyClassInitializer::from(base).add_subclass(SubOverrideTraverse {}),\n        )\n        .unwrap();\n        obj.borrow_mut().as_super().cycle = Some(obj.clone().into_any().unbind());\n\n        check.assert_not_dropped();\n        let ptr = obj.as_ptr();\n        drop(obj);\n        #[cfg(not(Py_GIL_DISABLED))]\n        {\n            // other thread might have caused GC on free-threaded build\n            check.assert_not_dropped();\n        }\n\n        check.assert_drops_with_gc(ptr);\n    });\n}\n\n#[test]\nfn test_traverse_subclass_override_clear() {\n    #[pyclass(extends = CycleWithClear)]\n    struct SubOverrideClear {}\n\n    #[pymethods]\n    impl SubOverrideClear {\n        #[expect(clippy::unnecessary_wraps)]\n        fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n            // subclass traverse overrides the base class traverse, necessary for\n            // the sub clear to be called\n            // FIXME: should this really need to be the case?\n            Ok(())\n        }\n\n        fn __clear__(&self) {\n            // subclass clear overrides the base class clear\n        }\n    }\n\n    let (guard, check) = drop_check();\n\n    Python::attach(|py| {\n        let base = CycleWithClear {\n            cycle: None,\n            _guard: guard,\n        };\n        let obj = Bound::new(\n            py,\n            PyClassInitializer::from(base).add_subclass(SubOverrideClear {}),\n        )\n        .unwrap();\n        obj.borrow_mut().as_super().cycle = Some(obj.clone().into_any().unbind());\n\n        check.assert_not_dropped();\n        let ptr = obj.as_ptr();\n        drop(obj);\n        #[cfg(not(Py_GIL_DISABLED))]\n        {\n            // other thread might have caused GC on free-threaded build\n            check.assert_not_dropped();\n        }\n\n        check.assert_drops_with_gc(ptr);\n    });\n}\n\n// Manual traversal utilities\n\nunsafe fn get_type_traverse(tp: *mut pyo3::ffi::PyTypeObject) -> Option<pyo3::ffi::traverseproc> {\n    unsafe { std::mem::transmute(pyo3::ffi::PyType_GetSlot(tp, pyo3::ffi::Py_tp_traverse)) }\n}\n\n// a dummy visitor function\nextern \"C\" fn novisit(\n    _object: *mut pyo3::ffi::PyObject,\n    _arg: *mut core::ffi::c_void,\n) -> std::ffi::c_int {\n    0\n}\n\n// a visitor function which errors (returns nonzero code)\nextern \"C\" fn visit_error(\n    _object: *mut pyo3::ffi::PyObject,\n    _arg: *mut core::ffi::c_void,\n) -> std::ffi::c_int {\n    -1\n}\n\n#[test]\n#[cfg(any(not(Py_LIMITED_API), Py_3_11))] // buffer availability\nfn test_drop_buffer_during_traversal_without_gil() {\n    use pyo3::buffer::PyBuffer;\n    use pyo3::types::PyBytes;\n\n    // `PyBuffer` has a drop method which attempts to attach to the Python interpreter,\n    // if the thread is during traverse we leak it for safety. This should _never_ be happening\n    // so it's purely a user bug, but we leak to be safe.\n\n    #[pyclass]\n    struct BufferDropDuringTraversal {\n        inner: Mutex<Option<(DropGuard, PyBuffer<u8>)>>,\n        cycle: Option<Py<PyAny>>,\n    }\n\n    #[pymethods]\n    impl BufferDropDuringTraversal {\n        #[expect(clippy::unnecessary_wraps)]\n        fn __traverse__(&self, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n            self.inner.lock().unwrap().take();\n            Ok(())\n        }\n\n        fn __clear__(&mut self) {\n            self.cycle = None;\n        }\n    }\n\n    let (guard, check) = drop_check();\n    Python::attach(|py| {\n        let obj = Py::new(\n            py,\n            BufferDropDuringTraversal {\n                inner: Mutex::new(Some((\n                    guard,\n                    PyBuffer::get(&PyBytes::new(py, b\"test\")).unwrap(),\n                ))),\n                cycle: None,\n            },\n        )\n        .unwrap();\n\n        obj.borrow_mut(py).cycle = Some(obj.clone_ref(py).into_any());\n\n        let ptr = obj.as_ptr();\n        drop(obj);\n\n        check.assert_drops_with_gc(ptr);\n    });\n}\n"
  },
  {
    "path": "tests/test_getter_setter.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse std::cell::Cell;\n\nuse pyo3::prelude::*;\nuse pyo3::py_run;\nuse pyo3::types::PyString;\nuse pyo3::types::{IntoPyDict, PyList};\n\nmod test_utils;\n\n#[pyclass]\nstruct ClassWithProperties {\n    num: i32,\n}\n\n#[pymethods]\nimpl ClassWithProperties {\n    fn get_num(&self) -> i32 {\n        self.num\n    }\n\n    #[getter(DATA)]\n    /// a getter for data\n    fn get_data(&self) -> i32 {\n        self.num\n    }\n    #[setter(DATA)]\n    fn set_data(&mut self, value: i32) {\n        self.num = value;\n    }\n\n    #[getter]\n    /// a getter with a type un-wrapped by PyResult\n    fn get_unwrapped(&self) -> i32 {\n        self.num\n    }\n\n    #[setter]\n    fn set_unwrapped(&mut self, value: i32) {\n        self.num = value;\n    }\n\n    #[setter]\n    fn set_from_len(&mut self, #[pyo3(from_py_with = extract_len)] value: i32) {\n        self.num = value;\n    }\n\n    #[setter]\n    fn set_from_any(&mut self, value: &Bound<'_, PyAny>) -> PyResult<()> {\n        self.num = value.extract()?;\n        Ok(())\n    }\n\n    #[getter]\n    fn get_data_list<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyList>> {\n        PyList::new(py, [self.num])\n    }\n}\n\nfn extract_len(any: &Bound<'_, PyAny>) -> PyResult<i32> {\n    any.len().map(|len| len as i32)\n}\n\n#[test]\nfn class_with_properties() {\n    Python::attach(|py| {\n        let inst = Py::new(py, ClassWithProperties { num: 10 }).unwrap();\n\n        py_run!(py, inst, \"assert inst.get_num() == 10\");\n        py_run!(py, inst, \"assert inst.get_num() == inst.DATA\");\n        py_run!(py, inst, \"inst.DATA = 20\");\n        py_run!(py, inst, \"assert inst.get_num() == 20 == inst.DATA\");\n\n        py_expect_exception!(py, inst, \"del inst.DATA\", PyAttributeError);\n\n        py_run!(py, inst, \"assert inst.get_num() == inst.unwrapped == 20\");\n        py_run!(py, inst, \"inst.unwrapped = 42\");\n        py_run!(py, inst, \"assert inst.get_num() == inst.unwrapped == 42\");\n        py_run!(py, inst, \"assert inst.data_list == [42]\");\n\n        py_run!(py, inst, \"inst.from_len = [0, 0, 0]\");\n        py_run!(py, inst, \"assert inst.get_num() == 3\");\n\n        py_run!(py, inst, \"inst.from_any = 15\");\n        py_run!(py, inst, \"assert inst.get_num() == 15\");\n\n        let d = [(\"C\", py.get_type::<ClassWithProperties>())]\n            .into_py_dict(py)\n            .unwrap();\n        py_assert!(py, *d, \"C.DATA.__doc__ == 'a getter for data'\");\n    });\n}\n\n#[pyclass]\nstruct GetterSetter {\n    #[pyo3(get, set)]\n    num: i32,\n    #[pyo3(get, set)]\n    text: String,\n}\n\n#[pymethods]\nimpl GetterSetter {\n    fn get_num2(&self) -> i32 {\n        self.num\n    }\n}\n\n#[test]\nfn getter_setter_autogen() {\n    Python::attach(|py| {\n        let inst = Py::new(\n            py,\n            GetterSetter {\n                num: 10,\n                text: \"Hello\".to_string(),\n            },\n        )\n        .unwrap();\n\n        py_run!(py, inst, \"assert inst.num == 10\");\n        py_run!(py, inst, \"inst.num = 20; assert inst.num == 20\");\n        py_run!(\n            py,\n            inst,\n            \"assert inst.text == 'Hello'; inst.text = 'There'; assert inst.text == 'There'\"\n        );\n    });\n}\n\n#[pyclass]\nstruct RefGetterSetter {\n    num: i32,\n}\n\n#[pymethods]\nimpl RefGetterSetter {\n    #[getter]\n    fn get_num(slf: PyRef<'_, Self>) -> i32 {\n        slf.num\n    }\n\n    #[setter]\n    fn set_num(mut slf: PyRefMut<'_, Self>, value: i32) {\n        slf.num = value;\n    }\n}\n\n#[test]\nfn ref_getter_setter() {\n    // Regression test for #837\n    Python::attach(|py| {\n        let inst = Py::new(py, RefGetterSetter { num: 10 }).unwrap();\n\n        py_run!(py, inst, \"assert inst.num == 10\");\n        py_run!(py, inst, \"inst.num = 20; assert inst.num == 20\");\n    });\n}\n\n#[pyclass]\nstruct TupleClassGetterSetter(i32);\n\n#[pymethods]\nimpl TupleClassGetterSetter {\n    #[getter(num)]\n    fn get_num(&self) -> i32 {\n        self.0\n    }\n\n    #[setter(num)]\n    fn set_num(&mut self, value: i32) {\n        self.0 = value;\n    }\n}\n\n#[test]\nfn tuple_struct_getter_setter() {\n    Python::attach(|py| {\n        let inst = Py::new(py, TupleClassGetterSetter(10)).unwrap();\n\n        py_assert!(py, inst, \"inst.num == 10\");\n        py_run!(py, inst, \"inst.num = 20\");\n        py_assert!(py, inst, \"inst.num == 20\");\n    });\n}\n\n#[pyclass(get_all, set_all)]\nstruct All {\n    num: i32,\n}\n\n#[test]\nfn get_set_all() {\n    Python::attach(|py| {\n        let inst = Py::new(py, All { num: 10 }).unwrap();\n\n        py_run!(py, inst, \"assert inst.num == 10\");\n        py_run!(py, inst, \"inst.num = 20; assert inst.num == 20\");\n    });\n}\n\n#[pyclass(get_all)]\nstruct All2 {\n    #[pyo3(set)]\n    num: i32,\n}\n\n#[test]\nfn get_all_and_set() {\n    Python::attach(|py| {\n        let inst = Py::new(py, All2 { num: 10 }).unwrap();\n\n        py_run!(py, inst, \"assert inst.num == 10\");\n        py_run!(py, inst, \"inst.num = 20; assert inst.num == 20\");\n    });\n}\n\n#[pyclass(unsendable)]\nstruct CellGetterSetter {\n    #[pyo3(get, set)]\n    cell_inner: Cell<i32>,\n}\n\n#[test]\nfn cell_getter_setter() {\n    let c = CellGetterSetter {\n        cell_inner: Cell::new(10),\n    };\n    Python::attach(|py| {\n        let inst = Py::new(py, c).unwrap();\n        let cell = Cell::new(20i32).into_pyobject(py).unwrap();\n\n        py_run!(py, cell, \"assert cell == 20\");\n        py_run!(py, inst, \"assert inst.cell_inner == 10\");\n        py_run!(\n            py,\n            inst,\n            \"inst.cell_inner = 20; assert inst.cell_inner == 20\"\n        );\n    });\n}\n\n#[test]\nfn borrowed_value_with_lifetime_of_self() {\n    #[pyclass]\n    struct BorrowedValue {}\n\n    #[pymethods]\n    impl BorrowedValue {\n        #[getter]\n        fn value(&self) -> &str {\n            \"value\"\n        }\n    }\n\n    Python::attach(|py| {\n        let inst = Py::new(py, BorrowedValue {}).unwrap();\n\n        py_run!(py, inst, \"assert inst.value == 'value'\");\n    });\n}\n\n#[test]\nfn frozen_py_field_get() {\n    #[pyclass(frozen)]\n    struct FrozenPyField {\n        #[pyo3(get)]\n        value: Py<PyString>,\n    }\n\n    Python::attach(|py| {\n        let inst = Py::new(\n            py,\n            FrozenPyField {\n                value: \"value\".into_pyobject(py).unwrap().unbind(),\n            },\n        )\n        .unwrap();\n\n        py_run!(py, inst, \"assert inst.value == 'value'\");\n    });\n}\n\n#[test]\nfn test_optional_setter() {\n    #[pyclass]\n    struct SimpleClass {\n        field: Option<u32>,\n    }\n\n    #[pymethods]\n    impl SimpleClass {\n        #[getter]\n        fn get_field(&self) -> Option<u32> {\n            self.field\n        }\n\n        #[setter]\n        fn set_field(&mut self, field: Option<u32>) {\n            self.field = field;\n        }\n    }\n\n    Python::attach(|py| {\n        let instance = Py::new(py, SimpleClass { field: None }).unwrap();\n        py_run!(py, instance, \"assert instance.field is None\");\n        py_run!(\n            py,\n            instance,\n            \"instance.field = 42; assert instance.field == 42\"\n        );\n        py_run!(\n            py,\n            instance,\n            \"instance.field = None; assert instance.field is None\"\n        );\n    })\n}\n"
  },
  {
    "path": "tests/test_inheritance.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\nuse pyo3::py_run;\nuse pyo3::types::IntoPyDict;\n\nmod test_utils;\n\n#[pyclass(subclass)]\nstruct BaseClass {\n    #[pyo3(get)]\n    val1: usize,\n}\n\n#[pyclass(subclass)]\nstruct SubclassAble {}\n\n#[test]\nfn subclass() {\n    Python::attach(|py| {\n        let d = [(\"SubclassAble\", py.get_type::<SubclassAble>())]\n            .into_py_dict(py)\n            .unwrap();\n\n        py.run(\n            c\"class A(SubclassAble): pass\\nassert issubclass(A, SubclassAble)\",\n            None,\n            Some(&d),\n        )\n        .map_err(|e| e.display(py))\n        .unwrap();\n    });\n}\n\n#[pymethods]\nimpl BaseClass {\n    #[new]\n    fn new() -> Self {\n        BaseClass { val1: 10 }\n    }\n    fn base_method(&self, x: usize) -> usize {\n        x * self.val1\n    }\n    fn base_set(&mut self, fn_: &Bound<'_, PyAny>) -> PyResult<()> {\n        let value: usize = fn_.call0()?.extract()?;\n        self.val1 = value;\n        Ok(())\n    }\n}\n\n#[pyclass(extends=BaseClass)]\nstruct SubClass {\n    #[pyo3(get)]\n    val2: usize,\n}\n\n#[pymethods]\nimpl SubClass {\n    #[new]\n    fn new() -> (Self, BaseClass) {\n        (SubClass { val2: 5 }, BaseClass { val1: 10 })\n    }\n    fn sub_method(&self, x: usize) -> usize {\n        x * self.val2\n    }\n    fn sub_set_and_ret(&mut self, x: usize) -> usize {\n        self.val2 = x;\n        x\n    }\n}\n\n#[test]\nfn inheritance_with_new_methods() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<SubClass>();\n        let inst = typeobj.call((), None).unwrap();\n        py_run!(py, inst, \"assert inst.val1 == 10; assert inst.val2 == 5\");\n    });\n}\n\n#[test]\nfn call_base_and_sub_methods() {\n    Python::attach(|py| {\n        let obj = Py::new(py, SubClass::new()).unwrap();\n        py_run!(\n            py,\n            obj,\n            r#\"\n    assert obj.base_method(10) == 100\n    assert obj.sub_method(10) == 50\n\"#\n        );\n    });\n}\n\n#[test]\nfn mutation_fails() {\n    Python::attach(|py| {\n        let obj = Py::new(py, SubClass::new()).unwrap();\n        let global = [(\"obj\", obj)].into_py_dict(py).unwrap();\n        let e = py\n            .run(\n                c\"obj.base_set(lambda: obj.sub_set_and_ret(1))\",\n                Some(&global),\n                None,\n            )\n            .unwrap_err();\n        assert_eq!(&e.to_string(), \"RuntimeError: Already borrowed\");\n    });\n}\n\n#[test]\nfn is_subclass_and_is_instance() {\n    Python::attach(|py| {\n        let sub_ty = py.get_type::<SubClass>();\n        let base_ty = py.get_type::<BaseClass>();\n        assert!(sub_ty.is_subclass_of::<BaseClass>().unwrap());\n        assert!(sub_ty.is_subclass(&base_ty).unwrap());\n\n        let obj = Bound::new(py, SubClass::new()).unwrap().into_any();\n        assert!(obj.is_instance_of::<SubClass>());\n        assert!(obj.is_instance_of::<BaseClass>());\n        assert!(obj.is_instance(&sub_ty).unwrap());\n        assert!(obj.is_instance(&base_ty).unwrap());\n    });\n}\n\n#[pyclass(subclass)]\nstruct BaseClassWithResult {\n    _val: usize,\n}\n\n#[pymethods]\nimpl BaseClassWithResult {\n    #[new]\n    fn new(value: isize) -> PyResult<Self> {\n        Ok(Self {\n            _val: std::convert::TryFrom::try_from(value)?,\n        })\n    }\n}\n\n#[pyclass(extends=BaseClassWithResult)]\nstruct SubClass2 {}\n\n#[pymethods]\nimpl SubClass2 {\n    #[new]\n    fn new(value: isize) -> PyResult<(Self, BaseClassWithResult)> {\n        let base = BaseClassWithResult::new(value)?;\n        Ok((Self {}, base))\n    }\n}\n\n#[test]\nfn handle_result_in_new() {\n    Python::attach(|py| {\n        let subclass = py.get_type::<SubClass2>();\n        py_run!(\n            py,\n            subclass,\n            r#\"\ntry:\n    subclass(-10)\n    assert False\nexcept ValueError as e:\n    pass\nexcept Exception as e:\n    raise e\n\"#\n        );\n    });\n}\n\n// Subclassing builtin types is not possible in the LIMITED API before 3.12\n#[cfg(any(not(Py_LIMITED_API), Py_3_12))]\nmod inheriting_native_type {\n    use super::*;\n    use pyo3::exceptions::PyException;\n\n    #[cfg(not(GraalPy))]\n    use {\n        pyo3::types::{PyCapsule, PyDict},\n        std::sync::{\n            atomic::{AtomicBool, Ordering},\n            Arc,\n        },\n    };\n\n    #[cfg(not(any(PyPy, GraalPy)))]\n    #[test]\n    fn inherit_set() {\n        use pyo3::types::PySet;\n\n        #[pyclass(extends=PySet)]\n        #[derive(Debug)]\n        struct SetWithName {\n            #[pyo3(get, name = \"name\")]\n            _name: &'static str,\n        }\n\n        #[pymethods]\n        impl SetWithName {\n            #[new]\n            fn new() -> Self {\n                SetWithName { _name: \"Hello :)\" }\n            }\n        }\n\n        Python::attach(|py| {\n            let set_sub = pyo3::Py::new(py, SetWithName::new()).unwrap();\n            py_run!(\n                py,\n                set_sub,\n                r#\"set_sub.add(10); assert list(set_sub) == [10]; assert set_sub.name == \"Hello :)\"\"#\n            );\n        });\n    }\n\n    #[cfg(not(GraalPy))]\n    #[pyclass(extends=PyDict)]\n    #[derive(Debug)]\n    struct DictWithName {\n        #[pyo3(get, name = \"name\")]\n        _name: &'static str,\n    }\n\n    #[cfg(not(GraalPy))]\n    #[pymethods]\n    impl DictWithName {\n        #[new]\n        fn new() -> Self {\n            DictWithName { _name: \"Hello :)\" }\n        }\n    }\n\n    #[cfg(not(GraalPy))]\n    #[test]\n    fn inherit_dict() {\n        Python::attach(|py| {\n            let dict_sub = pyo3::Py::new(py, DictWithName::new()).unwrap();\n            py_run!(\n                py,\n                dict_sub,\n                r#\"dict_sub[0] = 1; assert dict_sub[0] == 1; assert dict_sub.name == \"Hello :)\"\"#\n            );\n        });\n    }\n\n    #[cfg(not(GraalPy))]\n    #[test]\n    fn inherit_dict_drop() {\n        Python::attach(|py| {\n            let dropped = Arc::new(AtomicBool::new(false));\n            let destructor_drop = Arc::clone(&dropped);\n            let item = PyCapsule::new_with_destructor(py, 0, None, move |_, _| {\n                destructor_drop.store(true, Ordering::Relaxed)\n            })\n            .unwrap();\n\n            let dict_sub = pyo3::Py::new(py, DictWithName::new()).unwrap();\n            dict_sub.bind(py).set_item(\"foo\", &item).unwrap();\n            drop(item);\n            assert!(!dropped.load(Ordering::Relaxed));\n            drop(dict_sub);\n            assert!(dropped.load(Ordering::Relaxed));\n        })\n    }\n\n    #[pyclass(extends=PyException)]\n    struct CustomException {\n        #[pyo3(get)]\n        context: &'static str,\n    }\n\n    #[pymethods]\n    impl CustomException {\n        #[new]\n        fn new(_exc_arg: &Bound<'_, PyAny>) -> Self {\n            CustomException {\n                context: \"Hello :)\",\n            }\n        }\n    }\n\n    #[test]\n    fn custom_exception() {\n        Python::attach(|py| {\n            let cls = py.get_type::<CustomException>();\n            let dict = [(\"cls\", &cls)].into_py_dict(py).unwrap();\n            let res = py.run(\n            c\"e = cls('hello'); assert str(e) == 'hello'; assert e.context == 'Hello :)'; raise e\",\n            None,\n            Some(&dict)\n            );\n            let err = res.unwrap_err();\n            assert!(err.matches(py, &cls).unwrap(), \"{}\", err);\n\n            // catching the exception in Python also works:\n            py_run!(\n                py,\n                cls,\n                r#\"\n                    try:\n                        raise cls(\"foo\")\n                    except cls:\n                        pass\n                \"#\n            )\n        })\n    }\n\n    #[test]\n    #[cfg(Py_3_12)]\n    fn inherit_list() {\n        #[pyclass(extends=pyo3::types::PyList, subclass)]\n        struct ListWithName {\n            #[pyo3(get)]\n            name: &'static str,\n        }\n\n        #[pymethods]\n        impl ListWithName {\n            #[new]\n            fn new() -> Self {\n                Self { name: \"Hello :)\" }\n            }\n        }\n\n        #[pyclass(extends=ListWithName)]\n        struct SubListWithName {\n            #[pyo3(get)]\n            sub_name: &'static str,\n        }\n\n        #[pymethods]\n        impl SubListWithName {\n            #[new]\n            fn new() -> PyClassInitializer<Self> {\n                PyClassInitializer::from(ListWithName::new()).add_subclass(Self {\n                    sub_name: \"Sublist\",\n                })\n            }\n        }\n\n        Python::attach(|py| {\n            let list_with_name = pyo3::Bound::new(py, ListWithName::new()).unwrap();\n            let sub_list_with_name = pyo3::Bound::new(py, SubListWithName::new()).unwrap();\n            py_run!(\n                py,\n                list_with_name sub_list_with_name,\n                r#\"\n                    list_with_name.append(1)\n                    assert list_with_name[0] == 1\n                    assert list_with_name.name == \"Hello :)\", list_with_name.name\n\n                    sub_list_with_name.append(1)\n                    assert sub_list_with_name[0] == 1\n                    assert sub_list_with_name.name == \"Hello :)\", sub_list_with_name.name\n                    assert sub_list_with_name.sub_name == \"Sublist\", sub_list_with_name.sub_name\n                \"#\n            );\n        });\n    }\n}\n\n#[pyclass(subclass)]\nstruct SimpleClass {}\n\n#[pymethods]\nimpl SimpleClass {\n    #[new]\n    fn new() -> Self {\n        Self {}\n    }\n}\n\n#[test]\nfn test_subclass_ref_counts() {\n    // regression test for issue #1363\n    Python::attach(|py| {\n        #[expect(non_snake_case)]\n        let SimpleClass = py.get_type::<SimpleClass>();\n        py_run!(\n            py,\n            SimpleClass,\n            r#\"\n            import gc\n            import sys\n\n            class SubClass(SimpleClass):\n                pass\n\n            gc.collect()\n            count = sys.getrefcount(SubClass)\n\n            for i in range(1000):\n                c = SubClass()\n                del c\n\n            gc.collect()\n            after = sys.getrefcount(SubClass)\n            # depending on Python's GC the count may be either identical or exactly 1000 higher,\n            # both are expected values that are not representative of the issue.\n            #\n            # (With issue #1363 the count will be decreased.)\n            assert after == count or (after == count + 1000), f\"{after} vs {count}\"\n            \"#\n        );\n    })\n}\n"
  },
  {
    "path": "tests/test_intopyobject.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::types::{PyDict, PyList, PyString};\nuse pyo3::{prelude::*, py_run, IntoPyObject, IntoPyObjectExt};\nuse std::collections::HashMap;\nuse std::hash::Hash;\n\n#[macro_use]\nmod test_utils;\n\n#[derive(Debug, IntoPyObject)]\npub struct A<'py> {\n    s: String,\n    t: Bound<'py, PyString>,\n    p: Bound<'py, PyAny>,\n}\n\n#[test]\nfn test_named_fields_struct() {\n    Python::attach(|py| {\n        let a = A {\n            s: \"Hello\".into(),\n            t: PyString::new(py, \"World\"),\n            p: 42i32.into_pyobject(py).unwrap().into_any(),\n        };\n        let pya = a.into_pyobject(py).unwrap();\n        assert_eq!(\n            pya.get_item(\"s\")\n                .unwrap()\n                .unwrap()\n                .cast::<PyString>()\n                .unwrap(),\n            \"Hello\"\n        );\n        assert_eq!(\n            pya.get_item(\"t\")\n                .unwrap()\n                .unwrap()\n                .cast::<PyString>()\n                .unwrap(),\n            \"World\"\n        );\n        assert_eq!(\n            pya.get_item(\"p\")\n                .unwrap()\n                .unwrap()\n                .extract::<i32>()\n                .unwrap(),\n            42\n        );\n    });\n}\n\n#[derive(Debug, IntoPyObject)]\n#[pyo3(transparent)]\npub struct B<'a> {\n    test: &'a str,\n}\n\n#[test]\nfn test_transparent_named_field_struct() {\n    Python::attach(|py| {\n        let pyb = B { test: \"test\" }.into_pyobject(py).unwrap();\n        let b = pyb.extract::<String>().unwrap();\n        assert_eq!(b, \"test\");\n    });\n}\n\n#[derive(Debug, IntoPyObject)]\n#[pyo3(transparent)]\npub struct D<T> {\n    test: T,\n}\n\n#[test]\nfn test_generic_transparent_named_field_struct() {\n    Python::attach(|py| {\n        let pyd = D {\n            test: String::from(\"test\"),\n        }\n        .into_pyobject(py)\n        .unwrap();\n        let d = pyd.extract::<String>().unwrap();\n        assert_eq!(d, \"test\");\n\n        let pyd = D { test: 1usize }.into_pyobject(py).unwrap();\n        let d = pyd.extract::<usize>().unwrap();\n        assert_eq!(d, 1);\n    });\n}\n\n#[derive(Debug, IntoPyObject)]\npub struct GenericWithBound<K: Hash + Eq, V>(HashMap<K, V>);\n\n#[test]\nfn test_generic_with_bound() {\n    Python::attach(|py| {\n        let mut hash_map = HashMap::<String, i32>::new();\n        hash_map.insert(\"1\".into(), 1);\n        hash_map.insert(\"2\".into(), 2);\n        let map = GenericWithBound(hash_map).into_pyobject(py).unwrap();\n        assert_eq!(map.len(), 2);\n        assert_eq!(\n            map.get_item(\"1\")\n                .unwrap()\n                .unwrap()\n                .extract::<i32>()\n                .unwrap(),\n            1\n        );\n        assert_eq!(\n            map.get_item(\"2\")\n                .unwrap()\n                .unwrap()\n                .extract::<i32>()\n                .unwrap(),\n            2\n        );\n        assert!(map.get_item(\"3\").unwrap().is_none());\n    });\n}\n\n#[derive(Debug, IntoPyObject)]\npub struct Tuple(String, usize);\n\n#[test]\nfn test_tuple_struct() {\n    Python::attach(|py| {\n        let tup = Tuple(String::from(\"test\"), 1).into_pyobject(py).unwrap();\n        assert!(tup.extract::<(usize, String)>().is_err());\n        let tup = tup.extract::<(String, usize)>().unwrap();\n        assert_eq!(tup.0, \"test\");\n        assert_eq!(tup.1, 1);\n    });\n}\n\n#[derive(Debug, IntoPyObject)]\npub struct TransparentTuple(String);\n\n#[test]\nfn test_transparent_tuple_struct() {\n    Python::attach(|py| {\n        let tup = TransparentTuple(String::from(\"test\"))\n            .into_pyobject(py)\n            .unwrap();\n        assert!(tup.extract::<(String,)>().is_err());\n        let tup = tup.extract::<String>().unwrap();\n        assert_eq!(tup, \"test\");\n    });\n}\n\nfn phantom_into_py<'py, T>(\n    _: std::borrow::Cow<'_, std::marker::PhantomData<T>>,\n    py: Python<'py>,\n) -> PyResult<Bound<'py, PyAny>> {\n    std::any::type_name::<T>().into_bound_py_any(py)\n}\n\n#[derive(Debug, IntoPyObject, IntoPyObjectRef)]\npub enum Foo<'py> {\n    TupleVar(\n        usize,\n        String,\n        #[pyo3(into_py_with = phantom_into_py::<()>)] std::marker::PhantomData<()>,\n    ),\n    StructVar {\n        test: Bound<'py, PyString>,\n    },\n    #[pyo3(transparent)]\n    TransparentTuple(usize),\n    #[pyo3(transparent)]\n    TransparentStructVar {\n        a: Option<String>,\n    },\n}\n\n#[test]\nfn test_enum() {\n    Python::attach(|py| {\n        let foo = Foo::TupleVar(1, \"test\".into(), std::marker::PhantomData)\n            .into_pyobject(py)\n            .unwrap();\n        assert_eq!(\n            foo.extract::<(usize, String, String)>().unwrap(),\n            (1, String::from(\"test\"), String::from(\"()\"))\n        );\n\n        let foo = Foo::StructVar {\n            test: PyString::new(py, \"test\"),\n        }\n        .into_pyobject(py)\n        .unwrap()\n        .cast_into::<PyDict>()\n        .unwrap();\n\n        assert_eq!(\n            foo.get_item(\"test\")\n                .unwrap()\n                .unwrap()\n                .cast_into::<PyString>()\n                .unwrap(),\n            \"test\"\n        );\n\n        let foo = Foo::TransparentTuple(1).into_pyobject(py).unwrap();\n        assert_eq!(foo.extract::<usize>().unwrap(), 1);\n\n        let foo = Foo::TransparentStructVar { a: None }\n            .into_pyobject(py)\n            .unwrap();\n        assert!(foo.is_none());\n    });\n}\n\n#[derive(Debug, IntoPyObject, IntoPyObjectRef)]\npub struct Zap {\n    #[pyo3(item)]\n    name: String,\n\n    #[pyo3(into_py_with = zap_into_py, item(\"my_object\"))]\n    some_object_length: usize,\n}\n\nfn zap_into_py<'py>(\n    len: std::borrow::Cow<'_, usize>,\n    py: Python<'py>,\n) -> PyResult<Bound<'py, PyAny>> {\n    Ok(PyList::new(py, 1..*len + 1)?.into_any())\n}\n\n#[test]\nfn test_into_py_with() {\n    Python::attach(|py| {\n        let zap = Zap {\n            name: \"whatever\".into(),\n            some_object_length: 3,\n        };\n\n        let py_zap_ref = (&zap).into_pyobject(py).unwrap();\n        let py_zap = zap.into_pyobject(py).unwrap();\n\n        py_run!(\n            py,\n            py_zap_ref,\n            \"assert py_zap_ref == {'name': 'whatever', 'my_object': [1, 2, 3]},f'{py_zap_ref}'\"\n        );\n        py_run!(\n            py,\n            py_zap,\n            \"assert py_zap == {'name': 'whatever', 'my_object': [1, 2, 3]},f'{py_zap}'\"\n        );\n    });\n}\n\n#[test]\nfn test_struct_into_py_rename_all() {\n    #[derive(IntoPyObject, IntoPyObjectRef)]\n    #[pyo3(rename_all = \"camelCase\")]\n    struct Foo {\n        foo_bar: String,\n        #[pyo3(item(\"BAZ\"))]\n        baz: usize,\n        #[pyo3(item)]\n        long_field_name: f32,\n    }\n\n    let foo = Foo {\n        foo_bar: \"foobar\".into(),\n        baz: 42,\n        long_field_name: 0.0,\n    };\n\n    Python::attach(|py| {\n        let py_foo_ref = (&foo).into_pyobject(py).unwrap();\n        let py_foo = foo.into_pyobject(py).unwrap();\n\n        py_run!(\n            py,\n            py_foo_ref,\n            \"assert py_foo_ref == {'fooBar': 'foobar', 'BAZ': 42, 'longFieldName': 0},f'{py_foo_ref}'\"\n        );\n        py_run!(\n            py,\n            py_foo,\n            \"assert py_foo == {'fooBar': 'foobar', 'BAZ': 42, 'longFieldName': 0},f'{py_foo}'\"\n        );\n    });\n}\n"
  },
  {
    "path": "tests/test_macro_docs.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\nuse pyo3::types::IntoPyDict;\n\n#[macro_use]\nmod test_utils;\n\n#[pyclass]\n/// The MacroDocs class.\n#[doc = concat!(\"Some macro \", \"class \", \"docs.\")]\n/// A very interesting type!\nstruct MacroDocs {}\n\n#[pymethods]\nimpl MacroDocs {\n    #[doc = concat!(\"A macro \", \"example.\")]\n    /// With mixed doc types.\n    fn macro_doc(&self) {}\n}\n\n#[test]\nfn meth_doc() {\n    Python::attach(|py| {\n        let d = [(\"C\", py.get_type::<MacroDocs>())]\n            .into_py_dict(py)\n            .unwrap();\n        py_assert!(\n            py,\n            *d,\n            \"C.__doc__ == 'The MacroDocs class.\\\\nSome macro class docs.\\\\nA very interesting type!'\"\n        );\n        py_assert!(\n            py,\n            *d,\n            \"C.macro_doc.__doc__ == 'A macro example.\\\\nWith mixed doc types.'\"\n        );\n    });\n}\n"
  },
  {
    "path": "tests/test_macros.rs",
    "content": "#![cfg(feature = \"macros\")]\n\n//! Ensure that pyo3 macros can be used inside macro_rules!\n\nuse pyo3::prelude::*;\n\n#[macro_use]\nmod test_utils;\n\nmacro_rules! make_struct_using_macro {\n    // Ensure that one doesn't need to fall back on the escape type: tt\n    // in order to macro create pyclass.\n    ($class_name:ident, $py_name:literal) => {\n        #[pyclass(name=$py_name, subclass)]\n        struct $class_name {}\n    };\n}\n\nmake_struct_using_macro!(MyBaseClass, \"MyClass\");\n\nmacro_rules! set_extends_via_macro {\n    ($class_name:ident, $base_class:path) => {\n        // Try and pass a variable into the extends parameter\n        #[allow(dead_code)]\n        #[pyclass(extends=$base_class)]\n        struct $class_name {}\n    };\n}\n\nset_extends_via_macro!(MyClass2, MyBaseClass);\n\n//\n// Check that pyfunctions and text_signature can be called with macro arguments.\n//\n\nmacro_rules! fn_macro {\n    ($sig:literal, $a_exp:expr, $b_exp:expr, $c_exp: expr) => {\n        // Try and pass a variable into the signature parameter\n        #[pyfunction(signature = ($a_exp, $b_exp, *, $c_exp))]\n        #[pyo3(text_signature = $sig)]\n        fn my_function_in_macro(a: i32, b: Option<i32>, c: i32) {\n            let _ = (a, b, c);\n        }\n    };\n}\n\nfn_macro!(\"(a, b=None, *, c=42)\", a, b = None, c = 42);\n\nmacro_rules! property_rename_via_macro {\n    ($prop_name:ident) => {\n        #[pyclass]\n        struct ClassWithProperty {\n            member: u64,\n        }\n\n        #[pymethods]\n        impl ClassWithProperty {\n            #[getter($prop_name)]\n            fn get_member(&self) -> u64 {\n                self.member\n            }\n\n            #[setter($prop_name)]\n            fn set_member(&mut self, member: u64) {\n                self.member = member;\n            }\n        }\n    };\n}\n\nproperty_rename_via_macro!(my_new_property_name);\n\n#[test]\nfn test_macro_rules_interactions() {\n    Python::attach(|py| {\n        let my_base = py.get_type::<MyBaseClass>();\n        py_assert!(py, my_base, \"my_base.__name__ == 'MyClass'\");\n\n        let my_func = wrap_pyfunction!(my_function_in_macro, py).unwrap();\n        py_assert!(\n            py,\n            my_func,\n            \"my_func.__text_signature__ == '(a, b=None, *, c=42)'\"\n        );\n\n        let renamed_prop = py.get_type::<ClassWithProperty>();\n        py_assert!(\n            py,\n            renamed_prop,\n            \"hasattr(renamed_prop, 'my_new_property_name')\"\n        );\n    });\n}\n"
  },
  {
    "path": "tests/test_mapping.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse std::collections::HashMap;\n\nuse pyo3::exceptions::PyKeyError;\nuse pyo3::prelude::*;\nuse pyo3::py_run;\nuse pyo3::types::IntoPyDict;\nuse pyo3::types::PyList;\nuse pyo3::types::PyMapping;\nuse pyo3::types::PySequence;\n\nmod test_utils;\n\n#[pyclass(mapping)]\nstruct Mapping {\n    index: HashMap<String, usize>,\n}\n\n#[pymethods]\nimpl Mapping {\n    #[new]\n    #[pyo3(signature=(elements=None))]\n    fn new(elements: Option<&Bound<'_, PyList>>) -> PyResult<Self> {\n        if let Some(pylist) = elements {\n            let mut elems = HashMap::with_capacity(pylist.len());\n            for (i, pyelem) in pylist.into_iter().enumerate() {\n                let elem = pyelem.extract()?;\n                elems.insert(elem, i);\n            }\n            Ok(Self { index: elems })\n        } else {\n            Ok(Self {\n                index: HashMap::new(),\n            })\n        }\n    }\n\n    fn __len__(&self) -> usize {\n        self.index.len()\n    }\n\n    fn __getitem__(&self, query: String) -> PyResult<usize> {\n        self.index\n            .get(&query)\n            .copied()\n            .ok_or_else(|| PyKeyError::new_err(\"unknown key\"))\n    }\n\n    fn __setitem__(&mut self, key: String, value: usize) {\n        self.index.insert(key, value);\n    }\n\n    fn __delitem__(&mut self, key: String) -> PyResult<()> {\n        if self.index.remove(&key).is_none() {\n            Err(PyKeyError::new_err(\"unknown key\"))\n        } else {\n            Ok(())\n        }\n    }\n\n    #[pyo3(signature=(key, default=None))]\n    fn get(\n        &self,\n        py: Python<'_>,\n        key: &str,\n        default: Option<Py<PyAny>>,\n    ) -> PyResult<Option<Py<PyAny>>> {\n        match self.index.get(key) {\n            Some(value) => Ok(Some(value.into_pyobject(py)?.into_any().unbind())),\n            None => Ok(default),\n        }\n    }\n}\n\n/// Return a dict with `m = Mapping(['1', '2', '3'])`.\nfn map_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> {\n    let d = [(\"Mapping\", py.get_type::<Mapping>())]\n        .into_py_dict(py)\n        .unwrap();\n    py_run!(py, *d, \"m = Mapping(['1', '2', '3'])\");\n    d\n}\n\n#[test]\nfn test_getitem() {\n    Python::attach(|py| {\n        let d = map_dict(py);\n\n        py_assert!(py, *d, \"m['1'] == 0\");\n        py_assert!(py, *d, \"m['2'] == 1\");\n        py_assert!(py, *d, \"m['3'] == 2\");\n        py_expect_exception!(py, *d, \"print(m['4'])\", PyKeyError);\n    });\n}\n\n#[test]\nfn test_setitem() {\n    Python::attach(|py| {\n        let d = map_dict(py);\n\n        py_run!(py, *d, \"m['1'] = 4; assert m['1'] == 4\");\n        py_run!(py, *d, \"m['0'] = 0; assert m['0'] == 0\");\n        py_assert!(py, *d, \"len(m) == 4\");\n        py_expect_exception!(py, *d, \"m[0] = 'hello'\", PyTypeError);\n        py_expect_exception!(py, *d, \"m[0] = -1\", PyTypeError);\n    });\n}\n\n#[test]\nfn test_delitem() {\n    Python::attach(|py| {\n        let d = map_dict(py);\n        py_run!(\n            py,\n            *d,\n            \"del m['1']; assert len(m) == 2 and m['2'] == 1 and m['3'] == 2\"\n        );\n        py_expect_exception!(py, *d, \"del m[-1]\", PyTypeError);\n        py_expect_exception!(py, *d, \"del m['4']\", PyKeyError);\n    });\n}\n\n#[test]\nfn mapping_is_not_sequence() {\n    Python::attach(|py| {\n        let mut index = HashMap::new();\n        index.insert(\"Foo\".into(), 1);\n        index.insert(\"Bar\".into(), 2);\n        let m = Py::new(py, Mapping { index }).unwrap();\n\n        PyMapping::register::<Mapping>(py).unwrap();\n\n        assert!(m.bind(py).cast::<PyMapping>().is_ok());\n        assert!(m.bind(py).cast::<PySequence>().is_err());\n    });\n}\n"
  },
  {
    "path": "tests/test_methods.rs",
    "content": "#![cfg(feature = \"macros\")]\n\n#[cfg(any(not(Py_LIMITED_API), Py_3_12))]\nuse pyo3::exceptions::PyWarning;\nuse pyo3::exceptions::{PyFutureWarning, PyUserWarning};\nuse pyo3::prelude::*;\nuse pyo3::py_run;\nuse pyo3::types::PySequence;\nuse pyo3::types::{IntoPyDict, PyDict, PyList, PySet, PyString, PyTuple, PyType};\nuse pyo3::BoundObject;\nuse pyo3_macros::pyclass;\n\nuse crate::test_utils::CatchWarnings;\n\nmod test_utils;\n\n#[pyclass]\nstruct InstanceMethod {\n    member: i32,\n}\n\n#[pymethods]\nimpl InstanceMethod {\n    /// Test method\n    fn method(&self) -> i32 {\n        self.member\n    }\n\n    // Checks that &Self works\n    fn add_other(&self, other: &Self) -> i32 {\n        self.member + other.member\n    }\n}\n\n#[test]\nfn instance_method() {\n    Python::attach(|py| {\n        let obj = Bound::new(py, InstanceMethod { member: 42 }).unwrap();\n        let obj_ref = obj.borrow();\n        assert_eq!(obj_ref.method(), 42);\n        py_assert!(py, obj, \"obj.method() == 42\");\n        py_assert!(py, obj, \"obj.add_other(obj) == 84\");\n        py_assert!(py, obj, \"obj.method.__doc__ == 'Test method'\");\n    });\n}\n\n#[pyclass]\nstruct InstanceMethodWithArgs {\n    member: i32,\n}\n\n#[pymethods]\nimpl InstanceMethodWithArgs {\n    fn method(&self, multiplier: i32) -> i32 {\n        self.member * multiplier\n    }\n}\n\n#[test]\nfn instance_method_with_args() {\n    Python::attach(|py| {\n        let obj = Bound::new(py, InstanceMethodWithArgs { member: 7 }).unwrap();\n        let obj_ref = obj.borrow();\n        assert_eq!(obj_ref.method(6), 42);\n        py_assert!(py, obj, \"obj.method(3) == 21\");\n        py_assert!(py, obj, \"obj.method(multiplier=6) == 42\");\n    });\n}\n\n#[pyclass]\nstruct ClassMethod {}\n\n#[pymethods]\nimpl ClassMethod {\n    #[new]\n    fn new() -> Self {\n        ClassMethod {}\n    }\n\n    #[classmethod]\n    /// Test class method.\n    fn method(cls: &Bound<'_, PyType>) -> PyResult<String> {\n        Ok(format!(\"{}.method()!\", cls.qualname()?))\n    }\n\n    #[classmethod]\n    fn method_owned(cls: Py<PyType>, py: Python<'_>) -> PyResult<String> {\n        Ok(format!(\"{}.method_owned()!\", cls.bind(py).qualname()?))\n    }\n}\n\n#[test]\nfn class_method() {\n    Python::attach(|py| {\n        let d = [(\"C\", py.get_type::<ClassMethod>())]\n            .into_py_dict(py)\n            .unwrap();\n        py_assert!(py, *d, \"C.method() == 'ClassMethod.method()!'\");\n        py_assert!(py, *d, \"C().method() == 'ClassMethod.method()!'\");\n        py_assert!(\n            py,\n            *d,\n            \"C().method_owned() == 'ClassMethod.method_owned()!'\"\n        );\n        py_assert!(py, *d, \"C.method.__doc__ == 'Test class method.'\");\n        py_assert!(py, *d, \"C().method.__doc__ == 'Test class method.'\");\n    });\n}\n\n#[pyclass]\nstruct ClassMethodWithArgs {}\n\n#[pymethods]\nimpl ClassMethodWithArgs {\n    #[classmethod]\n    fn method(cls: &Bound<'_, PyType>, input: &Bound<'_, PyString>) -> PyResult<String> {\n        Ok(format!(\"{}.method({})\", cls.qualname()?, input))\n    }\n}\n\n#[test]\nfn class_method_with_args() {\n    Python::attach(|py| {\n        let d = [(\"C\", py.get_type::<ClassMethodWithArgs>())]\n            .into_py_dict(py)\n            .unwrap();\n        py_assert!(\n            py,\n            *d,\n            \"C.method('abc') == 'ClassMethodWithArgs.method(abc)'\"\n        );\n    });\n}\n\n#[pyclass]\nstruct StaticMethod {}\n\n#[pymethods]\nimpl StaticMethod {\n    #[new]\n    fn new() -> Self {\n        StaticMethod {}\n    }\n\n    #[staticmethod]\n    /// Test static method.\n    fn method(_py: Python<'_>) -> &'static str {\n        \"StaticMethod.method()!\"\n    }\n}\n\n#[test]\nfn static_method() {\n    Python::attach(|py| {\n        assert_eq!(StaticMethod::method(py), \"StaticMethod.method()!\");\n\n        let d = [(\"C\", py.get_type::<StaticMethod>())]\n            .into_py_dict(py)\n            .unwrap();\n        py_assert!(py, *d, \"C.method() == 'StaticMethod.method()!'\");\n        py_assert!(py, *d, \"C().method() == 'StaticMethod.method()!'\");\n        py_assert!(py, *d, \"C.method.__doc__ == 'Test static method.'\");\n        py_assert!(py, *d, \"C().method.__doc__ == 'Test static method.'\");\n    });\n}\n\n#[pyclass]\nstruct StaticMethodWithArgs {}\n\n#[pymethods]\nimpl StaticMethodWithArgs {\n    #[staticmethod]\n    fn method(_py: Python<'_>, input: i32) -> String {\n        format!(\"0x{input:x}\")\n    }\n}\n\n#[test]\nfn static_method_with_args() {\n    Python::attach(|py| {\n        assert_eq!(StaticMethodWithArgs::method(py, 1234), \"0x4d2\");\n\n        let d = [(\"C\", py.get_type::<StaticMethodWithArgs>())]\n            .into_py_dict(py)\n            .unwrap();\n        py_assert!(py, *d, \"C.method(1337) == '0x539'\");\n    });\n}\n\n#[pyclass]\nstruct MethSignature {}\n\n#[pymethods]\nimpl MethSignature {\n    #[pyo3(signature = (test = None))]\n    fn get_optional(&self, test: Option<i32>) -> i32 {\n        test.unwrap_or(10)\n    }\n    #[pyo3(signature = (test = None))]\n    fn get_optional2(&self, test: Option<i32>) -> Option<i32> {\n        test\n    }\n    #[pyo3(signature=(_t1 = None, t2 = None, _t3 = None))]\n    fn get_optional_positional(\n        &self,\n        _t1: Option<i32>,\n        t2: Option<i32>,\n        _t3: Option<i32>,\n    ) -> Option<i32> {\n        t2\n    }\n\n    #[pyo3(signature = (test = 10))]\n    fn get_default(&self, test: i32) -> i32 {\n        test\n    }\n    #[pyo3(signature = (*, test = 10))]\n    fn get_kwarg(&self, test: i32) -> i32 {\n        test\n    }\n    #[pyo3(signature = (*args, **kwargs))]\n    fn get_kwargs<'py>(\n        &self,\n        py: Python<'py>,\n        args: &Bound<'py, PyTuple>,\n        kwargs: Option<&Bound<'py, PyDict>>,\n    ) -> PyResult<Bound<'py, PyAny>> {\n        [\n            args.as_any().clone(),\n            kwargs.into_pyobject(py)?.into_any().into_bound(),\n        ]\n        .into_pyobject(py)\n    }\n\n    #[pyo3(signature = (a, *args, **kwargs))]\n    fn get_pos_arg_kw<'py>(\n        &self,\n        py: Python<'py>,\n        a: i32,\n        args: &Bound<'py, PyTuple>,\n        kwargs: Option<&Bound<'py, PyDict>>,\n    ) -> PyResult<Bound<'py, PyAny>> {\n        [\n            a.into_pyobject(py)?.into_any().into_bound(),\n            args.as_any().clone(),\n            kwargs.into_pyobject(py)?.into_any().into_bound(),\n        ]\n        .into_pyobject(py)\n    }\n\n    #[pyo3(signature = (a, b, /))]\n    fn get_pos_only(&self, a: i32, b: i32) -> i32 {\n        a + b\n    }\n\n    #[pyo3(signature = (a, /, b))]\n    fn get_pos_only_and_pos(&self, a: i32, b: i32) -> i32 {\n        a + b\n    }\n\n    #[pyo3(signature = (a, /, b, c = 5))]\n    fn get_pos_only_and_pos_and_kw(&self, a: i32, b: i32, c: i32) -> i32 {\n        a + b + c\n    }\n\n    #[pyo3(signature = (a, /, *, b))]\n    fn get_pos_only_and_kw_only(&self, a: i32, b: i32) -> i32 {\n        a + b\n    }\n\n    #[pyo3(signature = (a, /, *, b = 3))]\n    fn get_pos_only_and_kw_only_with_default(&self, a: i32, b: i32) -> i32 {\n        a + b\n    }\n\n    #[pyo3(signature = (a, /, b, *, c, d = 5))]\n    fn get_all_arg_types_together(&self, a: i32, b: i32, c: i32, d: i32) -> i32 {\n        a + b + c + d\n    }\n\n    #[pyo3(signature = (a, /, *args))]\n    fn get_pos_only_with_varargs(&self, a: i32, args: Vec<i32>) -> i32 {\n        a + args.iter().sum::<i32>()\n    }\n\n    #[pyo3(signature = (a, /, **kwargs))]\n    fn get_pos_only_with_kwargs(\n        &self,\n        py: Python<'_>,\n        a: i32,\n        kwargs: Option<&Bound<'_, PyDict>>,\n    ) -> PyResult<Py<PyAny>> {\n        [\n            a.into_pyobject(py)?.into_any().into_bound(),\n            kwargs.into_pyobject(py)?.into_any().into_bound(),\n        ]\n        .into_pyobject(py)\n        .map(Bound::unbind)\n    }\n\n    #[pyo3(signature = (a=0, /, **kwargs))]\n    fn get_optional_pos_only_with_kwargs(\n        &self,\n        py: Python<'_>,\n        a: i32,\n        kwargs: Option<&Bound<'_, PyDict>>,\n    ) -> PyResult<Py<PyAny>> {\n        [\n            a.into_pyobject(py)?.into_any().into_bound(),\n            kwargs.into_pyobject(py)?.into_any().into_bound(),\n        ]\n        .into_pyobject(py)\n        .map(Bound::unbind)\n    }\n\n    #[pyo3(signature = (*, a = 2, b = 3))]\n    fn get_kwargs_only_with_defaults(&self, a: i32, b: i32) -> i32 {\n        a + b\n    }\n\n    #[pyo3(signature = (*, a, b))]\n    fn get_kwargs_only(&self, a: i32, b: i32) -> i32 {\n        a + b\n    }\n\n    #[pyo3(signature = (*, a = 1, b))]\n    fn get_kwargs_only_with_some_default(&self, a: i32, b: i32) -> i32 {\n        a + b\n    }\n\n    #[pyo3(signature = (*args, a))]\n    fn get_args_and_required_keyword(\n        &self,\n        py: Python<'_>,\n        args: &Bound<'_, PyTuple>,\n        a: i32,\n    ) -> PyResult<Py<PyAny>> {\n        (args, a)\n            .into_pyobject(py)\n            .map(BoundObject::into_any)\n            .map(Bound::unbind)\n    }\n\n    #[pyo3(signature = (a, b = 2, *, c = 3))]\n    fn get_pos_arg_kw_sep1(&self, a: i32, b: i32, c: i32) -> i32 {\n        a + b + c\n    }\n\n    #[pyo3(signature = (a, *, b = 2, c = 3))]\n    fn get_pos_arg_kw_sep2(&self, a: i32, b: i32, c: i32) -> i32 {\n        a + b + c\n    }\n\n    #[pyo3(signature = (a, **kwargs))]\n    fn get_pos_kw(\n        &self,\n        py: Python<'_>,\n        a: i32,\n        kwargs: Option<&Bound<'_, PyDict>>,\n    ) -> PyResult<Py<PyAny>> {\n        [\n            a.into_pyobject(py)?.into_any().into_bound(),\n            kwargs.into_pyobject(py)?.into_any().into_bound(),\n        ]\n        .into_pyobject(py)\n        .map(Bound::unbind)\n    }\n\n    // \"args\" can be anything that can be extracted from PyTuple\n    #[pyo3(signature = (*args))]\n    fn args_as_vec(&self, args: Vec<i32>) -> i32 {\n        args.iter().sum()\n    }\n}\n\n#[test]\nfn meth_signature() {\n    Python::attach(|py| {\n        let inst = Py::new(py, MethSignature {}).unwrap();\n\n        py_run!(py, inst, \"assert inst.get_optional() == 10\");\n        py_run!(py, inst, \"assert inst.get_optional(100) == 100\");\n        py_run!(py, inst, \"assert inst.get_optional2() == None\");\n        py_run!(py, inst, \"assert inst.get_optional2(100) == 100\");\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_optional_positional(1, 2, 3) == 2\"\n        );\n        py_run!(py, inst, \"assert inst.get_optional_positional(1) == None\");\n        py_run!(py, inst, \"assert inst.get_default() == 10\");\n        py_run!(py, inst, \"assert inst.get_default(100) == 100\");\n        py_run!(py, inst, \"assert inst.get_kwarg() == 10\");\n        py_expect_exception!(py, inst, \"inst.get_kwarg(100)\", PyTypeError);\n        py_run!(py, inst, \"assert inst.get_kwarg(test=100) == 100\");\n        py_run!(py, inst, \"assert inst.get_kwargs() == [(), None]\");\n        py_run!(py, inst, \"assert inst.get_kwargs(1,2,3) == [(1,2,3), None]\");\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_kwargs(t=1,n=2) == [(), {'t': 1, 'n': 2}]\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_kwargs(1,2,3,t=1,n=2) == [(1,2,3), {'t': 1, 'n': 2}]\"\n        );\n\n        py_run!(py, inst, \"assert inst.get_pos_arg_kw(1) == [1, (), None]\");\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_arg_kw(1, 2, 3) == [1, (2, 3), None]\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_arg_kw(1, b=2) == [1, (), {'b': 2}]\"\n        );\n        py_run!(py, inst, \"assert inst.get_pos_arg_kw(a=1) == [1, (), None]\");\n        py_expect_exception!(py, inst, \"inst.get_pos_arg_kw()\", PyTypeError);\n        py_expect_exception!(py, inst, \"inst.get_pos_arg_kw(1, a=1)\", PyTypeError);\n        py_expect_exception!(py, inst, \"inst.get_pos_arg_kw(b=2)\", PyTypeError);\n\n        py_run!(py, inst, \"assert inst.get_pos_only(10, 11) == 21\");\n        py_expect_exception!(py, inst, \"inst.get_pos_only(10, b = 11)\", PyTypeError);\n        py_expect_exception!(py, inst, \"inst.get_pos_only(a = 10, b = 11)\", PyTypeError);\n\n        py_run!(py, inst, \"assert inst.get_pos_only_and_pos(10, 11) == 21\");\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_and_pos(10, b = 11) == 21\"\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_pos_only_and_pos(a = 10, b = 11)\",\n            PyTypeError\n        );\n\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_and_pos_and_kw(10, 11) == 26\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_and_pos_and_kw(10, b = 11) == 26\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_and_pos_and_kw(10, 11, c = 0) == 21\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_and_pos_and_kw(10, b = 11, c = 0) == 21\"\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_pos_only_and_pos_and_kw(a = 10, b = 11)\",\n            PyTypeError\n        );\n\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_and_kw_only(10, b = 11) == 21\"\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_pos_only_and_kw_only(10, 11)\",\n            PyTypeError\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_pos_only_and_kw_only(a = 10, b = 11)\",\n            PyTypeError\n        );\n\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_and_kw_only_with_default(10) == 13\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_and_kw_only_with_default(10, b = 11) == 21\"\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_pos_only_and_kw_only_with_default(10, 11)\",\n            PyTypeError\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_pos_only_and_kw_only_with_default(a = 10, b = 11)\",\n            PyTypeError\n        );\n\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_all_arg_types_together(10, 10, c = 10) == 35\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_all_arg_types_together(10, 10, c = 10, d = 10) == 40\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_all_arg_types_together(10, b = 10, c = 10, d = 10) == 40\"\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_all_arg_types_together(10, 10, 10)\",\n            PyTypeError\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_all_arg_types_together(a = 10, b = 10, c = 10)\",\n            PyTypeError\n        );\n\n        py_run!(py, inst, \"assert inst.get_pos_only_with_varargs(10) == 10\");\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_with_varargs(10, 10) == 20\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_with_varargs(10, 10, 10, 10, 10) == 50\"\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_pos_only_with_varargs(a = 10)\",\n            PyTypeError\n        );\n\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_with_kwargs(10) == [10, None]\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_only_with_kwargs(10, b = 10) == [10, {'b': 10}]\"\n        );\n        py_run!(\n        py,\n        inst,\n        \"assert inst.get_pos_only_with_kwargs(10, b = 10, c = 10, d = 10, e = 10) == [10, {'b': 10, 'c': 10, 'd': 10, 'e': 10}]\"\n    );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_pos_only_with_kwargs(a = 10)\",\n            PyTypeError\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_pos_only_with_kwargs(a = 10, b = 10)\",\n            PyTypeError\n        );\n\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_optional_pos_only_with_kwargs() == [0, None]\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_optional_pos_only_with_kwargs(10) == [10, None]\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_optional_pos_only_with_kwargs(a=10) == [0, {'a': 10}]\"\n        );\n\n        py_run!(py, inst, \"assert inst.get_kwargs_only_with_defaults() == 5\");\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_kwargs_only_with_defaults(a = 8) == 11\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_kwargs_only_with_defaults(b = 8) == 10\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_kwargs_only_with_defaults(a = 1, b = 1) == 2\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_kwargs_only_with_defaults(b = 1, a = 1) == 2\"\n        );\n\n        py_run!(py, inst, \"assert inst.get_kwargs_only(a = 1, b = 1) == 2\");\n        py_run!(py, inst, \"assert inst.get_kwargs_only(b = 1, a = 1) == 2\");\n\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_kwargs_only_with_some_default(a = 2, b = 1) == 3\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_kwargs_only_with_some_default(b = 1) == 2\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_kwargs_only_with_some_default(b = 1, a = 2) == 3\"\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_kwargs_only_with_some_default()\",\n            PyTypeError\n        );\n\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_args_and_required_keyword(1, 2, a=3) == ((1, 2), 3)\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_args_and_required_keyword(a=1) == ((), 1)\"\n        );\n        py_expect_exception!(\n            py,\n            inst,\n            \"inst.get_args_and_required_keyword()\",\n            PyTypeError\n        );\n\n        py_run!(py, inst, \"assert inst.get_pos_arg_kw_sep1(1) == 6\");\n        py_run!(py, inst, \"assert inst.get_pos_arg_kw_sep1(1, 2) == 6\");\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_arg_kw_sep1(1, 2, c=13) == 16\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_arg_kw_sep1(a=1, b=2, c=13) == 16\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_arg_kw_sep1(b=2, c=13, a=1) == 16\"\n        );\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_arg_kw_sep1(c=13, b=2, a=1) == 16\"\n        );\n        py_expect_exception!(py, inst, \"inst.get_pos_arg_kw_sep1(1, 2, 3)\", PyTypeError);\n\n        py_run!(py, inst, \"assert inst.get_pos_arg_kw_sep2(1) == 6\");\n        py_run!(\n            py,\n            inst,\n            \"assert inst.get_pos_arg_kw_sep2(1, b=12, c=13) == 26\"\n        );\n        py_expect_exception!(py, inst, \"inst.get_pos_arg_kw_sep2(1, 2)\", PyTypeError);\n\n        py_run!(py, inst, \"assert inst.get_pos_kw(1, b=2) == [1, {'b': 2}]\");\n        py_expect_exception!(py, inst, \"inst.get_pos_kw(1,2)\", PyTypeError);\n\n        py_run!(py, inst, \"assert inst.args_as_vec(1,2,3) == 6\");\n    });\n}\n\n#[pyclass]\n/// A class with \"documentation\".\nstruct MethDocs {\n    x: i32,\n}\n\n#[pymethods]\nimpl MethDocs {\n    /// A method with \"documentation\" as well.\n    fn method(&self) -> i32 {\n        0\n    }\n\n    #[getter]\n    /// `int`: a very \"important\" member of 'this' instance.\n    fn get_x(&self) -> i32 {\n        self.x\n    }\n}\n\n#[test]\nfn meth_doc() {\n    Python::attach(|py| {\n        let d = [(\"C\", py.get_type::<MethDocs>())].into_py_dict(py).unwrap();\n        py_assert!(py, *d, \"C.__doc__ == 'A class with \\\"documentation\\\".'\");\n        py_assert!(\n            py,\n            *d,\n            \"C.method.__doc__ == 'A method with \\\"documentation\\\" as well.'\"\n        );\n        py_assert!(\n            py,\n            *d,\n            \"C.x.__doc__ == '`int`: a very \\\"important\\\" member of \\\\'this\\\\' instance.'\"\n        );\n    });\n}\n\n#[pyclass]\nstruct MethodWithLifeTime {}\n\n#[pymethods]\nimpl MethodWithLifeTime {\n    fn set_to_list<'py>(&self, set: &Bound<'py, PySet>) -> PyResult<Bound<'py, PyList>> {\n        let py = set.py();\n        let mut items = vec![];\n        for _ in 0..set.len() {\n            items.push(set.pop().unwrap());\n        }\n        let list = PyList::new(py, items)?;\n        list.sort()?;\n        Ok(list)\n    }\n}\n\n#[test]\nfn method_with_lifetime() {\n    Python::attach(|py| {\n        let obj = Py::new(py, MethodWithLifeTime {}).unwrap();\n        py_run!(\n            py,\n            obj,\n            \"assert obj.set_to_list(set((1, 2, 3))) == [1, 2, 3]\"\n        );\n    });\n}\n\n#[pyclass]\nstruct MethodWithPyClassArg {\n    #[pyo3(get)]\n    value: i64,\n}\n\n#[pymethods]\nimpl MethodWithPyClassArg {\n    fn add(&self, other: &MethodWithPyClassArg) -> MethodWithPyClassArg {\n        MethodWithPyClassArg {\n            value: self.value + other.value,\n        }\n    }\n    fn add_pyref(&self, other: PyRef<'_, MethodWithPyClassArg>) -> MethodWithPyClassArg {\n        MethodWithPyClassArg {\n            value: self.value + other.value,\n        }\n    }\n    fn inplace_add(&self, other: &mut MethodWithPyClassArg) {\n        other.value += self.value;\n    }\n    fn inplace_add_pyref(&self, mut other: PyRefMut<'_, MethodWithPyClassArg>) {\n        other.value += self.value;\n    }\n    #[pyo3(signature=(other = None))]\n    fn optional_add(&self, other: Option<&MethodWithPyClassArg>) -> MethodWithPyClassArg {\n        MethodWithPyClassArg {\n            value: self.value + other.map(|o| o.value).unwrap_or(10),\n        }\n    }\n    #[pyo3(signature=(other = None))]\n    fn optional_inplace_add(&self, other: Option<&mut MethodWithPyClassArg>) {\n        if let Some(other) = other {\n            other.value += self.value;\n        }\n    }\n}\n\n#[test]\nfn method_with_pyclassarg() {\n    Python::attach(|py| {\n        let obj1 = Py::new(py, MethodWithPyClassArg { value: 10 }).unwrap();\n        let obj2 = Py::new(py, MethodWithPyClassArg { value: 10 }).unwrap();\n        let d = [(\"obj1\", obj1), (\"obj2\", obj2)].into_py_dict(py).unwrap();\n        py_run!(py, *d, \"obj = obj1.add(obj2); assert obj.value == 20\");\n        py_run!(py, *d, \"obj = obj1.add_pyref(obj2); assert obj.value == 20\");\n        py_run!(py, *d, \"obj = obj1.optional_add(); assert obj.value == 20\");\n        py_run!(\n            py,\n            *d,\n            \"obj = obj1.optional_add(obj2); assert obj.value == 20\"\n        );\n        py_run!(py, *d, \"obj1.inplace_add(obj2); assert obj.value == 20\");\n        py_run!(\n            py,\n            *d,\n            \"obj1.inplace_add_pyref(obj2); assert obj2.value == 30\"\n        );\n        py_run!(\n            py,\n            *d,\n            \"obj1.optional_inplace_add(); assert obj2.value == 30\"\n        );\n        py_run!(\n            py,\n            *d,\n            \"obj1.optional_inplace_add(obj2); assert obj2.value == 40\"\n        );\n    });\n}\n\n#[pyclass]\n#[cfg(unix)]\nstruct CfgStruct {}\n\n#[pyclass]\n#[cfg(not(unix))]\nstruct CfgStruct {}\n\n#[pymethods]\n#[cfg(unix)]\nimpl CfgStruct {\n    fn unix_method(&self) -> &str {\n        \"unix\"\n    }\n\n    #[cfg(not(unix))]\n    fn never_compiled_method(&self) {}\n}\n\n#[pymethods]\n#[cfg(not(unix))]\nimpl CfgStruct {\n    fn not_unix_method(&self) -> &str {\n        \"not unix\"\n    }\n\n    #[cfg(unix)]\n    fn never_compiled_method(&self) {}\n}\n\n#[test]\nfn test_cfg_attrs() {\n    Python::attach(|py| {\n        let inst = Py::new(py, CfgStruct {}).unwrap();\n\n        #[cfg(unix)]\n        {\n            py_assert!(py, inst, \"inst.unix_method() == 'unix'\");\n            py_assert!(py, inst, \"not hasattr(inst, 'not_unix_method')\");\n        }\n\n        #[cfg(not(unix))]\n        {\n            py_assert!(py, inst, \"not hasattr(inst, 'unix_method')\");\n            py_assert!(py, inst, \"inst.not_unix_method() == 'not unix'\");\n        }\n\n        py_assert!(py, inst, \"not hasattr(inst, 'never_compiled_method')\");\n    });\n}\n\n#[pyclass]\n#[derive(Default)]\nstruct FromSequence {\n    #[pyo3(get)]\n    numbers: Vec<i64>,\n}\n\n#[pymethods]\nimpl FromSequence {\n    #[new]\n    #[pyo3(signature=(seq = None))]\n    fn new(seq: Option<&Bound<'_, PySequence>>) -> PyResult<Self> {\n        if let Some(seq) = seq {\n            Ok(FromSequence {\n                numbers: seq.as_any().extract::<Vec<_>>()?,\n            })\n        } else {\n            Ok(FromSequence::default())\n        }\n    }\n}\n\n#[test]\nfn test_from_sequence() {\n    Python::attach(|py| {\n        let typeobj = py.get_type::<FromSequence>();\n        py_assert!(py, typeobj, \"typeobj(range(0, 4)).numbers == [0, 1, 2, 3]\");\n    });\n}\n\n#[pyclass]\nstruct r#RawIdents {\n    #[pyo3(get, set)]\n    r#type: Py<PyAny>,\n    r#subtype: Py<PyAny>,\n    r#subsubtype: Py<PyAny>,\n}\n\n#[pymethods]\nimpl r#RawIdents {\n    #[new]\n    pub fn r#new(\n        r#_py: Python<'_>,\n        r#type: Py<PyAny>,\n        r#subtype: Py<PyAny>,\n        r#subsubtype: Py<PyAny>,\n    ) -> Self {\n        Self {\n            r#type,\n            r#subtype,\n            r#subsubtype,\n        }\n    }\n\n    #[getter(r#subtype)]\n    pub fn r#get_subtype(&self, py: Python<'_>) -> Py<PyAny> {\n        self.r#subtype.clone_ref(py)\n    }\n\n    #[setter(r#subtype)]\n    pub fn r#set_subtype(&mut self, r#subtype: Py<PyAny>) {\n        self.r#subtype = r#subtype;\n    }\n\n    #[deleter(r#subtype)]\n    pub fn r#del_subtype(&mut self) {}\n\n    #[getter]\n    pub fn r#get_subsubtype(&self, py: Python<'_>) -> Py<PyAny> {\n        self.r#subsubtype.clone_ref(py)\n    }\n\n    #[setter]\n    pub fn r#set_subsubtype(&mut self, r#subsubtype: Py<PyAny>) {\n        self.r#subsubtype = r#subsubtype;\n    }\n\n    #[deleter]\n    pub fn r#delete_subsubtype(&mut self) {}\n\n    pub fn r#__call__(&mut self, r#type: Py<PyAny>) {\n        self.r#type = r#type;\n    }\n\n    #[staticmethod]\n    pub fn r#static_method(r#type: Py<PyAny>) -> Py<PyAny> {\n        r#type\n    }\n\n    #[classmethod]\n    pub fn r#class_method(_: &Bound<'_, PyType>, r#type: Py<PyAny>) -> Py<PyAny> {\n        r#type\n    }\n\n    #[classattr]\n    pub fn r#class_attr_fn() -> i32 {\n        5\n    }\n\n    #[classattr]\n    const r#CLASS_ATTR_CONST: i32 = 6;\n\n    #[pyo3(signature = (r#struct = \"foo\"))]\n    fn method_with_keyword<'a>(&self, r#struct: &'a str) -> &'a str {\n        r#struct\n    }\n}\n\n#[test]\nfn test_raw_idents() {\n    Python::attach(|py| {\n        let raw_idents_type = py.get_type::<r#RawIdents>();\n        assert_eq!(raw_idents_type.qualname().unwrap(), \"RawIdents\");\n        py_run!(\n            py,\n            raw_idents_type,\n            r#\"\n            instance = raw_idents_type(type=None, subtype=5, subsubtype=\"foo\")\n\n            assert instance.type is None\n            assert instance.subtype == 5\n            assert instance.subsubtype == \"foo\"\n\n            instance.type = 1\n            instance.subtype = 2\n            instance.subsubtype = 3\n\n            assert instance.type == 1\n            assert instance.subtype == 2\n            assert instance.subsubtype == 3\n\n            del instance.subtype\n            del instance.subsubtype\n\n            assert raw_idents_type.static_method(type=30) == 30\n            assert instance.class_method(type=40) == 40\n\n            instance(type=50)\n            assert instance.type == 50\n\n            assert raw_idents_type.class_attr_fn == 5\n            assert raw_idents_type.CLASS_ATTR_CONST == 6\n\n            assert instance.method_with_keyword() == \"foo\"\n            assert instance.method_with_keyword(\"bar\") == \"bar\"\n            assert instance.method_with_keyword(struct=\"baz\") == \"baz\"\n            \"#\n        );\n    })\n}\n\n// Regression test for issue 1505 - Python argument not detected correctly when inside a macro.\n\n#[pyclass]\nstruct Issue1505 {}\n\nmacro_rules! pymethods {\n    (\n        #[pymethods]\n        impl $ty: ty {\n            fn $fn:ident (&self, $arg:ident : $arg_ty:ty) {}\n        }\n    ) => {\n        #[pymethods]\n        impl $ty {\n            fn $fn(&self, $arg: $arg_ty) {}\n        }\n    };\n}\n\npymethods!(\n    #[pymethods]\n    impl Issue1505 {\n        fn issue_1505(&self, _py: Python<'_>) {}\n    }\n);\n\n// Regression test for issue 1506 - incorrect macro hygiene.\n// By applying the `#[pymethods]` attribute inside a macro_rules! macro, this separates the macro\n// call scope from the scope of the impl block. For this to work our macros must be careful to not\n// cheat hygiene!\n\n#[pyclass]\nstruct Issue1506 {}\n\nmacro_rules! issue_1506 {\n    (#[pymethods] $($body:tt)*) => {\n        #[pymethods]\n        $($body)*\n    };\n}\n\nissue_1506!(\n    #[pymethods]\n    impl Issue1506 {\n        #[pyo3(signature = (_arg, _args, _kwargs=None))]\n        fn issue_1506(\n            &self,\n            _py: Python<'_>,\n            _arg: &Bound<'_, PyAny>,\n            _args: &Bound<'_, PyTuple>,\n            _kwargs: Option<&Bound<'_, PyDict>>,\n        ) {\n        }\n\n        #[pyo3(signature = (_arg, _args, _kwargs=None))]\n        fn issue_1506_mut(\n            &mut self,\n            _py: Python<'_>,\n            _arg: &Bound<'_, PyAny>,\n            _args: &Bound<'_, PyTuple>,\n            _kwargs: Option<&Bound<'_, PyDict>>,\n        ) {\n        }\n\n        #[pyo3(signature = (_arg, _args, _kwargs=None))]\n        fn issue_1506_custom_receiver(\n            _slf: Py<Self>,\n            _py: Python<'_>,\n            _arg: &Bound<'_, PyAny>,\n            _args: &Bound<'_, PyTuple>,\n            _kwargs: Option<&Bound<'_, PyDict>>,\n        ) {\n        }\n\n        #[pyo3(signature = (_arg, _args, _kwargs=None))]\n        fn issue_1506_custom_receiver_explicit(\n            _slf: Py<Issue1506>,\n            _py: Python<'_>,\n            _arg: &Bound<'_, PyAny>,\n            _args: &Bound<'_, PyTuple>,\n            _kwargs: Option<&Bound<'_, PyDict>>,\n        ) {\n        }\n\n        #[new]\n        #[pyo3(signature = (_arg, _args, _kwargs=None))]\n        fn issue_1506_new(\n            _py: Python<'_>,\n            _arg: &Bound<'_, PyAny>,\n            _args: &Bound<'_, PyTuple>,\n            _kwargs: Option<&Bound<'_, PyDict>>,\n        ) -> Self {\n            Issue1506 {}\n        }\n\n        #[getter(\"foo\")]\n        fn issue_1506_getter(&self, _py: Python<'_>) -> i32 {\n            5\n        }\n\n        #[setter(\"foo\")]\n        fn issue_1506_setter(&self, _py: Python<'_>, _value: i32) {}\n\n        #[deleter(\"foo\")]\n        fn issue_1506_deleter(&self, _py: Python<'_>) {}\n\n        #[staticmethod]\n        #[pyo3(signature = (_arg, _args, _kwargs=None))]\n        fn issue_1506_static(\n            _py: Python<'_>,\n            _arg: &Bound<'_, PyAny>,\n            _args: &Bound<'_, PyTuple>,\n            _kwargs: Option<&Bound<'_, PyDict>>,\n        ) {\n        }\n\n        #[classmethod]\n        #[pyo3(signature = (_arg, _args, _kwargs=None))]\n        fn issue_1506_class(\n            _cls: &Bound<'_, PyType>,\n            _py: Python<'_>,\n            _arg: &Bound<'_, PyAny>,\n            _args: &Bound<'_, PyTuple>,\n            _kwargs: Option<&Bound<'_, PyDict>>,\n        ) {\n        }\n    }\n);\n\n#[pyclass]\nstruct Issue1696 {}\n\npymethods!(\n    #[pymethods]\n    impl Issue1696 {\n        fn issue_1696(&self, _x: &InstanceMethod) {}\n    }\n);\n\n#[test]\nfn test_option_pyclass_arg() {\n    // Option<&PyClass> argument with a default set in a signature regressed to a compile\n    // error in PyO3 0.17.0 - this test it continues to be accepted.\n\n    #[pyclass]\n    struct SomePyClass {}\n\n    #[pyfunction(signature = (arg=None))]\n    fn option_class_arg(arg: Option<&SomePyClass>) -> Option<SomePyClass> {\n        arg.map(|_| SomePyClass {})\n    }\n\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(option_class_arg, py).unwrap();\n        assert!(f.call0().unwrap().is_none());\n        let obj = Py::new(py, SomePyClass {}).unwrap();\n        assert!(f\n            .call1((obj,))\n            .unwrap()\n            .extract::<Py<SomePyClass>>()\n            .is_ok());\n    })\n}\n\n#[test]\nfn test_issue_2988() {\n    #[pyfunction]\n    #[pyo3(signature = (\n        _data = vec![],\n        _data2 = vec![],\n    ))]\n    pub fn _foo(\n        _data: Vec<i32>,\n        // The from_py_with here looks a little odd, we just need some way\n        // to encourage the macro to expand the from_py_with default path too\n        #[pyo3(from_py_with = <Bound<'_, _> as PyAnyMethods>::extract)] _data2: Vec<i32>,\n    ) {\n    }\n}\n\n#[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n#[pyclass(extends=PyWarning)]\npub struct UserDefinedWarning {}\n\n#[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n#[pymethods]\nimpl UserDefinedWarning {\n    #[new]\n    #[pyo3(signature = (*_args, **_kwargs))]\n    fn new(_args: Bound<'_, PyAny>, _kwargs: Option<Bound<'_, PyAny>>) -> Self {\n        Self {}\n    }\n}\n\n#[test]\nfn test_pymethods_warn() {\n    // We do not test #[classattr] nor __traverse__\n    // because it doesn't make sense to implement deprecated methods for them.\n\n    #[pyclass]\n    struct WarningMethodContainer {\n        value: i32,\n    }\n\n    #[pymethods]\n    impl WarningMethodContainer {\n        #[new]\n        #[pyo3(warn(message = \"this __new__ method raises warning\"))]\n        fn new() -> Self {\n            Self { value: 0 }\n        }\n\n        #[pyo3(warn(message = \"this method raises warning\"))]\n        fn method_with_warning(_slf: PyRef<'_, Self>) {}\n\n        #[pyo3(warn(message = \"this method raises warning\", category = PyFutureWarning))]\n        fn method_with_warning_and_custom_category(_slf: PyRef<'_, Self>) {}\n\n        #[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n        #[pyo3(warn(message = \"this method raises user-defined warning\", category = UserDefinedWarning))]\n        fn method_with_warning_and_user_defined_category(&self) {}\n\n        #[staticmethod]\n        #[pyo3(warn(message = \"this static method raises warning\"))]\n        fn static_method() {}\n\n        #[staticmethod]\n        #[pyo3(warn(message = \"this class method raises warning\"))]\n        fn class_method() {}\n\n        #[getter]\n        #[pyo3(warn(message = \"this getter raises warning\"))]\n        fn get_value(&self) -> i32 {\n            self.value\n        }\n\n        #[setter]\n        #[pyo3(warn(message = \"this setter raises warning\"))]\n        fn set_value(&mut self, value: i32) {\n            self.value = value;\n        }\n\n        #[deleter]\n        #[pyo3(warn(message = \"this deleter raises warning\"))]\n        fn delete_value(&mut self) {}\n\n        #[pyo3(warn(message = \"this subscript op method raises warning\"))]\n        fn __getitem__(&self, _key: i32) -> i32 {\n            0\n        }\n\n        #[pyo3(warn(message = \"the + op method raises warning\"))]\n        fn __add__(&self, other: PyRef<'_, Self>) -> Self {\n            Self {\n                value: self.value + other.value,\n            }\n        }\n\n        #[pyo3(warn(message = \"this __call__ method raises warning\"))]\n        fn __call__(&self) -> i32 {\n            self.value\n        }\n    }\n\n    Python::attach(|py| {\n        let typeobj = py.get_type::<WarningMethodContainer>();\n        let obj = CatchWarnings::enter(py, |_| typeobj.call0()).unwrap();\n\n        // FnType::Fn\n        py_expect_warning!(\n            py,\n            obj,\n            \"obj.method_with_warning()\",\n            [(\"this method raises warning\", PyUserWarning)],\n        );\n\n        // FnType::Fn\n        py_expect_warning!(\n            py,\n            obj,\n            \"obj.method_with_warning_and_custom_category()\",\n            [(\"this method raises warning\", PyFutureWarning)]\n        );\n\n        // FnType::Fn, user-defined warning\n        #[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n        py_expect_warning!(\n            py,\n            obj,\n            \"obj.method_with_warning_and_user_defined_category()\",\n            [(\n                \"this method raises user-defined warning\",\n                UserDefinedWarning\n            )]\n        );\n\n        // #[staticmethod], FnType::FnStatic\n        py_expect_warning!(\n            py,\n            typeobj,\n            \"typeobj.static_method()\",\n            [(\"this static method raises warning\", PyUserWarning)]\n        );\n\n        // #[classmethod], FnType::FnClass\n        py_expect_warning!(\n            py,\n            typeobj,\n            \"typeobj.class_method()\",\n            [(\"this class method raises warning\", PyUserWarning)]\n        );\n\n        // #[classmethod], FnType::FnClass\n        py_expect_warning!(\n            py,\n            obj,\n            \"obj.class_method()\",\n            [(\"this class method raises warning\", PyUserWarning)]\n        );\n\n        // #[new], FnType::FnNew\n        py_expect_warning!(\n            py,\n            typeobj,\n            \"typeobj()\",\n            [(\"this __new__ method raises warning\", PyUserWarning)]\n        );\n\n        // #[getter], FnType::Getter\n        py_expect_warning!(\n            py,\n            obj,\n            \"val = obj.value\",\n            [(\"this getter raises warning\", PyUserWarning)]\n        );\n\n        // #[setter], FnType::Setter\n        py_expect_warning!(\n            py,\n            obj,\n            \"obj.value = 10\",\n            [(\"this setter raises warning\", PyUserWarning)]\n        );\n\n        // #[deleter], FnType::Deleter\n        py_expect_warning!(\n            py,\n            obj,\n            \"del obj.value\",\n            [(\"this deleter raises warning\", PyUserWarning)]\n        );\n\n        // PyMethodProtoKind::Slot\n        py_expect_warning!(\n            py,\n            obj,\n            \"obj[0]\",\n            [(\"this subscript op method raises warning\", PyUserWarning)]\n        );\n\n        // PyMethodProtoKind::SlotFragment\n        py_expect_warning!(\n            py,\n            obj,\n            \"obj + obj\",\n            [(\"the + op method raises warning\", PyUserWarning)]\n        );\n\n        // PyMethodProtoKind::Call\n        py_expect_warning!(\n            py,\n            obj,\n            \"obj()\",\n            [(\"this __call__ method raises warning\", PyUserWarning)]\n        );\n    });\n\n    #[pyclass]\n    struct WarningMethodContainer2 {}\n\n    #[pymethods]\n    impl WarningMethodContainer2 {\n        #[new]\n        #[classmethod]\n        #[pyo3(warn(message = \"this class-method __new__ method raises warning\"))]\n        fn new(_cls: Bound<'_, PyType>) -> Self {\n            Self {}\n        }\n    }\n\n    Python::attach(|py| {\n        let typeobj = py.get_type::<WarningMethodContainer2>();\n\n        // #[new], #[classmethod], FnType::FnNewClass\n        py_expect_warning!(\n            py,\n            typeobj,\n            \"typeobj()\",\n            [(\n                \"this class-method __new__ method raises warning\",\n                PyUserWarning\n            )]\n        );\n    });\n}\n\n#[test]\nfn test_py_methods_multiple_warn() {\n    #[pyclass]\n    struct MultipleWarnContainer {}\n\n    #[pymethods]\n    impl MultipleWarnContainer {\n        #[new]\n        fn new() -> Self {\n            Self {}\n        }\n\n        #[pyo3(warn(message = \"this method raises warning 1\"))]\n        #[pyo3(warn(message = \"this method raises warning 2\", category = PyFutureWarning))]\n        fn multiple_warn_method(&self) {}\n\n        #[cfg(not(Py_LIMITED_API))]\n        #[pyo3(warn(message = \"this method raises FutureWarning\", category = PyFutureWarning))]\n        #[pyo3(warn(message = \"this method raises UserDefinedWarning\", category = UserDefinedWarning))]\n        fn multiple_warn_custom_category_method(&self) {}\n    }\n\n    Python::attach(|py| {\n        let typeobj = py.get_type::<MultipleWarnContainer>();\n        let obj = typeobj.call0().unwrap();\n\n        py_expect_warning!(\n            py,\n            obj,\n            \"obj.multiple_warn_method()\",\n            [\n                (\"this method raises warning 1\", PyUserWarning),\n                (\"this method raises warning 2\", PyFutureWarning)\n            ]\n        );\n\n        #[cfg(not(Py_LIMITED_API))]\n        py_expect_warning!(\n            py,\n            obj,\n            \"obj.multiple_warn_custom_category_method()\",\n            [\n                (\"this method raises FutureWarning\", PyFutureWarning),\n                (\"this method raises UserDefinedWarning\", UserDefinedWarning)\n            ]\n        );\n    });\n}\n"
  },
  {
    "path": "tests/test_module.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\n\nuse pyo3::py_run;\nuse pyo3::types::PyString;\nuse pyo3::types::{IntoPyDict, PyDict, PyTuple};\n\nmod test_utils;\n\n#[pyclass]\nstruct AnonClass {}\n\n#[pyclass]\nstruct ValueClass {\n    value: usize,\n}\n\n#[pymethods]\nimpl ValueClass {\n    #[new]\n    fn new(value: usize) -> ValueClass {\n        ValueClass { value }\n    }\n}\n\n#[pyclass(module = \"module\")]\nstruct LocatedClass {}\n\n#[pyfunction]\n/// Doubles the given value\nfn double(x: usize) -> usize {\n    x * 2\n}\n\n#[test]\nfn test_module_with_functions() {\n    use pyo3::wrap_pymodule;\n\n    /// This module is implemented in Rust.\n    #[pymodule]\n    mod module_with_functions {\n        use super::*;\n\n        #[pymodule_export]\n        use super::{AnonClass, ValueClass};\n\n        #[pymodule_init]\n        fn init_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n            m.add_class::<LocatedClass>()?;\n            m.add(\"foo\", \"bar\")?;\n            m.add_function(wrap_pyfunction!(double, m)?)?;\n            m.add(\"also_double\", wrap_pyfunction!(double, m)?)?;\n            Ok(())\n        }\n\n        #[pyfunction]\n        #[pyo3(name = \"no_parameters\")]\n        fn function_with_name() -> usize {\n            42\n        }\n\n        #[pyfunction]\n        #[pyo3(pass_module)]\n        fn with_module<'py>(module: &Bound<'py, PyModule>) -> PyResult<Bound<'py, PyString>> {\n            module.name()\n        }\n\n        #[pyfunction]\n        fn double_value(v: &ValueClass) -> usize {\n            v.value * 2\n        }\n    }\n\n    Python::attach(|py| {\n        let d = [(\n            \"module_with_functions\",\n            wrap_pymodule!(module_with_functions)(py),\n        )]\n        .into_py_dict(py)\n        .unwrap();\n\n        py_assert!(\n            py,\n            *d,\n            \"module_with_functions.__doc__ == 'This module is implemented in Rust.'\"\n        );\n        py_assert!(py, *d, \"module_with_functions.no_parameters() == 42\");\n        py_assert!(py, *d, \"module_with_functions.foo == 'bar'\");\n        py_assert!(py, *d, \"module_with_functions.AnonClass != None\");\n        py_assert!(py, *d, \"module_with_functions.LocatedClass != None\");\n        py_assert!(\n            py,\n            *d,\n            \"module_with_functions.LocatedClass.__module__ == 'module'\"\n        );\n        py_assert!(py, *d, \"module_with_functions.double(3) == 6\");\n        py_assert!(\n            py,\n            *d,\n            \"module_with_functions.double.__doc__ == 'Doubles the given value'\"\n        );\n        py_assert!(py, *d, \"module_with_functions.also_double(3) == 6\");\n        py_assert!(\n            py,\n            *d,\n            \"module_with_functions.also_double.__doc__ == 'Doubles the given value'\"\n        );\n        py_assert!(\n            py,\n            *d,\n            \"module_with_functions.double_value(module_with_functions.ValueClass(1)) == 2\"\n        );\n        py_assert!(\n            py,\n            *d,\n            \"module_with_functions.with_module() == 'module_with_functions'\"\n        );\n    });\n}\n\n#[test]\n#[allow(deprecated)]\nfn test_module_with_pyfn() {\n    use pyo3::wrap_pymodule;\n\n    /// This module is implemented in Rust.\n    #[pymodule]\n    fn module_with_pyfn(m: &Bound<'_, PyModule>) -> PyResult<()> {\n        #[pyfn(m)]\n        #[pyo3(name = \"no_parameters\")]\n        fn function_with_name() -> usize {\n            42\n        }\n\n        #[pyfn(m)]\n        #[pyo3(pass_module)]\n        fn with_module<'py>(module: &Bound<'py, PyModule>) -> PyResult<Bound<'py, PyString>> {\n            module.name()\n        }\n\n        #[pyfn(m)]\n        fn double_value(v: &ValueClass) -> usize {\n            v.value * 2\n        }\n\n        m.add_class::<AnonClass>()?;\n        m.add_class::<ValueClass>()?;\n        m.add_class::<LocatedClass>()?;\n\n        m.add(\"foo\", \"bar\")?;\n\n        m.add_function(wrap_pyfunction!(double, m)?)?;\n        m.add(\"also_double\", wrap_pyfunction!(double, m)?)?;\n\n        Ok(())\n    }\n\n    Python::attach(|py| {\n        let d = [(\"module_with_pyfn\", wrap_pymodule!(module_with_pyfn)(py))]\n            .into_py_dict(py)\n            .unwrap();\n\n        py_assert!(\n            py,\n            *d,\n            \"module_with_pyfn.__doc__ == 'This module is implemented in Rust.'\"\n        );\n        py_assert!(py, *d, \"module_with_pyfn.no_parameters() == 42\");\n        py_assert!(py, *d, \"module_with_pyfn.foo == 'bar'\");\n        py_assert!(py, *d, \"module_with_pyfn.AnonClass != None\");\n        py_assert!(py, *d, \"module_with_pyfn.LocatedClass != None\");\n        py_assert!(\n            py,\n            *d,\n            \"module_with_pyfn.LocatedClass.__module__ == 'module'\"\n        );\n        py_assert!(py, *d, \"module_with_pyfn.double(3) == 6\");\n        py_assert!(\n            py,\n            *d,\n            \"module_with_pyfn.double.__doc__ == 'Doubles the given value'\"\n        );\n        py_assert!(py, *d, \"module_with_pyfn.also_double(3) == 6\");\n        py_assert!(\n            py,\n            *d,\n            \"module_with_pyfn.also_double.__doc__ == 'Doubles the given value'\"\n        );\n        py_assert!(\n            py,\n            *d,\n            \"module_with_pyfn.double_value(module_with_pyfn.ValueClass(1)) == 2\"\n        );\n        py_assert!(\n            py,\n            *d,\n            \"module_with_pyfn.with_module() == 'module_with_pyfn'\"\n        );\n    });\n}\n\n/// This module uses a legacy two-argument module function.\n#[pymodule]\nfn module_with_explicit_py_arg(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {\n    m.add_function(wrap_pyfunction!(double, m)?)?;\n    Ok(())\n}\n\n#[test]\nfn test_module_with_explicit_py_arg() {\n    use pyo3::wrap_pymodule;\n\n    Python::attach(|py| {\n        let d = [(\n            \"module_with_explicit_py_arg\",\n            wrap_pymodule!(module_with_explicit_py_arg)(py),\n        )]\n        .into_py_dict(py)\n        .unwrap();\n\n        py_assert!(py, *d, \"module_with_explicit_py_arg.double(3) == 6\");\n    });\n}\n\n#[pymodule(name = \"other_name\")]\nfn some_name(m: &Bound<'_, PyModule>) -> PyResult<()> {\n    m.add(\"other_name\", \"other_name\")?;\n    Ok(())\n}\n\n#[test]\nfn test_module_renaming() {\n    use pyo3::wrap_pymodule;\n\n    Python::attach(|py| {\n        let d = [(\"different_name\", wrap_pymodule!(some_name)(py))]\n            .into_py_dict(py)\n            .unwrap();\n\n        py_run!(py, *d, \"assert different_name.__name__ == 'other_name'\");\n    });\n}\n\n#[test]\nfn test_module_from_code_bound() {\n    Python::attach(|py| {\n        let adder_mod = PyModule::from_code(\n            py,\n            c\"def add(a,b):\\n\\treturn a+b\",\n            c\"adder_mod.py\",\n            &test_utils::generate_unique_module_name(\"adder_mod\"),\n        )\n        .expect(\"Module code should be loaded\");\n\n        let add_func = adder_mod\n            .getattr(\"add\")\n            .expect(\"Add function should be in the module\");\n\n        let ret_value: i32 = add_func\n            .call1((1, 2))\n            .expect(\"A value should be returned\")\n            .extract()\n            .expect(\"The value should be able to be converted to an i32\");\n\n        assert_eq!(ret_value, 3);\n    });\n}\n\n#[pyfunction]\nfn r#move() -> usize {\n    42\n}\n\n#[pymodule]\nfn raw_ident_module(module: &Bound<'_, PyModule>) -> PyResult<()> {\n    module.add_function(wrap_pyfunction!(r#move, module)?)\n}\n\n#[test]\nfn test_raw_idents() {\n    use pyo3::wrap_pymodule;\n\n    Python::attach(|py| {\n        let module = wrap_pymodule!(raw_ident_module)(py);\n\n        py_assert!(py, module, \"module.move() == 42\");\n    });\n}\n\n#[pyfunction]\n#[pyo3(name = \"foobar\")]\nfn custom_named_fn() -> usize {\n    42\n}\n\n#[test]\nfn test_custom_names() {\n    #[pymodule]\n    fn custom_names(m: &Bound<'_, PyModule>) -> PyResult<()> {\n        m.add_function(wrap_pyfunction!(custom_named_fn, m)?)?;\n        Ok(())\n    }\n\n    Python::attach(|py| {\n        let module = pyo3::wrap_pymodule!(custom_names)(py);\n\n        py_assert!(py, module, \"not hasattr(module, 'custom_named_fn')\");\n        py_assert!(py, module, \"module.foobar() == 42\");\n    });\n}\n\n#[test]\nfn test_module_dict() {\n    #[pymodule]\n    fn module_dict(m: &Bound<'_, PyModule>) -> PyResult<()> {\n        m.dict().set_item(\"yay\", \"me\")?;\n        Ok(())\n    }\n\n    Python::attach(|py| {\n        let module = pyo3::wrap_pymodule!(module_dict)(py);\n\n        py_assert!(py, module, \"module.yay == 'me'\");\n    });\n}\n\n#[test]\nfn test_module_dunder_all() {\n    Python::attach(|py| {\n        #[pymodule]\n        fn dunder_all(m: &Bound<'_, PyModule>) -> PyResult<()> {\n            m.dict().set_item(\"yay\", \"me\")?;\n            m.add_function(wrap_pyfunction!(custom_named_fn, m)?)?;\n            Ok(())\n        }\n\n        let module = pyo3::wrap_pymodule!(dunder_all)(py);\n\n        py_assert!(py, module, \"module.__all__ == ['foobar']\");\n    });\n}\n\n#[pyfunction]\nfn subfunction() -> String {\n    \"Subfunction\".to_string()\n}\n\nfn submodule(module: &Bound<'_, PyModule>) -> PyResult<()> {\n    module.add_function(wrap_pyfunction!(subfunction, module)?)?;\n    Ok(())\n}\n\n#[pymodule]\nfn submodule_with_init_fn(module: &Bound<'_, PyModule>) -> PyResult<()> {\n    module.add_function(wrap_pyfunction!(subfunction, module)?)?;\n    Ok(())\n}\n\n#[pyfunction]\nfn superfunction() -> String {\n    \"Superfunction\".to_string()\n}\n\n#[pymodule]\nfn supermodule(module: &Bound<'_, PyModule>) -> PyResult<()> {\n    module.add_function(wrap_pyfunction!(superfunction, module)?)?;\n    let module_to_add = PyModule::new(module.py(), \"supermodule.submodule\")?;\n    submodule(&module_to_add)?;\n    module.add_submodule(&module_to_add)?;\n    let module_to_add = PyModule::new(module.py(), \"supermodule.submodule_with_init_fn\")?;\n    submodule_with_init_fn(&module_to_add)?;\n    module.add_submodule(&module_to_add)?;\n    Ok(())\n}\n\n#[test]\nfn test_module_nesting() {\n    use pyo3::wrap_pymodule;\n\n    Python::attach(|py| {\n        let supermodule = wrap_pymodule!(supermodule)(py);\n\n        py_assert!(\n            py,\n            supermodule,\n            \"supermodule.superfunction() == 'Superfunction'\"\n        );\n        py_assert!(\n            py,\n            supermodule,\n            \"supermodule.submodule.subfunction() == 'Subfunction'\"\n        );\n        py_assert!(\n            py,\n            supermodule,\n            \"supermodule.submodule_with_init_fn.subfunction() == 'Subfunction'\"\n        );\n\n        // submodule dunder name and attribute name\n        py_assert!(\n            py,\n            supermodule,\n            \"supermodule.submodule.__name__ == 'supermodule.submodule'\"\n        );\n        py_assert!(py, supermodule, \"'submodule' in supermodule.__dict__\");\n        py_assert!(\n            py,\n            supermodule,\n            \"'supermodule.submodule' not in supermodule.__dict__\"\n        );\n\n        // submodule_with_init_fn dunder name and attribute name\n        py_assert!(\n            py,\n            supermodule,\n            \"supermodule.submodule_with_init_fn.__name__ == 'supermodule.submodule_with_init_fn'\"\n        );\n        py_assert!(\n            py,\n            supermodule,\n            \"'submodule_with_init_fn' in supermodule.__dict__\"\n        );\n        py_assert!(\n            py,\n            supermodule,\n            \"'supermodule.submodule_with_init_fn' not in supermodule.__dict__\"\n        );\n    });\n}\n\n#[test]\nfn test_module_with_constant() {\n    // Regression test for #1102\n\n    #[pymodule]\n    fn module_with_constant(m: &Bound<'_, PyModule>) -> PyResult<()> {\n        const ANON: AnonClass = AnonClass {};\n\n        m.add(\"ANON\", ANON)?;\n        m.add_class::<AnonClass>()?;\n\n        Ok(())\n    }\n\n    Python::attach(|py| {\n        let m = pyo3::wrap_pymodule!(module_with_constant)(py);\n        py_assert!(py, m, \"isinstance(m.ANON, m.AnonClass)\");\n    });\n}\n\n#[pyfunction]\n#[pyo3(pass_module)]\nfn pyfunction_with_module<'py>(module: &Bound<'py, PyModule>) -> PyResult<Bound<'py, PyString>> {\n    module.name()\n}\n\n#[pyfunction]\n#[pyo3(pass_module)]\nfn pyfunction_with_module_owned(\n    module: Py<PyModule>,\n    py: Python<'_>,\n) -> PyResult<Bound<'_, PyString>> {\n    module.bind(py).name()\n}\n\n#[pyfunction]\n#[pyo3(pass_module)]\nfn pyfunction_with_module_and_py<'py>(\n    module: &Bound<'py, PyModule>,\n    _python: Python<'py>,\n) -> PyResult<Bound<'py, PyString>> {\n    module.name()\n}\n\n#[pyfunction]\n#[pyo3(pass_module)]\nfn pyfunction_with_module_and_arg<'py>(\n    module: &Bound<'py, PyModule>,\n    string: String,\n) -> PyResult<(Bound<'py, PyString>, String)> {\n    module.name().map(|s| (s, string))\n}\n\n#[pyfunction(signature = (string=\"foo\"))]\n#[pyo3(pass_module)]\nfn pyfunction_with_module_and_default_arg<'py>(\n    module: &Bound<'py, PyModule>,\n    string: &str,\n) -> PyResult<(Bound<'py, PyString>, String)> {\n    module.name().map(|s| (s, string.into()))\n}\n\n#[pyfunction(signature = (*args, **kwargs))]\n#[pyo3(pass_module)]\nfn pyfunction_with_module_and_args_kwargs<'py>(\n    module: &Bound<'py, PyModule>,\n    args: &Bound<'py, PyTuple>,\n    kwargs: Option<&Bound<'py, PyDict>>,\n) -> PyResult<(Bound<'py, PyString>, usize, Option<usize>)> {\n    module\n        .name()\n        .map(|s| (s, args.len(), kwargs.map(|d| d.len())))\n}\n\n#[pymodule]\nfn module_with_functions_with_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n    m.add_function(wrap_pyfunction!(pyfunction_with_module, m)?)?;\n    m.add_function(wrap_pyfunction!(pyfunction_with_module_owned, m)?)?;\n    m.add_function(wrap_pyfunction!(pyfunction_with_module_and_py, m)?)?;\n    m.add_function(wrap_pyfunction!(pyfunction_with_module_and_arg, m)?)?;\n    m.add_function(wrap_pyfunction!(pyfunction_with_module_and_default_arg, m)?)?;\n    m.add_function(wrap_pyfunction!(pyfunction_with_module_and_args_kwargs, m)?)?;\n    m.add_function(wrap_pyfunction!(pyfunction_with_module, m)?)?;\n    Ok(())\n}\n\n#[test]\nfn test_module_functions_with_module() {\n    Python::attach(|py| {\n        let m = pyo3::wrap_pymodule!(module_with_functions_with_module)(py);\n        py_assert!(\n            py,\n            m,\n            \"m.pyfunction_with_module() == 'module_with_functions_with_module'\"\n        );\n        py_assert!(\n            py,\n            m,\n            \"m.pyfunction_with_module_owned() == 'module_with_functions_with_module'\"\n        );\n        py_assert!(\n            py,\n            m,\n            \"m.pyfunction_with_module_and_py() == 'module_with_functions_with_module'\"\n        );\n        py_assert!(\n            py,\n            m,\n            \"m.pyfunction_with_module_and_default_arg() \\\n                        == ('module_with_functions_with_module', 'foo')\"\n        );\n        py_assert!(\n            py,\n            m,\n            \"m.pyfunction_with_module_and_args_kwargs(1, x=1, y=2) \\\n                        == ('module_with_functions_with_module', 1, 2)\"\n        );\n    });\n}\n\n#[test]\nfn test_module_doc_hidden() {\n    #[doc(hidden)]\n    #[expect(clippy::unnecessary_wraps)]\n    #[pymodule]\n    fn my_module(_m: &Bound<'_, PyModule>) -> PyResult<()> {\n        Ok(())\n    }\n\n    Python::attach(|py| {\n        let m = pyo3::wrap_pymodule!(my_module)(py);\n        py_assert!(py, m, \"m.__doc__ == ''\");\n    })\n}\n"
  },
  {
    "path": "tests/test_multiple_pymethods.rs",
    "content": "#![cfg(feature = \"multiple-pymethods\")]\n\nuse pyo3::prelude::*;\nuse pyo3::types::PyType;\n\n#[macro_use]\nmod test_utils;\n\n#[pyclass]\nstruct PyClassWithMultiplePyMethods {}\n\n#[pymethods]\nimpl PyClassWithMultiplePyMethods {\n    #[new]\n    fn new() -> Self {\n        Self {}\n    }\n}\n\n#[pymethods]\nimpl PyClassWithMultiplePyMethods {\n    fn __call__(&self) -> &'static str {\n        \"call\"\n    }\n}\n\n#[pymethods]\nimpl PyClassWithMultiplePyMethods {\n    fn method(&self) -> &'static str {\n        \"method\"\n    }\n}\n\n#[pymethods]\nimpl PyClassWithMultiplePyMethods {\n    #[classmethod]\n    fn classmethod(_ty: &Bound<'_, PyType>) -> &'static str {\n        \"classmethod\"\n    }\n}\n\n#[pymethods]\nimpl PyClassWithMultiplePyMethods {\n    #[staticmethod]\n    fn staticmethod() -> &'static str {\n        \"staticmethod\"\n    }\n}\n\n#[pymethods]\nimpl PyClassWithMultiplePyMethods {\n    #[classattr]\n    fn class_attribute() -> &'static str {\n        \"class_attribute\"\n    }\n}\n\n#[pymethods]\nimpl PyClassWithMultiplePyMethods {\n    #[classattr]\n    const CLASS_ATTRIBUTE: &'static str = \"CLASS_ATTRIBUTE\";\n}\n\n#[test]\nfn test_class_with_multiple_pymethods() {\n    Python::attach(|py| {\n        let cls = py.get_type::<PyClassWithMultiplePyMethods>();\n        py_assert!(py, cls, \"cls()() == 'call'\");\n        py_assert!(py, cls, \"cls().method() == 'method'\");\n        py_assert!(py, cls, \"cls.classmethod() == 'classmethod'\");\n        py_assert!(py, cls, \"cls.staticmethod() == 'staticmethod'\");\n        py_assert!(py, cls, \"cls.class_attribute == 'class_attribute'\");\n        py_assert!(py, cls, \"cls.CLASS_ATTRIBUTE == 'CLASS_ATTRIBUTE'\");\n    })\n}\n"
  },
  {
    "path": "tests/test_proto_methods.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::exceptions::{PyAttributeError, PyIndexError, PyValueError};\nuse pyo3::types::{PyDict, PyList, PyMapping, PySequence, PySlice, PyType};\nuse pyo3::{prelude::*, py_run};\nuse std::iter;\nuse std::sync::Mutex;\n\nmod test_utils;\n\n#[pyclass]\nstruct EmptyClass;\n\n#[pyclass]\nstruct ExampleClass {\n    #[pyo3(get, set)]\n    value: i32,\n    custom_attr: Option<i32>,\n}\n\n#[pymethods]\nimpl ExampleClass {\n    fn __getattr__(&self, py: Python<'_>, attr: &str) -> PyResult<Py<PyAny>> {\n        if attr == \"special_custom_attr\" {\n            Ok(self.custom_attr.into_pyobject(py)?.into_any().unbind())\n        } else {\n            Err(PyAttributeError::new_err(attr.to_string()))\n        }\n    }\n\n    fn __setattr__(&mut self, attr: &str, value: &Bound<'_, PyAny>) -> PyResult<()> {\n        if attr == \"special_custom_attr\" {\n            self.custom_attr = Some(value.extract()?);\n            Ok(())\n        } else {\n            Err(PyAttributeError::new_err(attr.to_string()))\n        }\n    }\n\n    fn __delattr__(&mut self, attr: &str) -> PyResult<()> {\n        if attr == \"special_custom_attr\" {\n            self.custom_attr = None;\n            Ok(())\n        } else {\n            Err(PyAttributeError::new_err(attr.to_string()))\n        }\n    }\n\n    fn __str__(&self) -> String {\n        self.value.to_string()\n    }\n\n    fn __repr__(&self) -> String {\n        format!(\"ExampleClass(value={})\", self.value)\n    }\n\n    fn __hash__(&self) -> u64 {\n        let i64_value: i64 = self.value.into();\n        i64_value as u64\n    }\n\n    fn __bool__(&self) -> bool {\n        self.value != 0\n    }\n}\n\nfn make_example(py: Python<'_>) -> Bound<'_, ExampleClass> {\n    Bound::new(\n        py,\n        ExampleClass {\n            value: 5,\n            custom_attr: Some(20),\n        },\n    )\n    .unwrap()\n}\n\n#[test]\nfn test_getattr() {\n    Python::attach(|py| {\n        let example_py = make_example(py);\n        assert_eq!(\n            example_py\n                .getattr(\"value\")\n                .unwrap()\n                .extract::<i32>()\n                .unwrap(),\n            5,\n        );\n        assert_eq!(\n            example_py\n                .getattr(\"special_custom_attr\")\n                .unwrap()\n                .extract::<i32>()\n                .unwrap(),\n            20,\n        );\n        assert!(example_py\n            .getattr(\"other_attr\")\n            .unwrap_err()\n            .is_instance_of::<PyAttributeError>(py));\n    })\n}\n\n#[test]\nfn test_setattr() {\n    Python::attach(|py| {\n        let example_py = make_example(py);\n        example_py.setattr(\"special_custom_attr\", 15).unwrap();\n        assert_eq!(\n            example_py\n                .getattr(\"special_custom_attr\")\n                .unwrap()\n                .extract::<i32>()\n                .unwrap(),\n            15,\n        );\n    })\n}\n\n#[test]\nfn test_delattr() {\n    Python::attach(|py| {\n        let example_py = make_example(py);\n        example_py.delattr(\"special_custom_attr\").unwrap();\n        assert!(example_py.getattr(\"special_custom_attr\").unwrap().is_none());\n    })\n}\n\n#[test]\nfn test_str() {\n    Python::attach(|py| {\n        let example_py = make_example(py);\n        assert_eq!(example_py.str().unwrap(), \"5\");\n    })\n}\n\n#[test]\nfn test_repr() {\n    Python::attach(|py| {\n        let example_py = make_example(py);\n        assert_eq!(example_py.repr().unwrap(), \"ExampleClass(value=5)\");\n    })\n}\n\n#[test]\nfn test_hash() {\n    Python::attach(|py| {\n        let example_py = make_example(py);\n        assert_eq!(example_py.hash().unwrap(), 5);\n    })\n}\n\n#[test]\nfn test_bool() {\n    Python::attach(|py| {\n        let example_py = make_example(py);\n        assert!(example_py.is_truthy().unwrap());\n        example_py.borrow_mut().value = 0;\n        assert!(!example_py.is_truthy().unwrap());\n    })\n}\n\n#[pyclass]\npub struct LenOverflow;\n\n#[pymethods]\nimpl LenOverflow {\n    fn __len__(&self) -> usize {\n        (isize::MAX as usize) + 1\n    }\n}\n\n#[test]\nfn len_overflow() {\n    Python::attach(|py| {\n        let inst = Py::new(py, LenOverflow).unwrap();\n        py_expect_exception!(py, inst, \"len(inst)\", PyOverflowError);\n    });\n}\n\n#[pyclass]\npub struct Mapping {\n    values: Py<PyDict>,\n}\n\n#[pymethods]\nimpl Mapping {\n    fn __len__(&self, py: Python<'_>) -> usize {\n        self.values.bind(py).len()\n    }\n\n    fn __getitem__<'py>(&self, key: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> {\n        let any: &Bound<'py, PyAny> = self.values.bind(key.py());\n        any.get_item(key)\n    }\n\n    fn __setitem__<'py>(&self, key: &Bound<'py, PyAny>, value: &Bound<'py, PyAny>) -> PyResult<()> {\n        self.values.bind(key.py()).set_item(key, value)\n    }\n\n    fn __delitem__(&self, key: &Bound<'_, PyAny>) -> PyResult<()> {\n        self.values.bind(key.py()).del_item(key)\n    }\n}\n\n#[test]\nfn mapping() {\n    Python::attach(|py| {\n        PyMapping::register::<Mapping>(py).unwrap();\n\n        let inst = Py::new(\n            py,\n            Mapping {\n                values: PyDict::new(py).into(),\n            },\n        )\n        .unwrap();\n\n        let mapping: &Bound<'_, PyMapping> = inst.bind(py).cast().unwrap();\n\n        py_assert!(py, inst, \"len(inst) == 0\");\n\n        py_run!(py, inst, \"inst['foo'] = 'foo'\");\n        py_assert!(py, inst, \"inst['foo'] == 'foo'\");\n        py_run!(py, inst, \"del inst['foo']\");\n        py_expect_exception!(py, inst, \"inst['foo']\", PyKeyError);\n\n        // Default iteration will call __getitem__ with integer indices\n        // which fails with a KeyError\n        py_expect_exception!(py, inst, \"[*inst] == []\", PyKeyError, \"0\");\n\n        // check mapping protocol\n        assert_eq!(mapping.len().unwrap(), 0);\n\n        mapping.set_item(0, 5).unwrap();\n        assert_eq!(mapping.len().unwrap(), 1);\n\n        assert_eq!(mapping.get_item(0).unwrap().extract::<u8>().unwrap(), 5);\n\n        mapping.del_item(0).unwrap();\n        assert_eq!(mapping.len().unwrap(), 0);\n    });\n}\n\n#[derive(FromPyObject)]\nenum SequenceIndex<'py> {\n    Integer(isize),\n    Slice(Bound<'py, PySlice>),\n}\n\n#[pyclass]\npub struct Sequence {\n    values: Vec<Py<PyAny>>,\n}\n\n#[pymethods]\nimpl Sequence {\n    fn __len__(&self) -> usize {\n        self.values.len()\n    }\n\n    fn __getitem__(&self, index: SequenceIndex<'_>, py: Python<'_>) -> PyResult<Py<PyAny>> {\n        match index {\n            SequenceIndex::Integer(index) => {\n                let uindex = self.usize_index(index)?;\n                self.values\n                    .get(uindex)\n                    .map(|o| o.clone_ref(py))\n                    .ok_or_else(|| PyIndexError::new_err(index))\n            }\n            // Just to prove that slicing can be implemented\n            SequenceIndex::Slice(s) => Ok(s.into()),\n        }\n    }\n\n    fn __setitem__(&mut self, index: isize, value: Py<PyAny>) -> PyResult<()> {\n        let uindex = self.usize_index(index)?;\n        self.values\n            .get_mut(uindex)\n            .map(|place| *place = value)\n            .ok_or_else(|| PyIndexError::new_err(index))\n    }\n\n    fn __delitem__(&mut self, index: isize) -> PyResult<()> {\n        let uindex = self.usize_index(index)?;\n        if uindex >= self.values.len() {\n            Err(PyIndexError::new_err(index))\n        } else {\n            self.values.remove(uindex);\n            Ok(())\n        }\n    }\n\n    fn append(&mut self, value: Py<PyAny>) {\n        self.values.push(value);\n    }\n}\n\nimpl Sequence {\n    fn usize_index(&self, index: isize) -> PyResult<usize> {\n        if index < 0 {\n            let corrected_index = index + self.values.len() as isize;\n            if corrected_index < 0 {\n                Err(PyIndexError::new_err(index))\n            } else {\n                Ok(corrected_index as usize)\n            }\n        } else {\n            Ok(index as usize)\n        }\n    }\n}\n\n#[test]\nfn sequence() {\n    Python::attach(|py| {\n        PySequence::register::<Sequence>(py).unwrap();\n\n        let inst = Py::new(py, Sequence { values: vec![] }).unwrap();\n\n        let sequence: &Bound<'_, PySequence> = inst.bind(py).cast().unwrap();\n\n        py_assert!(py, inst, \"len(inst) == 0\");\n\n        py_expect_exception!(py, inst, \"inst[0]\", PyIndexError);\n        py_run!(py, inst, \"inst.append('foo')\");\n\n        py_assert!(py, inst, \"inst[0] == 'foo'\");\n        py_assert!(py, inst, \"inst[-1] == 'foo'\");\n\n        py_expect_exception!(py, inst, \"inst[1]\", PyIndexError);\n        py_expect_exception!(py, inst, \"inst[-2]\", PyIndexError);\n\n        py_assert!(py, inst, \"[*inst] == ['foo']\");\n\n        py_run!(py, inst, \"del inst[0]\");\n\n        py_expect_exception!(py, inst, \"inst['foo']\", PyTypeError);\n\n        py_assert!(py, inst, \"inst[0:2] == slice(0, 2)\");\n\n        // check sequence protocol\n\n        // we don't implement sequence length so that CPython doesn't attempt to correct negative\n        // indices.\n        assert!(sequence.len().is_err());\n        // however regular python len() works thanks to mp_len slot\n        assert_eq!(inst.bind(py).len().unwrap(), 0);\n\n        py_run!(py, inst, \"inst.append(0)\");\n        sequence.set_item(0, 5).unwrap();\n        assert_eq!(inst.bind(py).len().unwrap(), 1);\n\n        assert_eq!(sequence.get_item(0).unwrap().extract::<u8>().unwrap(), 5);\n        sequence.del_item(0).unwrap();\n\n        assert_eq!(inst.bind(py).len().unwrap(), 0);\n    });\n}\n\n#[pyclass]\nstruct Iterator {\n    iter: Mutex<Box<dyn iter::Iterator<Item = i32> + Send>>,\n}\n\n#[pymethods]\nimpl Iterator {\n    fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {\n        slf\n    }\n\n    fn __next__(slf: PyRefMut<'_, Self>) -> Option<i32> {\n        slf.iter.lock().unwrap().next()\n    }\n}\n\n#[test]\nfn iterator() {\n    Python::attach(|py| {\n        let inst = Py::new(\n            py,\n            Iterator {\n                iter: Mutex::new(Box::new(5..8)),\n            },\n        )\n        .unwrap();\n        py_assert!(py, inst, \"iter(inst) is inst\");\n        py_assert!(py, inst, \"list(inst) == [5, 6, 7]\");\n    });\n}\n\n#[pyclass]\nstruct Callable;\n\n#[pymethods]\nimpl Callable {\n    fn __call__(&self, arg: i32) -> i32 {\n        arg * 6\n    }\n}\n\n#[pyclass]\nstruct NotCallable;\n\n#[test]\nfn callable() {\n    Python::attach(|py| {\n        let c = Py::new(py, Callable).unwrap();\n        py_assert!(py, c, \"callable(c)\");\n        py_assert!(py, c, \"c(7) == 42\");\n\n        let nc = Py::new(py, NotCallable).unwrap();\n        py_assert!(py, nc, \"not callable(nc)\");\n    });\n}\n\n#[pyclass]\n#[derive(Debug)]\nstruct SetItem {\n    key: i32,\n    val: i32,\n}\n\n#[pymethods]\nimpl SetItem {\n    fn __setitem__(&mut self, key: i32, val: i32) {\n        self.key = key;\n        self.val = val;\n    }\n}\n\n#[test]\nfn setitem() {\n    Python::attach(|py| {\n        let c = Bound::new(py, SetItem { key: 0, val: 0 }).unwrap();\n        py_run!(py, c, \"c[1] = 2\");\n        {\n            let c = c.borrow();\n            assert_eq!(c.key, 1);\n            assert_eq!(c.val, 2);\n        }\n        py_expect_exception!(py, c, \"del c[1]\", PyNotImplementedError);\n    });\n}\n\n#[pyclass]\nstruct DelItem {\n    key: i32,\n}\n\n#[pymethods]\nimpl DelItem {\n    fn __delitem__(&mut self, key: i32) {\n        self.key = key;\n    }\n}\n\n#[test]\nfn delitem() {\n    Python::attach(|py| {\n        let c = Bound::new(py, DelItem { key: 0 }).unwrap();\n        py_run!(py, c, \"del c[1]\");\n        {\n            let c = c.borrow();\n            assert_eq!(c.key, 1);\n        }\n        py_expect_exception!(py, c, \"c[1] = 2\", PyNotImplementedError);\n    });\n}\n\n#[pyclass]\nstruct SetDelItem {\n    val: Option<i32>,\n}\n\n#[pymethods]\nimpl SetDelItem {\n    fn __setitem__(&mut self, _key: i32, val: i32) {\n        self.val = Some(val);\n    }\n\n    fn __delitem__(&mut self, _key: i32) {\n        self.val = None;\n    }\n}\n\n#[test]\nfn setdelitem() {\n    Python::attach(|py| {\n        let c = Bound::new(py, SetDelItem { val: None }).unwrap();\n        py_run!(py, c, \"c[1] = 2\");\n        {\n            let c = c.borrow();\n            assert_eq!(c.val, Some(2));\n        }\n        py_run!(py, c, \"del c[1]\");\n        let c = c.borrow();\n        assert_eq!(c.val, None);\n    });\n}\n\n#[pyclass]\nstruct Contains {}\n\n#[pymethods]\nimpl Contains {\n    fn __contains__(&self, item: i32) -> bool {\n        item >= 0\n    }\n}\n\n#[test]\nfn contains() {\n    Python::attach(|py| {\n        let c = Py::new(py, Contains {}).unwrap();\n        py_run!(py, c, \"assert 1 in c\");\n        py_run!(py, c, \"assert -1 not in c\");\n        py_expect_exception!(py, c, \"assert 'wrong type' not in c\", PyTypeError);\n    });\n}\n\n#[pyclass]\nstruct GetItem {}\n\n#[pymethods]\nimpl GetItem {\n    fn __getitem__(&self, idx: &Bound<'_, PyAny>) -> PyResult<&'static str> {\n        if let Ok(slice) = idx.cast::<PySlice>() {\n            let indices = slice.indices(1000)?;\n            if indices.start == 100 && indices.stop == 200 && indices.step == 1 {\n                return Ok(\"slice\");\n            }\n        } else if let Ok(idx) = idx.extract::<isize>() {\n            if idx == 1 {\n                return Ok(\"int\");\n            }\n        }\n        Err(PyValueError::new_err(\"error\"))\n    }\n}\n\n#[test]\nfn test_getitem() {\n    Python::attach(|py| {\n        let ob = Py::new(py, GetItem {}).unwrap();\n\n        py_assert!(py, ob, \"ob[1] == 'int'\");\n        py_assert!(py, ob, \"ob[100:200:1] == 'slice'\");\n    });\n}\n\n#[pyclass]\nstruct ClassWithGetAttr {\n    #[pyo3(get, set)]\n    data: u32,\n}\n\n#[pymethods]\nimpl ClassWithGetAttr {\n    fn __getattr__(&self, _name: &str) -> u32 {\n        self.data * 2\n    }\n}\n\n#[test]\nfn getattr_doesnt_override_member() {\n    Python::attach(|py| {\n        let inst = Py::new(py, ClassWithGetAttr { data: 4 }).unwrap();\n        py_assert!(py, inst, \"inst.data == 4\");\n        py_assert!(py, inst, \"inst.a == 8\");\n    });\n}\n\n#[pyclass]\nstruct ClassWithGetAttribute {\n    #[pyo3(get, set)]\n    data: u32,\n}\n\n#[pymethods]\nimpl ClassWithGetAttribute {\n    fn __getattribute__(&self, name: &str) -> PyResult<u32> {\n        if name == \"data\" {\n            Ok(self.data * 2)\n        } else {\n            Err(PyAttributeError::new_err(\n                \"this message will be swallowed by default `__getattr__`\",\n            ))\n        }\n    }\n}\n\n#[test]\nfn getattribute_overrides_member() {\n    Python::attach(|py| {\n        let inst = Py::new(py, ClassWithGetAttribute { data: 4 }).unwrap();\n        py_assert!(py, inst, \"inst.data == 8\");\n        py_expect_exception!(py, inst, \"inst.y == 8\", PyAttributeError, \"y\");\n    });\n}\n\n#[pyclass]\nstruct ClassWithGetAttrAndGetAttribute;\n\n#[pymethods]\nimpl ClassWithGetAttrAndGetAttribute {\n    fn __getattribute__(&self, name: &str) -> PyResult<u32> {\n        if name == \"exists\" {\n            Ok(42)\n        } else if name == \"error\" {\n            Err(PyValueError::new_err(\"bad\"))\n        } else {\n            Err(PyAttributeError::new_err(\"fallback\"))\n        }\n    }\n\n    fn __getattr__(&self, name: &str) -> PyResult<u32> {\n        if name == \"lucky\" {\n            Ok(57)\n        } else {\n            Err(PyAttributeError::new_err(\"no chance\"))\n        }\n    }\n}\n\n#[test]\nfn getattr_and_getattribute() {\n    Python::attach(|py| {\n        let inst = Py::new(py, ClassWithGetAttrAndGetAttribute).unwrap();\n        py_assert!(py, inst, \"inst.exists == 42\");\n        py_assert!(py, inst, \"inst.lucky == 57\");\n        py_expect_exception!(py, inst, \"inst.error\", PyValueError);\n        py_expect_exception!(py, inst, \"inst.unlucky\", PyAttributeError);\n    });\n}\n\n/// Wraps a Python future and yield it once.\n#[pyclass]\n#[derive(Debug)]\nstruct OnceFuture {\n    future: Py<PyAny>,\n    polled: bool,\n}\n\n#[pymethods]\nimpl OnceFuture {\n    #[new]\n    fn new(future: Py<PyAny>) -> Self {\n        OnceFuture {\n            future,\n            polled: false,\n        }\n    }\n\n    fn __await__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {\n        slf\n    }\n\n    fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {\n        slf\n    }\n    fn __next__<'py>(&mut self, py: Python<'py>) -> Option<&Bound<'py, PyAny>> {\n        if !self.polled {\n            self.polled = true;\n            Some(self.future.bind(py))\n        } else {\n            None\n        }\n    }\n}\n\n#[test]\n#[cfg(not(target_arch = \"wasm32\"))] // Won't work without wasm32 event loop (e.g., Pyodide has WebLoop)\nfn test_await() {\n    Python::attach(|py| {\n        let once = py.get_type::<OnceFuture>();\n        let source = cr#\"\nimport asyncio\nimport sys\n\nasync def main():\n    res = await Once(await asyncio.sleep(0.1))\n    assert res is None\n\n# For an odd error similar to https://bugs.python.org/issue38563\nif sys.platform == \"win32\" and sys.version_info >= (3, 8, 0):\n    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())\n\nasyncio.run(main())\n\"#;\n        let globals = PyModule::import(py, \"__main__\").unwrap().dict();\n        globals.set_item(\"Once\", once).unwrap();\n        py.run(source, Some(&globals), None)\n            .map_err(|e| e.display(py))\n            .unwrap();\n    });\n}\n\n#[pyclass]\nstruct AsyncIterator {\n    future: Option<Py<OnceFuture>>,\n}\n\n#[pymethods]\nimpl AsyncIterator {\n    #[new]\n    fn new(future: Py<OnceFuture>) -> Self {\n        Self {\n            future: Some(future),\n        }\n    }\n\n    fn __aiter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {\n        slf\n    }\n\n    fn __anext__(&mut self) -> Option<Py<OnceFuture>> {\n        self.future.take()\n    }\n}\n\n#[test]\n#[cfg(not(target_arch = \"wasm32\"))] // Won't work without wasm32 event loop (e.g., Pyodide has WebLoop)\nfn test_anext_aiter() {\n    Python::attach(|py| {\n        let once = py.get_type::<OnceFuture>();\n        let source = cr#\"\nimport asyncio\nimport sys\n\nasync def main():\n    count = 0\n    async for result in AsyncIterator(Once(await asyncio.sleep(0.1))):\n        # The Once is awaited as part of the `async for` and produces None\n        assert result is None\n        count +=1\n    assert count == 1\n\n# For an odd error similar to https://bugs.python.org/issue38563\nif sys.platform == \"win32\" and sys.version_info >= (3, 8, 0):\n    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())\n\nasyncio.run(main())\n\"#;\n        let globals = PyModule::import(py, \"__main__\").unwrap().dict();\n        globals.set_item(\"Once\", once).unwrap();\n        globals\n            .set_item(\"AsyncIterator\", py.get_type::<AsyncIterator>())\n            .unwrap();\n        py.run(source, Some(&globals), None)\n            .map_err(|e| e.display(py))\n            .unwrap();\n    });\n}\n\n/// Increment the count when `__get__` is called.\n#[pyclass]\nstruct DescrCounter {\n    #[pyo3(get)]\n    count: usize,\n}\n\n#[pymethods]\nimpl DescrCounter {\n    #[new]\n    fn new() -> Self {\n        DescrCounter { count: 0 }\n    }\n    /// Each access will increase the count\n    fn __get__<'a>(\n        mut slf: PyRefMut<'a, Self>,\n        _instance: &Bound<'_, PyAny>,\n        _owner: Option<&Bound<'_, PyType>>,\n    ) -> PyRefMut<'a, Self> {\n        slf.count += 1;\n        slf\n    }\n    /// Allow assigning a new counter to the descriptor, copying the count across\n    fn __set__(&self, _instance: &Bound<'_, PyAny>, new_value: &mut Self) {\n        new_value.count = self.count;\n    }\n    /// Delete to reset the counter\n    fn __delete__(&mut self, _instance: &Bound<'_, PyAny>) {\n        self.count = 0;\n    }\n}\n\n#[test]\nfn descr_getset() {\n    Python::attach(|py| {\n        let counter = py.get_type::<DescrCounter>();\n        let source = pyo3_ffi::c_str!(\n            r#\"\nclass Class:\n    counter = Counter()\n\n# access via type\ncounter = Class.counter\nassert counter.count == 1\n\n# access with instance directly\nassert Counter.__get__(counter, Class()).count == 2\n\n# access via instance\nc = Class()\nassert c.counter.count == 3\n\n# __set__\nc.counter = Counter()\nassert c.counter.count == 4\n\n# __delete__\ndel c.counter\nassert c.counter.count == 1\n\"#\n        );\n        let globals = PyModule::import(py, \"__main__\").unwrap().dict();\n        globals.set_item(\"Counter\", counter).unwrap();\n        py.run(source, Some(&globals), None)\n            .map_err(|e| e.display(py))\n            .unwrap();\n    });\n}\n\n#[pyclass]\nstruct NotHashable;\n\n#[pymethods]\nimpl NotHashable {\n    #[classattr]\n    const __hash__: Option<Py<PyAny>> = None;\n}\n\n#[test]\nfn test_hash_opt_out() {\n    // By default Python provides a hash implementation, which can be disabled by setting __hash__\n    // to None.\n    Python::attach(|py| {\n        let empty = Py::new(py, EmptyClass).unwrap();\n        py_assert!(py, empty, \"hash(empty) is not None\");\n\n        let not_hashable = Py::new(py, NotHashable).unwrap();\n        py_expect_exception!(py, not_hashable, \"hash(not_hashable)\", PyTypeError);\n    })\n}\n\n/// Class with __iter__ gets default contains from CPython.\n#[pyclass]\nstruct DefaultedContains;\n\n#[pymethods]\nimpl DefaultedContains {\n    fn __iter__(&self, py: Python<'_>) -> Py<PyAny> {\n        PyList::new(py, [\"a\", \"b\", \"c\"])\n            .unwrap()\n            .as_any()\n            .try_iter()\n            .unwrap()\n            .into()\n    }\n}\n\n#[pyclass]\nstruct NoContains;\n\n#[pymethods]\nimpl NoContains {\n    fn __iter__(&self, py: Python<'_>) -> Py<PyAny> {\n        PyList::new(py, [\"a\", \"b\", \"c\"])\n            .unwrap()\n            .as_any()\n            .try_iter()\n            .unwrap()\n            .into()\n    }\n\n    // Equivalent to the opt-out const form in NotHashable above, just more verbose, to confirm this\n    // also works.\n    #[classattr]\n    fn __contains__() -> Option<Py<PyAny>> {\n        None\n    }\n}\n\n#[test]\nfn test_contains_opt_out() {\n    Python::attach(|py| {\n        let defaulted_contains = Py::new(py, DefaultedContains).unwrap();\n        py_assert!(py, defaulted_contains, \"'a' in defaulted_contains\");\n\n        let no_contains = Py::new(py, NoContains).unwrap();\n        py_expect_exception!(py, no_contains, \"'a' in no_contains\", PyTypeError);\n    })\n}\n"
  },
  {
    "path": "tests/test_pybuffer_drop_without_interpreter.rs",
    "content": "#![cfg(any(not(Py_LIMITED_API), Py_3_11))] // buffer availability\n#![cfg(not(any(PyPy, GraalPy)))] // cannot control interpreter lifecycle in PyPy or GraalPy\n\n//! Dropping `Py<T>` after the interpreter has been finalized should be sound.\n//!\n//! See e.g. https://github.com/PyO3/pyo3/issues/4632 for an extension of this problem\n//! where the interpreter was finalized before `PyBuffer<T>` was dropped.\n//!\n//! This test runs in its own process to control the interpreter lifecycle.\n\nuse pyo3::{buffer::PyBuffer, types::PyBytes};\n\n#[test]\nfn test_pybuffer_drop_without_interpreter() {\n    // SAFETY: this is knowingly unsafe as we're preserving the `Py<T>` object\n    // after the Python interpreter has been finalized.\n    //\n    // However we should still be able to drop it without causing undefined behavior,\n    // so that process shutdown is sound.\n    let obj: PyBuffer<u8> = unsafe {\n        pyo3::with_embedded_python_interpreter(|py| {\n            PyBuffer::get(&PyBytes::new(py, b\"abcdef\")).unwrap()\n        })\n    };\n\n    // there should be no interpreter outside of the `with_embedded_python_interpreter` block\n    assert_eq!(unsafe { pyo3_ffi::Py_IsInitialized() }, 0);\n\n    // dropping object should be sound\n    drop(obj);\n\n    // dropping object should not re-initialize the interpreter\n    assert_eq!(unsafe { pyo3_ffi::Py_IsInitialized() }, 0);\n}\n"
  },
  {
    "path": "tests/test_pyerr_debug_unformattable.rs",
    "content": "use pyo3::prelude::*;\n\n// This test mucks around with sys.modules, so run it separately to prevent it\n// from potentially corrupting the state of the python interpreter used in other\n// tests.\n\n#[test]\nfn err_debug_unformattable() {\n    // Debug representation should be like the following (without the newlines):\n    // PyErr {\n    //     type: <class 'Exception'>,\n    //     value: Exception('banana'),\n    //     traceback: Some(\\\"<unformattable <traceback object at 0x...>>\\\")\n    // }\n\n    Python::attach(|py| {\n        // PyTracebackMethods::format uses io.StringIO. Mock it out to trigger a\n        // formatting failure:\n        // TypeError: 'Mock' object is not an instance of 'str'\n        let err = py\n            .run(\n                cr#\"\nimport io, sys, unittest.mock\nsys.modules['orig_io'] = sys.modules['io']\nsys.modules['io'] = unittest.mock.Mock()\nraise Exception('banana')\"#,\n                None,\n                None,\n            )\n            .expect_err(\"raising should have given us an error\");\n\n        let debug_str = format!(\"{err:?}\");\n        assert!(debug_str.starts_with(\"PyErr { \"));\n        assert!(debug_str.ends_with(\" }\"));\n\n        // Strip \"PyErr { \" and \" }\". Split into 3 substrings to separate type,\n        // value, and traceback while not splitting the string within traceback.\n        let mut fields = debug_str[\"PyErr { \".len()..debug_str.len() - 2].splitn(3, \", \");\n\n        assert_eq!(fields.next().unwrap(), \"type: <class 'Exception'>\");\n        assert_eq!(fields.next().unwrap(), \"value: Exception('banana')\");\n\n        let traceback = fields.next().unwrap();\n        assert!(\n            traceback.starts_with(\"traceback: Some(\\\"<unformattable <traceback object at 0x\"),\n            \"assertion failed, actual traceback str: {traceback:?}\"\n        );\n        assert!(fields.next().is_none());\n\n        py.run(\n            cr#\"\nimport io, sys, unittest.mock\nsys.modules['io'] = sys.modules['orig_io']\ndel sys.modules['orig_io']\n\"#,\n            None,\n            None,\n        )\n        .unwrap();\n    });\n}\n"
  },
  {
    "path": "tests/test_pyfunction.rs",
    "content": "#![cfg(feature = \"macros\")]\n#![warn(unsafe_op_in_unsafe_fn)]\n\nuse std::collections::HashMap;\n\n#[cfg(not(Py_LIMITED_API))]\nuse pyo3::buffer::PyBuffer;\n#[cfg(any(not(Py_LIMITED_API), Py_3_12))]\nuse pyo3::exceptions::PyWarning;\nuse pyo3::exceptions::{PyFutureWarning, PyUserWarning};\nuse pyo3::prelude::*;\n#[cfg(not(Py_LIMITED_API))]\nuse pyo3::types::PyDateTime;\n#[cfg(not(any(Py_LIMITED_API, PyPy)))]\nuse pyo3::types::PyFunction;\nuse pyo3::types::{self, PyCFunction};\nuse pyo3_macros::pyclass;\n\nmod test_utils;\n\n#[pyfunction(name = \"struct\")]\nfn struct_function() {}\n\n#[test]\nfn test_rust_keyword_name() {\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(struct_function)(py).unwrap();\n\n        py_assert!(py, f, \"f.__name__ == 'struct'\");\n    });\n}\n\n#[pyfunction(signature = (arg = true))]\nfn optional_bool(arg: Option<bool>) -> String {\n    format!(\"{arg:?}\")\n}\n\n#[test]\nfn test_optional_bool() {\n    // Regression test for issue #932\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(optional_bool)(py).unwrap();\n\n        py_assert!(py, f, \"f() == 'Some(true)'\");\n        py_assert!(py, f, \"f(True) == 'Some(true)'\");\n        py_assert!(py, f, \"f(False) == 'Some(false)'\");\n        py_assert!(py, f, \"f(None) == 'None'\");\n    });\n}\n\n#[test]\nfn test_trailing_optional_no_signature() {\n    // Since PyO3 0.24, trailing optional arguments are treated like any other required argument\n    // (previously would get an implicit default of `None`)\n\n    #[pyfunction]\n    fn trailing_optional(x: i32, y: Option<i32>) -> String {\n        format!(\"x={x:?} y={y:?}\")\n    }\n\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(trailing_optional)(py).unwrap();\n\n        py_assert!(py, f, \"f(1, 2) == 'x=1 y=Some(2)'\");\n        py_assert!(py, f, \"f(2, None) == 'x=2 y=None'\");\n\n        py_expect_exception!(\n            py,\n            f,\n            \"f(3)\",\n            PyTypeError,\n            \"trailing_optional() missing 1 required positional argument: 'y'\"\n        );\n    });\n}\n\n#[pyfunction]\n#[pyo3(signature=(arg))]\nfn required_optional_str(arg: Option<&str>) -> &str {\n    arg.unwrap_or(\"\")\n}\n\n#[test]\nfn test_optional_str() {\n    // Regression test for issue #4965\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(required_optional_str)(py).unwrap();\n\n        py_assert!(py, f, \"f('') == ''\");\n        py_assert!(py, f, \"f('foo') == 'foo'\");\n        py_assert!(py, f, \"f(None) == ''\");\n    });\n}\n\n#[pyclass]\nstruct MyClass();\n\n#[pyfunction]\n#[pyo3(signature=(arg))]\nfn required_optional_class(arg: Option<&MyClass>) {\n    let _ = arg;\n}\n\n#[test]\nfn test_required_optional_class() {\n    // Regression test for issue #4965\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(required_optional_class)(py).unwrap();\n        let val = Bound::new(py, MyClass()).unwrap();\n\n        py_assert!(py, f val, \"f(val) is None\");\n        py_assert!(py, f, \"f(None) is None\");\n    });\n}\n\n#[cfg(not(Py_LIMITED_API))]\n#[pyfunction]\nfn buffer_inplace_add(py: Python<'_>, x: PyBuffer<i32>, y: PyBuffer<i32>) {\n    let x = x.as_mut_slice(py).unwrap();\n    let y = y.as_slice(py).unwrap();\n    for (xi, yi) in x.iter().zip(y) {\n        let xi_plus_yi = xi.get() + yi.get();\n        xi.set(xi_plus_yi);\n    }\n}\n\n#[cfg(not(Py_LIMITED_API))]\n#[test]\nfn test_buffer_add() {\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(buffer_inplace_add)(py).unwrap();\n\n        py_expect_exception!(\n            py,\n            f,\n            r#\"\nimport array\na = array.array(\"i\", [0, 1, 2, 3])\nb = array.array(\"I\", [0, 1, 2, 3])\nf(a, b)\n\"#,\n            PyBufferError\n        );\n\n        pyo3::py_run!(\n            py,\n            f,\n            r#\"\nimport array\na = array.array(\"i\", [0, 1, 2, 3])\nb = array.array(\"i\", [2, 3, 4, 5])\nf(a, b)\nassert a, array.array(\"i\", [2, 4, 6, 8])\n\"#\n        );\n    });\n}\n\n#[cfg(not(any(Py_LIMITED_API, PyPy)))]\n#[pyfunction]\nfn function_with_pyfunction_arg<'py>(fun: &Bound<'py, PyFunction>) -> PyResult<Bound<'py, PyAny>> {\n    fun.call((), None)\n}\n\n#[pyfunction]\nfn function_with_pycfunction_arg<'py>(\n    fun: &Bound<'py, PyCFunction>,\n) -> PyResult<Bound<'py, PyAny>> {\n    fun.call((), None)\n}\n\n#[test]\nfn test_functions_with_function_args() {\n    Python::attach(|py| {\n        let py_cfunc_arg = wrap_pyfunction!(function_with_pycfunction_arg)(py).unwrap();\n        let bool_to_string = wrap_pyfunction!(optional_bool)(py).unwrap();\n\n        pyo3::py_run!(\n            py,\n            py_cfunc_arg\n            bool_to_string,\n            r#\"\n        assert py_cfunc_arg(bool_to_string) == \"Some(true)\"\n        \"#\n        );\n\n        #[cfg(not(any(Py_LIMITED_API, PyPy)))]\n        {\n            let py_func_arg = wrap_pyfunction!(function_with_pyfunction_arg)(py).unwrap();\n\n            pyo3::py_run!(\n                py,\n                py_func_arg,\n                r#\"\n            def foo(): return \"bar\"\n            assert py_func_arg(foo) == \"bar\"\n            \"#\n            );\n        }\n    });\n}\n\n#[cfg(not(Py_LIMITED_API))]\nfn datetime_to_timestamp(dt: &Bound<'_, PyAny>) -> PyResult<i64> {\n    let dt = dt.cast::<PyDateTime>()?;\n    let ts: f64 = dt.call_method0(\"timestamp\")?.extract()?;\n\n    Ok(ts as i64)\n}\n\n#[cfg(not(Py_LIMITED_API))]\n#[pyfunction]\nfn function_with_custom_conversion(\n    #[pyo3(from_py_with = datetime_to_timestamp)] timestamp: i64,\n) -> i64 {\n    timestamp\n}\n\n#[cfg(not(Py_LIMITED_API))]\n#[test]\nfn test_function_with_custom_conversion() {\n    Python::attach(|py| {\n        let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap();\n\n        pyo3::py_run!(\n            py,\n            custom_conv_func,\n            r#\"\n        import datetime\n\n        dt = datetime.datetime.fromtimestamp(1612040400)\n        assert custom_conv_func(dt) == 1612040400\n        \"#\n        )\n    });\n}\n\n#[cfg(not(Py_LIMITED_API))]\n#[test]\nfn test_function_with_custom_conversion_error() {\n    Python::attach(|py| {\n        let custom_conv_func = wrap_pyfunction!(function_with_custom_conversion)(py).unwrap();\n\n        py_expect_exception!(\n            py,\n            custom_conv_func,\n            \"custom_conv_func(['a'])\",\n            PyTypeError,\n            \"'list' object is not an instance of 'datetime'\",\n            \"while processing 'timestamp'\"\n        );\n    });\n}\n\n#[test]\nfn test_from_py_with_defaults() {\n    fn optional_int(x: &Bound<'_, PyAny>) -> PyResult<Option<i32>> {\n        if x.is_none() {\n            Ok(None)\n        } else {\n            Some(x.extract()).transpose()\n        }\n    }\n\n    // issue 2280 combination of from_py_with and Option<T> did not compile\n    #[pyfunction]\n    #[pyo3(signature = (int=None))]\n    fn from_py_with_option(#[pyo3(from_py_with = optional_int)] int: Option<i32>) -> i32 {\n        int.unwrap_or(0)\n    }\n\n    #[pyfunction(signature = (len=0))]\n    fn from_py_with_default(\n        #[pyo3(from_py_with = <Bound<'_, _> as PyAnyMethods>::len)] len: usize,\n    ) -> usize {\n        len\n    }\n\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(from_py_with_option)(py).unwrap();\n\n        assert_eq!(f.call0().unwrap().extract::<i32>().unwrap(), 0);\n        assert_eq!(f.call1((123,)).unwrap().extract::<i32>().unwrap(), 123);\n        assert_eq!(f.call1((999,)).unwrap().extract::<i32>().unwrap(), 999);\n\n        let f2 = wrap_pyfunction!(from_py_with_default)(py).unwrap();\n\n        assert_eq!(f2.call0().unwrap().extract::<usize>().unwrap(), 0);\n        assert_eq!(f2.call1((\"123\",)).unwrap().extract::<usize>().unwrap(), 3);\n        assert_eq!(f2.call1((\"1234\",)).unwrap().extract::<usize>().unwrap(), 4);\n    });\n}\n\n#[pyclass]\n#[derive(Debug, FromPyObject)]\nstruct ValueClass {\n    #[pyo3(get)]\n    value: usize,\n}\n\n#[pyfunction]\n#[pyo3(signature=(str_arg, int_arg, tuple_arg, option_arg = None, struct_arg = None))]\nfn conversion_error(\n    str_arg: &str,\n    int_arg: i64,\n    tuple_arg: (String, f64),\n    option_arg: Option<i64>,\n    struct_arg: Option<ValueClass>,\n) {\n    println!(\"{str_arg:?} {int_arg:?} {tuple_arg:?} {option_arg:?} {struct_arg:?}\");\n}\n\n#[test]\nfn test_conversion_error() {\n    Python::attach(|py| {\n        let conversion_error = wrap_pyfunction!(conversion_error)(py).unwrap();\n        py_expect_exception!(\n            py,\n            conversion_error,\n            \"conversion_error(None, None, None, None, None)\",\n            PyTypeError,\n            \"'None' is not an instance of 'str'\",\n            \"while processing 'str_arg'\"\n        );\n        py_expect_exception!(\n            py,\n            conversion_error,\n            \"conversion_error(100, None, None, None, None)\",\n            PyTypeError,\n            \"'int' object is not an instance of 'str'\",\n            \"while processing 'str_arg'\"\n        );\n        py_expect_exception!(\n            py,\n            conversion_error,\n            \"conversion_error('string1', 'string2', None, None, None)\",\n            PyTypeError,\n            \"'str' object cannot be interpreted as an integer\",\n            \"while processing 'int_arg'\"\n        );\n        py_expect_exception!(\n            py,\n            conversion_error,\n            \"conversion_error('string1', -100, 'string2', None, None)\",\n            PyTypeError,\n            \"'str' object is not an instance of 'tuple'\",\n            \"while processing 'tuple_arg'\"\n        );\n        py_expect_exception!(\n            py,\n            conversion_error,\n            \"conversion_error('string1', -100, ('string2', 10.), 'string3', None)\",\n            PyTypeError,\n            \"'str' object cannot be interpreted as an integer\",\n            \"while processing 'option_arg'\"\n        );\n        let exception = py_expect_exception!(\n            py,\n            conversion_error,\n            \"\nclass ValueClass:\n    def __init__(self, value):\n        self.value = value\nconversion_error('string1', -100, ('string2', 10.), None, ValueClass(\\\"no_expected_type\\\"))\",\n            PyTypeError\n        );\n        if exception.value(py).hasattr(\"add_note\").unwrap() {\n            assert_eq!(\n                exception\n                    .value(py)\n                    .getattr(\"__notes__\")\n                    .unwrap()\n                    .get_item(0)\n                    .unwrap()\n                    .extract::<std::borrow::Cow<'_, str>>()\n                    .unwrap(),\n                \"while processing 'struct_arg'\"\n            );\n        }\n        assert_eq!(\n            extract_traceback(py, exception),\n            \"TypeError: failed to \\\n    extract field ValueClass.value: TypeError: 'str' object cannot be interpreted as an integer\"\n        );\n\n        let exception = py_expect_exception!(\n            py,\n            conversion_error,\n            \"\nclass ValueClass:\n    def __init__(self, value):\n        self.value = value\nconversion_error('string1', -100, ('string2', 10.), None, ValueClass(-5))\",\n            PyTypeError\n        );\n        if exception.value(py).hasattr(\"add_note\").unwrap() {\n            assert_eq!(\n                exception\n                    .value(py)\n                    .getattr(\"__notes__\")\n                    .unwrap()\n                    .get_item(0)\n                    .unwrap()\n                    .extract::<std::borrow::Cow<'_, str>>()\n                    .unwrap(),\n                \"while processing 'struct_arg'\"\n            );\n        }\n        assert_eq!(\n            extract_traceback(py, exception),\n            \"TypeError: failed to \\\n    extract field ValueClass.value: OverflowError: can't convert negative int to unsigned\"\n        );\n    });\n}\n\n/// Helper function that concatenates the error message from\n/// each error in the traceback into a single string that can\n/// be tested.\nfn extract_traceback(py: Python<'_>, mut error: PyErr) -> String {\n    let mut error_msg = error.to_string();\n    while let Some(cause) = error.cause(py) {\n        error_msg.push_str(\": \");\n        error_msg.push_str(&cause.to_string());\n        error = cause\n    }\n    error_msg\n}\n\n#[test]\nfn test_pycfunction_new() {\n    use pyo3::ffi;\n\n    Python::attach(|py| {\n        unsafe extern \"C\" fn c_fn(\n            _self: *mut ffi::PyObject,\n            _args: *mut ffi::PyObject,\n        ) -> *mut ffi::PyObject {\n            unsafe { ffi::PyLong_FromLong(4200) }\n        }\n\n        let py_fn = PyCFunction::new(\n            py,\n            c_fn,\n            c\"py_fn\",\n            c\"py_fn for test (this is the docstring)\",\n            None,\n        )\n        .unwrap();\n\n        py_assert!(py, py_fn, \"py_fn() == 4200\");\n        py_assert!(\n            py,\n            py_fn,\n            \"py_fn.__doc__ == 'py_fn for test (this is the docstring)'\"\n        );\n    });\n}\n\n#[test]\nfn test_pycfunction_new_with_keywords() {\n    use pyo3::ffi;\n    use std::ffi::c_long;\n    use std::ptr;\n\n    Python::attach(|py| {\n        unsafe extern \"C\" fn c_fn(\n            _self: *mut ffi::PyObject,\n            args: *mut ffi::PyObject,\n            kwds: *mut ffi::PyObject,\n        ) -> *mut ffi::PyObject {\n            let mut foo: c_long = 0;\n            let mut bar: c_long = 0;\n\n            #[cfg(not(Py_3_13))]\n            let foo_name = std::ffi::CString::new(\"foo\").unwrap();\n            #[cfg(not(Py_3_13))]\n            let kw_bar_name = std::ffi::CString::new(\"kw_bar\").unwrap();\n            #[cfg(not(Py_3_13))]\n            let mut args_names = [foo_name.into_raw(), kw_bar_name.into_raw(), ptr::null_mut()];\n\n            #[cfg(Py_3_13)]\n            let args_names = [c\"foo\".as_ptr(), c\"kw_bar\".as_ptr(), ptr::null_mut()];\n\n            unsafe {\n                ffi::PyArg_ParseTupleAndKeywords(\n                    args,\n                    kwds,\n                    c\"l|l\".as_ptr(),\n                    #[cfg(Py_3_13)]\n                    args_names.as_ptr(),\n                    #[cfg(not(Py_3_13))]\n                    args_names.as_mut_ptr(),\n                    &mut foo,\n                    &mut bar,\n                )\n            };\n\n            #[cfg(not(Py_3_13))]\n            drop(unsafe { std::ffi::CString::from_raw(args_names[0]) });\n            #[cfg(not(Py_3_13))]\n            drop(unsafe { std::ffi::CString::from_raw(args_names[1]) });\n\n            unsafe { ffi::PyLong_FromLong(foo * bar) }\n        }\n\n        let py_fn = PyCFunction::new_with_keywords(\n            py,\n            c_fn,\n            c\"py_fn\",\n            c\"py_fn for test (this is the docstring)\",\n            None,\n        )\n        .unwrap();\n\n        py_assert!(py, py_fn, \"py_fn(42, kw_bar=100) == 4200\");\n        py_assert!(py, py_fn, \"py_fn(foo=42, kw_bar=100) == 4200\");\n        py_assert!(\n            py,\n            py_fn,\n            \"py_fn.__doc__ == 'py_fn for test (this is the docstring)'\"\n        );\n    });\n}\n\n#[test]\nfn test_closure() {\n    Python::attach(|py| {\n        let f = |args: &Bound<'_, types::PyTuple>,\n                 _kwargs: Option<&Bound<'_, types::PyDict>>|\n         -> PyResult<_> {\n            Python::attach(|py| {\n                let res: PyResult<Vec<_>> = args\n                    .iter()\n                    .map(|elem| {\n                        if let Ok(i) = elem.extract::<i64>() {\n                            Ok((i + 1).into_pyobject(py)?.into_any().unbind())\n                        } else if let Ok(f) = elem.extract::<f64>() {\n                            Ok((2. * f).into_pyobject(py)?.into_any().unbind())\n                        } else if let Ok(mut s) = elem.extract::<String>() {\n                            s.push_str(\"-py\");\n                            Ok(s.into_pyobject(py)?.into_any().unbind())\n                        } else {\n                            panic!(\"unexpected argument type for {elem:?}\")\n                        }\n                    })\n                    .collect();\n                res\n            })\n        };\n        let closure_py =\n            PyCFunction::new_closure(py, Some(c\"test_fn\"), Some(c\"test_fn doc\"), f).unwrap();\n\n        py_assert!(py, closure_py, \"closure_py(42) == [43]\");\n        py_assert!(py, closure_py, \"closure_py.__name__ == 'test_fn'\");\n        py_assert!(py, closure_py, \"closure_py.__doc__ == 'test_fn doc'\");\n        py_assert!(\n            py,\n            closure_py,\n            \"closure_py(42, 3.14, 'foo') == [43, 6.28, 'foo-py']\"\n        );\n    });\n}\n\n#[test]\nfn test_closure_counter() {\n    Python::attach(|py| {\n        let counter = std::cell::RefCell::new(0);\n        let counter_fn = move |_args: &Bound<'_, types::PyTuple>,\n                               _kwargs: Option<&Bound<'_, types::PyDict>>|\n              -> PyResult<i32> {\n            let mut counter = counter.borrow_mut();\n            *counter += 1;\n            Ok(*counter)\n        };\n        let counter_py = PyCFunction::new_closure(py, None, None, counter_fn).unwrap();\n\n        py_assert!(py, counter_py, \"counter_py() == 1\");\n        py_assert!(py, counter_py, \"counter_py() == 2\");\n        py_assert!(py, counter_py, \"counter_py() == 3\");\n    });\n}\n\n#[test]\nfn use_pyfunction() {\n    mod function_in_module {\n        use pyo3::prelude::*;\n\n        #[pyfunction]\n        pub fn foo(x: i32) -> i32 {\n            x\n        }\n    }\n\n    Python::attach(|py| {\n        use function_in_module::foo;\n\n        // check imported name can be wrapped\n        let f = wrap_pyfunction!(foo, py).unwrap();\n        assert_eq!(f.call1((5,)).unwrap().extract::<i32>().unwrap(), 5);\n        assert_eq!(f.call1((42,)).unwrap().extract::<i32>().unwrap(), 42);\n\n        // check path import can be wrapped\n        let f2 = wrap_pyfunction!(function_in_module::foo, py).unwrap();\n        assert_eq!(f2.call1((5,)).unwrap().extract::<i32>().unwrap(), 5);\n        assert_eq!(f2.call1((42,)).unwrap().extract::<i32>().unwrap(), 42);\n    })\n}\n\n#[pyclass]\nstruct Key(String);\n\n#[pyclass]\nstruct Value(i32);\n\n#[pyfunction]\nfn return_value_borrows_from_arguments<'py>(\n    py: Python<'py>,\n    key: &'py Key,\n    value: &'py Value,\n) -> HashMap<&'py str, i32> {\n    py.detach(move || {\n        let mut map = HashMap::new();\n        map.insert(key.0.as_str(), value.0);\n        map\n    })\n}\n\n#[test]\nfn test_return_value_borrows_from_arguments() {\n    Python::attach(|py| {\n        let function = wrap_pyfunction!(return_value_borrows_from_arguments, py).unwrap();\n\n        let key = Py::new(py, Key(\"key\".to_owned())).unwrap();\n        let value = Py::new(py, Value(42)).unwrap();\n\n        py_assert!(py, function key value, \"function(key, value) == { \\\"key\\\": 42 }\");\n    });\n}\n\n#[test]\nfn test_some_wrap_arguments() {\n    // Option<T> arguments get special treatment in pyfunction default values where it's\n    // valid to pass the inner type without wrapping in `Some()`.\n    //\n    // See also https://github.com/PyO3/pyo3/issues/3460\n    const NONE: Option<u8> = None;\n    #[pyfunction(signature = (a = 1, b = Some(2), c = None, d = NONE))]\n    fn some_wrap_arguments(\n        a: Option<u8>,\n        b: Option<u8>,\n        c: Option<u8>,\n        d: Option<u8>,\n    ) -> [Option<u8>; 4] {\n        [a, b, c, d]\n    }\n\n    Python::attach(|py| {\n        let function = wrap_pyfunction!(some_wrap_arguments, py).unwrap();\n        py_assert!(py, function, \"function() == [1, 2, None, None]\");\n    })\n}\n\n#[test]\nfn test_reference_to_bound_arguments() {\n    #[pyfunction]\n    #[pyo3(signature = (x, y = None))]\n    fn reference_args<'py>(\n        x: &Bound<'py, PyAny>,\n        y: Option<&Bound<'py, PyAny>>,\n    ) -> PyResult<Bound<'py, PyAny>> {\n        y.map_or_else(|| Ok(x.clone()), |y| y.add(x))\n    }\n\n    Python::attach(|py| {\n        let function = wrap_pyfunction!(reference_args, py).unwrap();\n        py_assert!(py, function, \"function(1) == 1\");\n        py_assert!(py, function, \"function(1, 2) == 3\");\n    })\n}\n\n#[test]\nfn test_pyfunction_raw_ident() {\n    #[pyfunction]\n    fn r#struct() -> bool {\n        true\n    }\n\n    #[pyfunction]\n    #[pyo3(name = \"r#enum\")]\n    fn raw_ident() -> bool {\n        true\n    }\n\n    #[pymodule]\n    fn m(m: &Bound<'_, PyModule>) -> PyResult<()> {\n        m.add_function(wrap_pyfunction!(r#struct, m)?)?;\n        m.add_function(wrap_pyfunction!(raw_ident, m)?)?;\n        Ok(())\n    }\n\n    Python::attach(|py| {\n        let m = pyo3::wrap_pymodule!(m)(py);\n        py_assert!(py, m, \"m.struct()\");\n        py_assert!(py, m, \"m.enum()\");\n    })\n}\n\n#[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n#[pyclass(extends=PyWarning)]\npub struct UserDefinedWarning {}\n\n#[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n#[pymethods]\nimpl UserDefinedWarning {\n    #[new]\n    #[pyo3(signature = (*_args, **_kwargs))]\n    fn new(_args: Bound<'_, PyAny>, _kwargs: Option<Bound<'_, PyAny>>) -> Self {\n        Self {}\n    }\n}\n\n#[test]\nfn test_pyfunction_warn() {\n    #[pyfunction]\n    #[pyo3(warn(message = \"TPW: this function raises warning\"))]\n    fn function_with_warning() {}\n\n    py_expect_warning_for_fn!(\n        function_with_warning,\n        f,\n        [(\"TPW: this function raises warning\", PyUserWarning)]\n    );\n\n    #[pyfunction]\n    #[pyo3(warn(message = \"TPW: this function raises warning with category\", category = PyFutureWarning))]\n    fn function_with_warning_with_category() {}\n\n    py_expect_warning_for_fn!(\n        function_with_warning_with_category,\n        f,\n        [(\n            \"TPW: this function raises warning with category\",\n            PyFutureWarning\n        )]\n    );\n\n    #[pyfunction]\n    #[pyo3(warn(message = \"TPW: custom deprecated category\", category = pyo3::exceptions::PyDeprecationWarning))]\n    fn function_with_warning_with_custom_category() {}\n\n    py_expect_warning_for_fn!(\n        function_with_warning_with_custom_category,\n        f,\n        [(\n            \"TPW: custom deprecated category\",\n            pyo3::exceptions::PyDeprecationWarning\n        )]\n    );\n\n    #[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n    #[pyfunction]\n    #[pyo3(warn(message = \"TPW: this function raises user-defined warning\", category = UserDefinedWarning))]\n    fn function_with_warning_and_user_defined_category() {}\n\n    #[cfg(any(not(Py_LIMITED_API), Py_3_12))]\n    py_expect_warning_for_fn!(\n        function_with_warning_and_user_defined_category,\n        f,\n        [(\n            \"TPW: this function raises user-defined warning\",\n            UserDefinedWarning\n        )]\n    );\n}\n\n#[test]\nfn test_pyfunction_multiple_warnings() {\n    #[pyfunction]\n    #[pyo3(warn(message = \"TPMW: this function raises warning\"))]\n    #[pyo3(warn(message = \"TPMW: this function raises FutureWarning\", category = PyFutureWarning))]\n    fn function_with_multiple_warnings() {}\n\n    py_expect_warning_for_fn!(\n        function_with_multiple_warnings,\n        f,\n        [\n            (\"TPMW: this function raises warning\", PyUserWarning),\n            (\"TPMW: this function raises FutureWarning\", PyFutureWarning)\n        ]\n    );\n\n    #[cfg(not(Py_LIMITED_API))]\n    #[pyfunction]\n    #[pyo3(warn(message = \"TPMW: this function raises FutureWarning\", category = PyFutureWarning))]\n    #[pyo3(warn(message = \"TPMW: this function raises user-defined warning\", category = UserDefinedWarning))]\n    fn function_with_multiple_custom_warnings() {}\n\n    #[cfg(not(Py_LIMITED_API))]\n    py_expect_warning_for_fn!(\n        function_with_multiple_custom_warnings,\n        f,\n        [\n            (\"TPMW: this function raises FutureWarning\", PyFutureWarning),\n            (\n                \"TPMW: this function raises user-defined warning\",\n                UserDefinedWarning\n            )\n        ]\n    );\n}\n"
  },
  {
    "path": "tests/test_pyself.rs",
    "content": "#![cfg(feature = \"macros\")]\n\n//! Test slf: PyRef/PyMutRef<Self>(especially, slf.into::<Py>) works\nuse pyo3::prelude::*;\nuse pyo3::types::{PyBytes, PyString};\nuse std::collections::HashMap;\n\nmod test_utils;\n\n/// Assumes it's a file reader or so.\n/// Inspired by https://github.com/jothan/cordoba, thanks.\n#[pyclass(skip_from_py_object)]\n#[derive(Clone, Debug)]\nstruct Reader {\n    inner: HashMap<u8, String>,\n}\n\n#[pymethods]\nimpl Reader {\n    fn clone_ref<'a, 'py>(slf: &'a Bound<'py, Self>) -> &'a Bound<'py, Self> {\n        slf\n    }\n    fn clone_ref_with_py<'a, 'py>(\n        slf: &'a Bound<'py, Self>,\n        _py: Python<'py>,\n    ) -> &'a Bound<'py, Self> {\n        slf\n    }\n    fn get_iter(slf: &Bound<'_, Self>, keys: Py<PyBytes>) -> Iter {\n        Iter {\n            reader: slf.clone().unbind(),\n            keys,\n            idx: 0,\n        }\n    }\n    fn get_iter_and_reset(\n        mut slf: PyRefMut<'_, Self>,\n        keys: Py<PyBytes>,\n        py: Python<'_>,\n    ) -> PyResult<Iter> {\n        let reader = Py::new(py, slf.clone())?;\n        slf.inner.clear();\n        Ok(Iter {\n            reader,\n            keys,\n            idx: 0,\n        })\n    }\n}\n\n#[pyclass]\n#[derive(Debug)]\nstruct Iter {\n    reader: Py<Reader>,\n    keys: Py<PyBytes>,\n    idx: usize,\n}\n\n#[pymethods]\nimpl Iter {\n    #[expect(clippy::self_named_constructors)]\n    fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {\n        slf\n    }\n\n    fn __next__(mut slf: PyRefMut<'_, Self>) -> PyResult<Option<Py<PyAny>>> {\n        let bytes = slf.keys.bind(slf.py()).as_bytes();\n        match bytes.get(slf.idx) {\n            Some(&b) => {\n                slf.idx += 1;\n                let py = slf.py();\n                let reader = slf.reader.bind(py);\n                let reader_ref = reader.try_borrow()?;\n                let res = reader_ref\n                    .inner\n                    .get(&b)\n                    .map(|s| PyString::new(py, s).into());\n                Ok(res)\n            }\n            None => Ok(None),\n        }\n    }\n}\n\nfn reader() -> Reader {\n    let reader = [(1, \"a\"), (2, \"b\"), (3, \"c\"), (4, \"d\"), (5, \"e\")];\n    Reader {\n        inner: reader.iter().map(|(k, v)| (*k, (*v).to_string())).collect(),\n    }\n}\n\n#[test]\nfn test_nested_iter() {\n    Python::attach(|py| {\n        let reader = reader().into_pyobject(py).unwrap();\n        py_assert!(\n            py,\n            reader,\n            \"list(reader.get_iter(bytes([3, 5, 2]))) == ['c', 'e', 'b']\"\n        );\n    });\n}\n\n#[test]\nfn test_clone_ref() {\n    Python::attach(|py| {\n        let reader = reader().into_pyobject(py).unwrap();\n        py_assert!(py, reader, \"reader == reader.clone_ref()\");\n        py_assert!(py, reader, \"reader == reader.clone_ref_with_py()\");\n    });\n}\n\n#[test]\nfn test_nested_iter_reset() {\n    Python::attach(|py| {\n        let reader = Bound::new(py, reader()).unwrap();\n        py_assert!(\n            py,\n            reader,\n            \"list(reader.get_iter_and_reset(bytes([3, 5, 2]))) == ['c', 'e', 'b']\"\n        );\n        let reader_ref = reader.borrow();\n        assert!(reader_ref.inner.is_empty());\n    });\n}\n"
  },
  {
    "path": "tests/test_sequence.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::exceptions::{PyIndexError, PyValueError};\nuse pyo3::types::{IntoPyDict, PyList, PyMapping, PySequence};\nuse pyo3::{ffi, prelude::*};\n\nuse pyo3::py_run;\n\nmod test_utils;\n\n#[pyclass]\nstruct ByteSequence {\n    elements: Vec<u8>,\n}\n\n#[pymethods]\nimpl ByteSequence {\n    #[new]\n    #[pyo3(signature=(elements = None))]\n    fn new(elements: Option<&Bound<'_, PyList>>) -> PyResult<Self> {\n        if let Some(pylist) = elements {\n            let mut elems = Vec::with_capacity(pylist.len());\n            for pyelem in pylist {\n                let elem = pyelem.extract()?;\n                elems.push(elem);\n            }\n            Ok(Self { elements: elems })\n        } else {\n            Ok(Self {\n                elements: Vec::new(),\n            })\n        }\n    }\n\n    fn __len__(&self) -> usize {\n        self.elements.len()\n    }\n\n    fn __getitem__(&self, idx: isize) -> PyResult<u8> {\n        self.elements\n            .get(idx as usize)\n            .copied()\n            .ok_or_else(|| PyIndexError::new_err(\"list index out of range\"))\n    }\n\n    fn __setitem__(&mut self, idx: isize, value: u8) {\n        self.elements[idx as usize] = value;\n    }\n\n    fn __delitem__(&mut self, mut idx: isize) -> PyResult<()> {\n        let self_len = self.elements.len() as isize;\n        if idx < 0 {\n            idx += self_len;\n        }\n        if (idx < self_len) && (idx >= 0) {\n            self.elements.remove(idx as usize);\n            Ok(())\n        } else {\n            Err(PyIndexError::new_err(\"list index out of range\"))\n        }\n    }\n\n    fn __contains__(&self, other: &Bound<'_, PyAny>) -> bool {\n        match other.extract::<u8>() {\n            Ok(x) => self.elements.contains(&x),\n            Err(_) => false,\n        }\n    }\n\n    fn __concat__(&self, other: &Self) -> Self {\n        let mut elements = self.elements.clone();\n        elements.extend_from_slice(&other.elements);\n        Self { elements }\n    }\n\n    fn __inplace_concat__(mut slf: PyRefMut<'_, Self>, other: &Self) -> Py<Self> {\n        slf.elements.extend_from_slice(&other.elements);\n        slf.into()\n    }\n\n    fn __repeat__(&self, count: isize) -> PyResult<Self> {\n        if count >= 0 {\n            let mut elements = Vec::with_capacity(self.elements.len() * count as usize);\n            for _ in 0..count {\n                elements.extend(&self.elements);\n            }\n            Ok(Self { elements })\n        } else {\n            Err(PyValueError::new_err(\"invalid repeat count\"))\n        }\n    }\n\n    fn __inplace_repeat__(mut slf: PyRefMut<'_, Self>, count: isize) -> PyResult<Py<Self>> {\n        if count >= 0 {\n            let mut elements = Vec::with_capacity(slf.elements.len() * count as usize);\n            for _ in 0..count {\n                elements.extend(&slf.elements);\n            }\n            slf.elements = elements;\n            Ok(slf.into())\n        } else {\n            Err(PyValueError::new_err(\"invalid repeat count\"))\n        }\n    }\n}\n\n/// Return a dict with `s = ByteSequence([1, 2, 3])`.\nfn seq_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> {\n    let d = [(\"ByteSequence\", py.get_type::<ByteSequence>())]\n        .into_py_dict(py)\n        .unwrap();\n    // Though we can construct `s` in Rust, let's test `__new__` works.\n    py_run!(py, *d, \"s = ByteSequence([1, 2, 3])\");\n    d\n}\n\n#[test]\nfn test_getitem() {\n    Python::attach(|py| {\n        let d = seq_dict(py);\n\n        py_assert!(py, *d, \"s[0] == 1\");\n        py_assert!(py, *d, \"s[1] == 2\");\n        py_assert!(py, *d, \"s[2] == 3\");\n        py_expect_exception!(py, *d, \"print(s[-4])\", PyIndexError);\n        py_expect_exception!(py, *d, \"print(s[4])\", PyIndexError);\n    });\n}\n\n#[test]\nfn test_setitem() {\n    Python::attach(|py| {\n        let d = seq_dict(py);\n\n        py_run!(py, *d, \"s[0] = 4; assert list(s) == [4, 2, 3]\");\n        py_expect_exception!(py, *d, \"s[0] = 'hello'\", PyTypeError);\n    });\n}\n\n#[test]\nfn test_delitem() {\n    Python::attach(|py| {\n        let d = [(\"ByteSequence\", py.get_type::<ByteSequence>())]\n            .into_py_dict(py)\n            .unwrap();\n\n        py_run!(\n            py,\n            *d,\n            \"s = ByteSequence([1, 2, 3]); del s[0]; assert list(s) == [2, 3]\"\n        );\n        py_run!(\n            py,\n            *d,\n            \"s = ByteSequence([1, 2, 3]); del s[1]; assert list(s) == [1, 3]\"\n        );\n        py_run!(\n            py,\n            *d,\n            \"s = ByteSequence([1, 2, 3]); del s[-1]; assert list(s) == [1, 2]\"\n        );\n        py_run!(\n            py,\n            *d,\n            \"s = ByteSequence([1, 2, 3]); del s[-2]; assert list(s) == [1, 3]\"\n        );\n        py_expect_exception!(\n            py,\n            *d,\n            \"s = ByteSequence([1, 2, 3]); del s[-4]; print(list(s))\",\n            PyIndexError\n        );\n        py_expect_exception!(\n            py,\n            *d,\n            \"s = ByteSequence([1, 2, 3]); del s[4]\",\n            PyIndexError\n        );\n    });\n}\n\n#[test]\nfn test_contains() {\n    Python::attach(|py| {\n        let d = seq_dict(py);\n\n        py_assert!(py, *d, \"1 in s\");\n        py_assert!(py, *d, \"2 in s\");\n        py_assert!(py, *d, \"3 in s\");\n        py_assert!(py, *d, \"4 not in s\");\n        py_assert!(py, *d, \"'hello' not in s\");\n    });\n}\n\n#[test]\nfn test_concat() {\n    Python::attach(|py| {\n        let d = seq_dict(py);\n\n        py_run!(\n        py,\n        *d,\n        \"s1 = ByteSequence([1, 2]); s2 = ByteSequence([3, 4]); assert list(s1 + s2) == [1, 2, 3, 4]\"\n    );\n        py_expect_exception!(\n            py,\n            *d,\n            \"s1 = ByteSequence([1, 2]); s2 = 'hello'; s1 + s2\",\n            PyTypeError\n        );\n    });\n}\n\n#[test]\nfn test_inplace_concat() {\n    Python::attach(|py| {\n        let d = seq_dict(py);\n\n        py_run!(\n            py,\n            *d,\n            \"s += ByteSequence([4, 5]); assert list(s) == [1, 2, 3, 4, 5]\"\n        );\n        py_expect_exception!(py, *d, \"s += 'hello'\", PyTypeError);\n    });\n}\n\n#[test]\nfn test_repeat() {\n    Python::attach(|py| {\n        let d = seq_dict(py);\n\n        py_run!(py, *d, \"s2 = s * 2; assert list(s2) == [1, 2, 3, 1, 2, 3]\");\n        py_expect_exception!(py, *d, \"s2 = s * -1\", PyValueError);\n    });\n}\n\n#[test]\nfn test_inplace_repeat() {\n    Python::attach(|py| {\n        let d = [(\"ByteSequence\", py.get_type::<ByteSequence>())]\n            .into_py_dict(py)\n            .unwrap();\n\n        py_run!(\n            py,\n            *d,\n            \"s = ByteSequence([1, 2]); s *= 3; assert list(s) == [1, 2, 1, 2, 1, 2]\"\n        );\n        py_expect_exception!(py, *d, \"s = ByteSequence([1, 2]); s *= -1\", PyValueError);\n    });\n}\n\n// Check that #[pyo3(get, set)] works correctly for Vec<PyObject>\n\n#[pyclass]\nstruct AnyObjectList {\n    #[pyo3(get, set)]\n    items: Vec<Py<PyAny>>,\n}\n\n#[test]\nfn test_any_object_list_get() {\n    Python::attach(|py| {\n        let list = AnyObjectList {\n            items: [1i32, 2, 3]\n                .iter()\n                .map(|i| i.into_pyobject(py).unwrap().into_any().unbind())\n                .collect(),\n        }\n        .into_pyobject(py)\n        .unwrap();\n\n        py_assert!(py, list, \"list.items == [1, 2, 3]\");\n    });\n}\n\n#[test]\nfn test_any_object_list_set() {\n    Python::attach(|py| {\n        let list = Bound::new(py, AnyObjectList { items: vec![] }).unwrap();\n\n        py_run!(py, list, \"list.items = [1, 2, 3]\");\n        assert!(list\n            .borrow()\n            .items\n            .iter()\n            .zip(&[1u32, 2, 3])\n            .all(|(a, b)| a.bind(py).eq(b.into_pyobject(py).unwrap()).unwrap()));\n    });\n}\n\n#[pyclass(sequence)]\nstruct OptionList {\n    #[pyo3(get, set)]\n    items: Vec<Option<i64>>,\n}\n\n#[pymethods]\nimpl OptionList {\n    fn __len__(&self) -> usize {\n        self.items.len()\n    }\n\n    fn __getitem__(&self, idx: isize) -> PyResult<Option<i64>> {\n        match self.items.get(idx as usize) {\n            Some(x) => Ok(*x),\n            None => Err(PyIndexError::new_err(\"Index out of bounds\")),\n        }\n    }\n}\n\n#[test]\nfn test_option_list_get() {\n    // Regression test for #798\n    Python::attach(|py| {\n        let list = Py::new(\n            py,\n            OptionList {\n                items: vec![Some(1), None],\n            },\n        )\n        .unwrap();\n\n        py_assert!(py, list, \"list[0] == 1\");\n        py_assert!(py, list, \"list[1] == None\");\n        py_expect_exception!(py, list, \"list[2]\", PyIndexError);\n    });\n}\n\n#[test]\nfn sequence_is_not_mapping() {\n    Python::attach(|py| {\n        let list = Bound::new(\n            py,\n            OptionList {\n                items: vec![Some(1), None],\n            },\n        )\n        .unwrap()\n        .into_any();\n\n        PySequence::register::<OptionList>(py).unwrap();\n\n        assert!(list.cast::<PyMapping>().is_err());\n        assert!(list.cast::<PySequence>().is_ok());\n    })\n}\n\n#[test]\nfn sequence_length() {\n    Python::attach(|py| {\n        let list = Bound::new(\n            py,\n            OptionList {\n                items: vec![Some(1), None],\n            },\n        )\n        .unwrap()\n        .into_any();\n\n        assert_eq!(list.len().unwrap(), 2);\n        assert_eq!(unsafe { ffi::PySequence_Length(list.as_ptr()) }, 2);\n\n        assert_eq!(unsafe { ffi::PyMapping_Length(list.as_ptr()) }, -1);\n        unsafe { ffi::PyErr_Clear() };\n    })\n}\n\n#[cfg(Py_3_10)]\n#[pyclass(generic, sequence)]\nstruct GenericList {\n    #[pyo3(get, set)]\n    items: Vec<Py<PyAny>>,\n}\n\n#[cfg(Py_3_10)]\n#[pymethods]\nimpl GenericList {\n    fn __len__(&self) -> usize {\n        self.items.len()\n    }\n\n    fn __getitem__(&self, idx: isize) -> PyResult<Py<PyAny>> {\n        match self.items.get(idx as usize) {\n            Some(x) => pyo3::Python::attach(|py| Ok(x.clone_ref(py))),\n            None => Err(PyIndexError::new_err(\"Index out of bounds\")),\n        }\n    }\n}\n\n#[cfg(Py_3_10)]\n#[test]\nfn test_generic_both_subscriptions_types() {\n    use pyo3::types::PyInt;\n    use std::convert::Infallible;\n\n    Python::attach(|py| {\n        let l = Bound::new(\n            py,\n            GenericList {\n                items: [1, 2, 3]\n                    .iter()\n                    .map(|x| -> Py<PyAny> {\n                        let x: Result<Bound<'_, PyInt>, Infallible> = x.into_pyobject(py);\n                        x.unwrap().into_any().unbind()\n                    })\n                    .chain([py.None()])\n                    .collect(),\n            },\n        )\n        .unwrap();\n        let ty = py.get_type::<GenericList>();\n        py_assert!(py, l, \"l[0] == 1\");\n        py_run!(\n            py,\n            ty,\n            \"import types;\n            import typing;\n            IntOrNone: typing.TypeAlias = typing.Union[int, None];\n            assert ty[IntOrNone] == types.GenericAlias(ty, (IntOrNone,))\"\n        );\n        py_assert!(py, l, \"list(reversed(l)) == [None, 3, 2, 1]\");\n    });\n}\n"
  },
  {
    "path": "tests/test_serde.rs",
    "content": "#[cfg(feature = \"serde\")]\nmod test_serde {\n    use pyo3::prelude::*;\n\n    use serde::{Deserialize, Serialize};\n\n    #[pyclass]\n    #[derive(Debug, Serialize, Deserialize)]\n    struct Group {\n        name: String,\n    }\n\n    #[pyclass]\n    #[derive(Debug, Serialize, Deserialize)]\n    struct User {\n        username: String,\n        group: Option<Py<Group>>,\n        friends: Vec<Py<User>>,\n    }\n\n    #[test]\n    fn test_serialize() {\n        let friend1 = User {\n            username: \"friend 1\".into(),\n            group: None,\n            friends: vec![],\n        };\n        let friend2 = User {\n            username: \"friend 2\".into(),\n            group: None,\n            friends: vec![],\n        };\n\n        let user = Python::attach(|py| {\n            let py_friend1 = Py::new(py, friend1).expect(\"failed to create friend 1\");\n            let py_friend2 = Py::new(py, friend2).expect(\"failed to create friend 2\");\n\n            let friends = vec![py_friend1, py_friend2];\n            let py_group = Py::new(\n                py,\n                Group {\n                    name: \"group name\".into(),\n                },\n            )\n            .unwrap();\n\n            User {\n                username: \"danya\".into(),\n                group: Some(py_group),\n                friends,\n            }\n        });\n\n        let serialized = serde_json::to_string(&user).expect(\"failed to serialize\");\n        assert_eq!(\n            serialized,\n            r#\"{\"username\":\"danya\",\"group\":{\"name\":\"group name\"},\"friends\":[{\"username\":\"friend 1\",\"group\":null,\"friends\":[]},{\"username\":\"friend 2\",\"group\":null,\"friends\":[]}]}\"#\n        );\n    }\n\n    #[test]\n    fn test_deserialize() {\n        let serialized = r#\"{\"username\": \"danya\", \"friends\":\n        [{\"username\": \"friend\", \"group\": {\"name\": \"danya's friends\"}, \"friends\": []}]}\"#;\n        let user: User = serde_json::from_str(serialized).expect(\"failed to deserialize\");\n\n        assert_eq!(user.username, \"danya\");\n        assert!(user.group.is_none());\n        assert_eq!(user.friends.len(), 1usize);\n        let friend = user.friends.first().unwrap();\n\n        Python::attach(|py| {\n            assert_eq!(friend.borrow(py).username, \"friend\");\n            assert_eq!(\n                friend.borrow(py).group.as_ref().unwrap().borrow(py).name,\n                \"danya's friends\"\n            )\n        });\n    }\n}\n"
  },
  {
    "path": "tests/test_static_slots.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::exceptions::PyIndexError;\nuse pyo3::prelude::*;\nuse pyo3::types::IntoPyDict;\n\nuse pyo3::py_run;\n\nmod test_utils;\n\n#[pyclass]\nstruct Count5();\n\n#[pymethods]\nimpl Count5 {\n    #[new]\n    fn new() -> Self {\n        Self()\n    }\n\n    #[staticmethod]\n    fn __len__() -> usize {\n        5\n    }\n\n    #[staticmethod]\n    fn __getitem__(idx: isize) -> PyResult<f64> {\n        if idx < 0 {\n            Err(PyIndexError::new_err(\"Count5 cannot count backwards\"))\n        } else if idx > 4 {\n            Err(PyIndexError::new_err(\"Count5 cannot count higher than 5\"))\n        } else {\n            Ok(idx as f64 + 1.0)\n        }\n    }\n}\n\n/// Return a dict with `s = Count5()`.\nfn test_dict(py: Python<'_>) -> Bound<'_, pyo3::types::PyDict> {\n    let d = [(\"Count5\", py.get_type::<Count5>())]\n        .into_py_dict(py)\n        .unwrap();\n    // Though we can construct `s` in Rust, let's test `__new__` works.\n    py_run!(py, *d, \"s = Count5()\");\n    d\n}\n\n#[test]\nfn test_len() {\n    Python::attach(|py| {\n        let d = test_dict(py);\n\n        py_assert!(py, *d, \"len(s) == 5\");\n    });\n}\n\n#[test]\nfn test_getitem() {\n    Python::attach(|py| {\n        let d = test_dict(py);\n\n        py_assert!(py, *d, \"s[4] == 5.0\");\n    });\n}\n\n#[test]\nfn test_list() {\n    Python::attach(|py| {\n        let d = test_dict(py);\n\n        py_assert!(py, *d, \"list(s) == [1.0, 2.0, 3.0, 4.0, 5.0]\");\n    });\n}\n"
  },
  {
    "path": "tests/test_string.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\n\nmod test_utils;\n\n#[pyfunction]\nfn take_str(_s: &str) {}\n\n#[test]\nfn test_unicode_encode_error() {\n    Python::attach(|py| {\n        let take_str = wrap_pyfunction!(take_str)(py).unwrap();\n        py_expect_exception!(\n            py,\n            take_str,\n            \"take_str('\\\\ud800')\",\n            PyUnicodeEncodeError,\n            \"'utf-8' codec can't encode character '\\\\ud800' in position 0: surrogates not allowed\"\n        );\n    });\n}\n"
  },
  {
    "path": "tests/test_super.rs",
    "content": "#![cfg(all(feature = \"macros\", not(any(PyPy, GraalPy))))]\n\nuse pyo3::{prelude::*, types::PySuper};\n\n#[pyclass(subclass)]\nstruct BaseClass {\n    val1: usize,\n}\n\n#[pymethods]\nimpl BaseClass {\n    #[new]\n    fn new() -> Self {\n        BaseClass { val1: 10 }\n    }\n\n    pub fn method(&self) -> usize {\n        self.val1\n    }\n}\n\n#[pyclass(extends=BaseClass)]\nstruct SubClass {}\n\n#[pymethods]\nimpl SubClass {\n    #[new]\n    fn new() -> (Self, BaseClass) {\n        (SubClass {}, BaseClass::new())\n    }\n\n    fn method<'py>(self_: &Bound<'py, Self>) -> PyResult<Bound<'py, PyAny>> {\n        let super_ = self_.py_super()?;\n        super_.call_method(\"method\", (), None)\n    }\n\n    fn method_super_new<'py>(self_: &Bound<'py, Self>) -> PyResult<Bound<'py, PyAny>> {\n        let super_ = PySuper::new(&self_.get_type(), self_)?;\n        super_.call_method(\"method\", (), None)\n    }\n}\n\n#[test]\nfn test_call_super_method() {\n    Python::attach(|py| {\n        let cls = py.get_type::<SubClass>();\n        pyo3::py_run!(\n            py,\n            cls,\n            r#\"\n        obj = cls()\n        assert obj.method() == 10\n        assert obj.method_super_new() == 10\n    \"#\n        )\n    });\n}\n"
  },
  {
    "path": "tests/test_text_signature.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\nuse pyo3::types::{PyDict, PyTuple};\nuse pyo3::{types::PyType, wrap_pymodule};\n\nmod test_utils;\n\n#[test]\nfn class_without_docs_or_signature() {\n    #[pyclass]\n    struct MyClass {}\n\n    Python::attach(|py| {\n        let typeobj = py.get_type::<MyClass>();\n\n        py_assert!(py, typeobj, \"typeobj.__doc__ is None\");\n        py_assert!(py, typeobj, \"typeobj.__text_signature__ is None\");\n    });\n}\n\n#[test]\nfn class_with_docs() {\n    /// docs line1\n    #[pyclass]\n    /// docs line2\n    struct MyClass {}\n\n    Python::attach(|py| {\n        let typeobj = py.get_type::<MyClass>();\n\n        py_assert!(py, typeobj, \"typeobj.__doc__ == 'docs line1\\\\ndocs line2'\");\n        py_assert!(py, typeobj, \"typeobj.__text_signature__ is None\");\n    });\n}\n\n#[test]\n#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]\nfn class_with_signature_no_doc() {\n    #[pyclass]\n    struct MyClass {}\n\n    #[pymethods]\n    impl MyClass {\n        #[new]\n        #[pyo3(signature = (a, b=None, *, c=42), text_signature = \"(a, b=None, *, c=42)\")]\n        fn __new__(a: i32, b: Option<i32>, c: i32) -> Self {\n            let _ = (a, b, c);\n            Self {}\n        }\n    }\n\n    Python::attach(|py| {\n        let typeobj = py.get_type::<MyClass>();\n        py_assert!(py, typeobj, \"typeobj.__doc__ == ''\");\n        py_assert!(\n            py,\n            typeobj,\n            \"typeobj.__text_signature__ == '(a, b=None, *, c=42)'\"\n        );\n    });\n}\n\n#[test]\n#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]\nfn class_with_docs_and_signature() {\n    /// docs line1\n    #[pyclass]\n    /// docs line2\n    struct MyClass {}\n\n    #[pymethods]\n    impl MyClass {\n        #[new]\n        #[pyo3(signature = (a, b=None, *, c=42), text_signature = \"(a, b=None, *, c=42)\")]\n        fn __new__(a: i32, b: Option<i32>, c: i32) -> Self {\n            let _ = (a, b, c);\n            Self {}\n        }\n    }\n\n    Python::attach(|py| {\n        let typeobj = py.get_type::<MyClass>();\n\n        py_assert!(py, typeobj, \"typeobj.__doc__ == 'docs line1\\\\ndocs line2'\");\n        py_assert!(\n            py,\n            typeobj,\n            \"typeobj.__text_signature__ == '(a, b=None, *, c=42)'\"\n        );\n    });\n}\n\n#[test]\nfn test_function() {\n    #[pyfunction(signature = (a, b=None, *, c=42))]\n    #[pyo3(text_signature = \"(a, b=None, *, c=42)\")]\n    fn my_function(a: i32, b: Option<i32>, c: i32) {\n        let _ = (a, b, c);\n    }\n\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(my_function)(py).unwrap();\n\n        py_assert!(py, f, \"f.__text_signature__ == '(a, b=None, *, c=42)'\");\n    });\n}\n\n#[test]\nfn test_auto_test_signature_function() {\n    #[pyfunction]\n    fn my_function(a: i32, b: i32, c: i32) {\n        let _ = (a, b, c);\n    }\n\n    #[pyfunction(pass_module)]\n    fn my_function_2(module: &Bound<'_, PyModule>, a: i32, b: i32, c: i32) {\n        let _ = (module, a, b, c);\n    }\n\n    #[pyfunction(signature = (a, /, b = None, *, c = 5))]\n    fn my_function_3(a: i32, b: Option<i32>, c: i32) {\n        let _ = (a, b, c);\n    }\n\n    #[pyfunction(signature = (a, /, b = None, *args, c, d=5, **kwargs))]\n    fn my_function_4(\n        a: i32,\n        b: Option<i32>,\n        args: &Bound<'_, PyTuple>,\n        c: i32,\n        d: i32,\n        kwargs: Option<&Bound<'_, PyDict>>,\n    ) {\n        let _ = (a, b, args, c, d, kwargs);\n    }\n\n    #[pyfunction(signature = (a = 1, /, b = None, c = 1.5, d=5, e = \"pyo3\", f = 'f', h = true))]\n    fn my_function_5(a: i32, b: Option<i32>, c: f32, d: i32, e: &str, f: char, h: bool) {\n        let _ = (a, b, c, d, e, f, h);\n    }\n\n    #[pyfunction]\n    #[pyo3(signature=(a, b=None, c=None))]\n    fn my_function_6(a: i32, b: Option<i32>, c: Option<i32>) {\n        let _ = (a, b, c);\n    }\n\n    #[pyfunction]\n    fn trailing_optional_required(a: i32, b: Option<i32>, c: Option<i32>) {\n        // Since PyO3 0.24, trailing optional arguments are treated like any other required argument\n        // (previously would get an implicit default of `None`)\n        let _ = (a, b, c);\n    }\n\n    macro_rules! assert_text_signature {\n        ($py:expr, $func:ident, $expected:expr) => {\n            assert_eq!(\n                wrap_pyfunction!($func, $py)\n                    .unwrap()\n                    .getattr(\"__text_signature__\")\n                    .unwrap()\n                    .cast_into::<pyo3::types::PyString>()\n                    .unwrap(),\n                $expected\n            );\n        };\n    }\n\n    Python::attach(|py| {\n        assert_text_signature!(py, my_function, \"(a, b, c)\");\n\n        assert_text_signature!(py, my_function_2, \"($module, a, b, c)\");\n\n        assert_text_signature!(py, my_function_3, \"(a, /, b=None, *, c=5)\");\n\n        assert_text_signature!(py, my_function_4, \"(a, /, b=None, *args, c, d=5, **kwargs)\");\n\n        assert_text_signature!(\n            py,\n            my_function_5,\n            \"(a=1, /, b=None, c=1.5, d=5, e=\\\"pyo3\\\", f='f', h=True)\"\n        );\n\n        assert_text_signature!(py, my_function_6, \"(a, b=None, c=None)\");\n\n        assert_text_signature!(py, trailing_optional_required, \"(a, b, c)\");\n    });\n}\n\n#[test]\nfn test_auto_test_signature_method() {\n    #[pyclass]\n    struct MyClass {}\n\n    #[pymethods]\n    impl MyClass {\n        #[new]\n        fn new(a: i32, b: i32, c: i32) -> Self {\n            let _ = (a, b, c);\n            Self {}\n        }\n\n        fn method(&self, a: i32, b: i32, c: i32) {\n            let _ = (a, b, c);\n        }\n\n        #[pyo3(signature = (a, /, b = None, *, c = 5))]\n        fn method_2(&self, a: i32, b: Option<i32>, c: i32) {\n            let _ = (a, b, c);\n        }\n\n        #[pyo3(signature = (a, /, b = None, *args, c, d=5, **kwargs))]\n        fn method_3(\n            &self,\n            a: i32,\n            b: Option<i32>,\n            args: &Bound<'_, PyTuple>,\n            c: i32,\n            d: i32,\n            kwargs: Option<&Bound<'_, PyDict>>,\n        ) {\n            let _ = (a, b, args, c, d, kwargs);\n        }\n\n        #[staticmethod]\n        fn staticmethod(a: i32, b: i32, c: i32) {\n            let _ = (a, b, c);\n        }\n\n        #[classmethod]\n        fn classmethod(cls: &Bound<'_, PyType>, a: i32, b: i32, c: i32) {\n            let _ = (cls, a, b, c);\n        }\n    }\n\n    Python::attach(|py| {\n        let cls = py.get_type::<MyClass>();\n        #[cfg(any(not(Py_LIMITED_API), Py_3_10))]\n        py_assert!(py, cls, \"cls.__text_signature__ == '(a, b, c)'\");\n        py_assert!(\n            py,\n            cls,\n            \"cls.method.__text_signature__ == '($self, a, b, c)'\"\n        );\n        py_assert!(\n            py,\n            cls,\n            \"cls.method_2.__text_signature__ == '($self, a, /, b=None, *, c=5)'\"\n        );\n        py_assert!(\n            py,\n            cls,\n            \"cls.method_3.__text_signature__ == '($self, a, /, b=None, *args, c, d=5, **kwargs)'\"\n        );\n        py_assert!(\n            py,\n            cls,\n            \"cls.staticmethod.__text_signature__ == '(a, b, c)'\"\n        );\n        py_assert!(\n            py,\n            cls,\n            \"cls.classmethod.__text_signature__ == '($cls, a, b, c)'\"\n        );\n    });\n}\n\n#[test]\nfn test_auto_test_signature_opt_out() {\n    #[pyfunction(text_signature = None)]\n    fn my_function(a: i32, b: i32, c: i32) {\n        let _ = (a, b, c);\n    }\n\n    #[pyfunction(signature = (a, /, b = None, *, c = 5), text_signature = None)]\n    fn my_function_2(a: i32, b: Option<i32>, c: i32) {\n        let _ = (a, b, c);\n    }\n\n    #[pyclass]\n    struct MyClass {}\n\n    #[pymethods]\n    impl MyClass {\n        #[new]\n        #[pyo3(text_signature = None)]\n        fn new(a: i32, b: i32, c: i32) -> Self {\n            let _ = (a, b, c);\n            Self {}\n        }\n\n        #[pyo3(text_signature = None)]\n        fn method(&self, a: i32, b: i32, c: i32) {\n            let _ = (a, b, c);\n        }\n\n        #[pyo3(signature = (a, /, b = None, *, c = 5), text_signature = None)]\n        fn method_2(&self, a: i32, b: Option<i32>, c: i32) {\n            let _ = (a, b, c);\n        }\n\n        #[staticmethod]\n        #[pyo3(text_signature = None)]\n        fn staticmethod(a: i32, b: i32, c: i32) {\n            let _ = (a, b, c);\n        }\n\n        #[classmethod]\n        #[pyo3(text_signature = None)]\n        fn classmethod(cls: &Bound<'_, PyType>, a: i32, b: i32, c: i32) {\n            let _ = (cls, a, b, c);\n        }\n    }\n\n    Python::attach(|py| {\n        let f = wrap_pyfunction!(my_function)(py).unwrap();\n        py_assert!(py, f, \"f.__text_signature__ == None\");\n\n        let f = wrap_pyfunction!(my_function_2)(py).unwrap();\n        py_assert!(py, f, \"f.__text_signature__ == None\");\n\n        let cls = py.get_type::<MyClass>();\n        py_assert!(py, cls, \"cls.__text_signature__ == None\");\n        py_assert!(py, cls, \"cls.method.__text_signature__ == None\");\n        py_assert!(py, cls, \"cls.method_2.__text_signature__ == None\");\n        py_assert!(py, cls, \"cls.staticmethod.__text_signature__ == None\");\n        py_assert!(py, cls, \"cls.classmethod.__text_signature__ == None\");\n    });\n}\n\n#[test]\n#[allow(deprecated)]\nfn test_pyfn() {\n    #[pymodule]\n    fn my_module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n        #[pyfn(m, signature = (a, b=None, *, c=42))]\n        #[pyo3(text_signature = \"(a, b=None, *, c=42)\")]\n        fn my_function(a: i32, b: Option<i32>, c: i32) {\n            let _ = (a, b, c);\n        }\n        Ok(())\n    }\n\n    Python::attach(|py| {\n        let m = wrap_pymodule!(my_module)(py);\n\n        py_assert!(\n            py,\n            m,\n            \"m.my_function.__text_signature__ == '(a, b=None, *, c=42)'\"\n        );\n    });\n}\n\n#[test]\nfn test_methods() {\n    #[pyclass]\n    struct MyClass {}\n\n    #[pymethods]\n    impl MyClass {\n        #[pyo3(text_signature = \"($self, a)\")]\n        fn method(&self, a: i32) {\n            let _ = a;\n        }\n        #[pyo3(text_signature = \"($self, b)\")]\n        fn pyself_method(_this: &Bound<'_, Self>, b: i32) {\n            let _ = b;\n        }\n        #[classmethod]\n        #[pyo3(text_signature = \"($cls, c)\")]\n        fn class_method(_cls: &Bound<'_, PyType>, c: i32) {\n            let _ = c;\n        }\n        #[staticmethod]\n        #[pyo3(text_signature = \"(d)\")]\n        fn static_method(d: i32) {\n            let _ = d;\n        }\n    }\n\n    Python::attach(|py| {\n        let typeobj = py.get_type::<MyClass>();\n\n        py_assert!(\n            py,\n            typeobj,\n            \"typeobj.method.__text_signature__ == '($self, a)'\"\n        );\n        py_assert!(\n            py,\n            typeobj,\n            \"typeobj.pyself_method.__text_signature__ == '($self, b)'\"\n        );\n        py_assert!(\n            py,\n            typeobj,\n            \"typeobj.class_method.__text_signature__ == '($cls, c)'\"\n        );\n        py_assert!(\n            py,\n            typeobj,\n            \"typeobj.static_method.__text_signature__ == '(d)'\"\n        );\n    });\n}\n\n#[test]\n#[cfg_attr(all(Py_LIMITED_API, not(Py_3_10)), ignore)]\nfn test_raw_identifiers() {\n    #[pyclass]\n    struct r#MyClass {}\n\n    #[pymethods]\n    impl MyClass {\n        #[new]\n        fn new() -> MyClass {\n            MyClass {}\n        }\n        fn r#method(&self) {}\n    }\n\n    Python::attach(|py| {\n        let typeobj = py.get_type::<MyClass>();\n\n        py_assert!(py, typeobj, \"typeobj.__text_signature__ == '()'\");\n\n        py_assert!(\n            py,\n            typeobj,\n            \"typeobj.method.__text_signature__ == '($self)'\"\n        );\n    });\n}\n"
  },
  {
    "path": "tests/test_utils/mod.rs",
    "content": "// Common macros and helpers for tests\n//\n// This file is used in two different ways, which makes it a bit of a pain to build:\n// - as a module `include!`-ed from `src/test_utils.rs`\n// - as a module `mod test_utils` in various integration tests\n//\n// the inner mod enables the #![allow(dead_code)] to\n// be applied - `src/test_utils.rs` uses `include!` to pull in this file\n\n#[allow(\n    dead_code,\n    unused_macros,\n    reason = \"many tests do not use the complete set of functionality offered here\"\n)]\n#[allow(missing_docs, reason = \"only used in tests\")]\n#[macro_use]\nmod inner {\n\n    #[allow(\n        unused_imports,\n        reason = \"pulls in `use crate as pyo3` from src/test_utils.rs, no function in integration tests\"\n    )]\n    use super::*;\n\n    use pyo3::prelude::*;\n\n    #[cfg(any(not(all(Py_GIL_DISABLED, Py_3_14)), all(feature = \"macros\", Py_3_8)))]\n    use pyo3::sync::MutexExt;\n    use pyo3::types::{IntoPyDict, PyList};\n\n    #[cfg(any(not(all(Py_GIL_DISABLED, Py_3_14)), all(feature = \"macros\", Py_3_8)))]\n    use std::sync::{Mutex, PoisonError};\n\n    use uuid::Uuid;\n\n    #[macro_export]\n    macro_rules! py_assert {\n        ($py:expr, $($val:ident)+, $assertion:literal) => {\n            pyo3::py_run!($py, $($val)+, concat!(\"assert \", $assertion))\n        };\n        ($py:expr, *$dict:expr, $assertion:literal) => {\n            pyo3::py_run!($py, *$dict, concat!(\"assert \", $assertion))\n        };\n    }\n\n    #[macro_export]\n    macro_rules! assert_py_eq {\n        ($val:expr, $expected:expr) => {\n            assert!($val.eq($expected).unwrap());\n        };\n    }\n\n    #[macro_export]\n    macro_rules! py_expect_exception {\n        // Case1: idents & no err_msg\n        ($py:expr, $($val:ident)+, $code:expr, $err:ident) => {{\n            use pyo3::types::IntoPyDict;\n            use pyo3::BoundObject;\n            let d = [$((stringify!($val), (&$val).into_pyobject($py).unwrap().into_any().into_bound()),)+].into_py_dict($py).unwrap();\n            py_expect_exception!($py, *d, $code, $err)\n        }};\n        // Case2: dict & no err_msg\n        ($py:expr, *$dict:expr, $code:expr, $err:ident) => {{\n            let res = $py.run(&std::ffi::CString::new($code).unwrap(), None, Some(&$dict.as_borrowed()));\n            let err = res.expect_err(&format!(\"Did not raise {}\", stringify!($err)));\n            if !err.matches($py, $py.get_type::<pyo3::exceptions::$err>()).unwrap() {\n                panic!(\"Expected {} but got {:?}\", stringify!($err), err)\n            }\n            err\n        }};\n        // Case3: idents & err_msg\n        ($py:expr, $($val:ident)+, $code:expr, $err:ident, $err_msg:literal $(,$notes:literal)*) => {{\n            let err = py_expect_exception!($py, $($val)+, $code, $err);\n            // Suppose that the error message looks like 'TypeError: ~'\n            assert_eq!(format!(\"Py{}\", err), concat!(stringify!($err), \": \", $err_msg));\n            if err.value($py).hasattr(\"add_note\").unwrap() {\n                let notes = err.value($py).getattr(\"__notes__\").map(|n| n.cast_into::<pyo3::types::PyList>().unwrap()).unwrap_or_else(|_| pyo3::types::PyList::empty($py));\n                let mut _notes_iter = notes.iter();\n                $(\n                    assert_eq!(_notes_iter.next().as_ref().map(|v| v.extract::<std::borrow::Cow<'_, str>>().unwrap()).as_deref(), Some($notes));\n                )*\n            }\n            err\n        }};\n        // Case4: dict & err_msg\n        ($py:expr, *$dict:expr, $code:expr, $err:ident, $err_msg:literal) => {{\n            let err = py_expect_exception!($py, *$dict, $code, $err);\n            assert_eq!(format!(\"Py{}\", err), concat!(stringify!($err), \": \", $err_msg));\n            err\n        }};\n    }\n\n    #[macro_export]\n    macro_rules! py_expect_warning {\n        ($py:expr, $($val:ident)+, $code:expr, [$(($warning_msg:literal, $warning_category:path)),+] $(,)?) => {{\n            use pyo3::types::IntoPyDict;\n            let d = [$((stringify!($val), ($val.as_ref() as &Bound<'_, PyAny>).into_pyobject($py).expect(\"Failed to create test dict element\")),)+].into_py_dict($py).expect(\"Failed to create test dict\");\n            py_expect_warning!($py, *d, $code, [$(($warning_msg, $warning_category)),+])\n        }};\n        ($py:expr, *$dict:expr, $code:expr, [$(($warning_msg:literal, $warning_category:path)),+] $(,)?) => {{\n            $crate::test_utils::CatchWarnings::enter($py, |warning_record| {\n                $py.run(&std::ffi::CString::new($code).unwrap(), None, Some(&$dict.as_borrowed())).expect(\"Failed to run warning testing code\");\n                let expected_warnings = [$(($warning_msg, <$warning_category as pyo3::PyTypeInfo>::type_object($py))),+];\n\n                assert_eq!(warning_record.len(), expected_warnings.len(), \"Expecting {} warnings but got {}\", expected_warnings.len(), warning_record.len());\n\n                for ((index, warning), (msg, category)) in warning_record.iter().enumerate().zip(expected_warnings.iter()) {\n                    let actual_msg = warning.getattr(\"message\").unwrap().str().unwrap().to_string_lossy().to_string();\n                    let actual_category = warning.getattr(\"category\").unwrap();\n\n                    assert_eq!(actual_msg, msg.to_string(), \"Warning message mismatch at index {}, expecting `{}` but got `{}`\", index, msg, actual_msg);\n                    assert!(actual_category.is(category), \"Warning category mismatch at index {}, expecting {:?} but got {:?}\", index, category, actual_category);\n                }\n\n                Ok(())\n            }).expect(\"failed to test warnings\");\n        }};\n    }\n\n    #[macro_export]\n    macro_rules! py_expect_warning_for_fn {\n        ($fn:ident, $($val:ident)+, [$(($warning_msg:literal, $warning_category:path)),+] $(,)?) => {\n            pyo3::Python::attach(|py| {\n                let f = wrap_pyfunction!($fn)(py).unwrap();\n                py_expect_warning!(\n                    py,\n                    f,\n                    \"f()\",\n                    [$(($warning_msg, $warning_category)),+]\n                );\n            });\n        };\n    }\n\n    // sys.unraisablehook not available until Python 3.8\n    #[cfg(all(feature = \"macros\", Py_3_8))]\n    pub struct UnraisableCapture<'py> {\n        hook: Bound<'py, UnraisableCaptureHook>,\n    }\n\n    #[cfg(all(feature = \"macros\", Py_3_8))]\n    impl<'py> UnraisableCapture<'py> {\n        /// Runs the closure `f` with a custom sys.unraisablehook installed.\n        ///\n        /// `f`\n        pub fn enter<R>(py: Python<'py>, f: impl FnOnce(&Self) -> R) -> R {\n            // unraisablehook is a global, so only one thread can be using this struct at a time.\n            static UNRAISABLE_HOOK_MUTEX: Mutex<()> = Mutex::new(());\n\n            // NB this is best-effort, other tests could always modify sys.unraisablehook directly.\n            let mutex_guard = UNRAISABLE_HOOK_MUTEX\n                .lock_py_attached(py)\n                .unwrap_or_else(PoisonError::into_inner);\n\n            let guard = Self {\n                hook: UnraisableCaptureHook::install(py),\n            };\n\n            let result = f(&guard);\n\n            drop(guard);\n            drop(mutex_guard);\n\n            result\n        }\n\n        /// Takes the captured unraisable error, if any.\n        pub fn take_capture(&self) -> Option<(PyErr, Bound<'py, PyAny>)> {\n            let mut guard = self.hook.get().capture.lock().unwrap();\n            guard.take().map(|(e, o)| (e, o.into_bound(self.hook.py())))\n        }\n    }\n\n    #[cfg(all(feature = \"macros\", Py_3_8))]\n    impl Drop for UnraisableCapture<'_> {\n        fn drop(&mut self) {\n            let py = self.hook.py();\n            self.hook.get().uninstall(py);\n        }\n    }\n\n    #[cfg(all(feature = \"macros\", Py_3_8))]\n    #[pyclass(crate = \"pyo3\", frozen)]\n    struct UnraisableCaptureHook {\n        pub capture: Mutex<Option<(PyErr, Py<PyAny>)>>,\n        old_hook: Py<PyAny>,\n    }\n\n    #[cfg(all(feature = \"macros\", Py_3_8))]\n    #[pymethods(crate = \"pyo3\")]\n    impl UnraisableCaptureHook {\n        pub fn hook(&self, unraisable: Bound<'_, PyAny>) {\n            let err = PyErr::from_value(unraisable.getattr(\"exc_value\").unwrap());\n            let instance = unraisable.getattr(\"object\").unwrap();\n            self.capture.lock().unwrap().replace((err, instance.into()));\n        }\n    }\n\n    #[cfg(all(feature = \"macros\", Py_3_8))]\n    impl UnraisableCaptureHook {\n        fn install(py: Python<'_>) -> Bound<'_, Self> {\n            let sys = py.import(\"sys\").unwrap();\n\n            let old_hook = sys.getattr(\"unraisablehook\").unwrap().into();\n            let capture = Mutex::new(None);\n\n            let capture = Bound::new(py, UnraisableCaptureHook { capture, old_hook }).unwrap();\n\n            sys.setattr(\"unraisablehook\", capture.getattr(\"hook\").unwrap())\n                .unwrap();\n\n            capture\n        }\n\n        fn uninstall(&self, py: Python<'_>) {\n            let sys = py.import(\"sys\").unwrap();\n            sys.setattr(\"unraisablehook\", &self.old_hook).unwrap();\n        }\n    }\n\n    pub struct CatchWarnings<'py> {\n        catch_warnings: Bound<'py, PyAny>,\n    }\n\n    /// catch_warnings is not thread-safe, so only one thread can be using this struct at\n    /// a time.\n    #[cfg(not(all(Py_GIL_DISABLED, Py_3_14)))] // Python 3.14t has thread-safe catch_warnings\n    static CATCH_WARNINGS_MUTEX: Mutex<()> = Mutex::new(());\n\n    impl<'py> CatchWarnings<'py> {\n        pub fn enter<R>(\n            py: Python<'py>,\n            f: impl FnOnce(&Bound<'py, PyList>) -> PyResult<R>,\n        ) -> PyResult<R> {\n            // NB this is best-effort, other tests could always call the warnings API directly.\n            #[cfg(not(all(Py_GIL_DISABLED, Py_3_14)))]\n            let _mutex_guard = CATCH_WARNINGS_MUTEX\n                .lock_py_attached(py)\n                .unwrap_or_else(PoisonError::into_inner);\n            let warnings = py.import(\"warnings\")?;\n            let kwargs = [(\"record\", true)].into_py_dict(py)?;\n            let catch_warnings = warnings\n                .getattr(\"catch_warnings\")?\n                .call((), Some(&kwargs))?;\n            let list = catch_warnings.call_method0(\"__enter__\")?.cast_into()?;\n            let _guard = Self { catch_warnings };\n            f(&list)\n        }\n    }\n\n    impl Drop for CatchWarnings<'_> {\n        fn drop(&mut self) {\n            let py = self.catch_warnings.py();\n            self.catch_warnings\n                .call_method1(\"__exit__\", (py.None(), py.None(), py.None()))\n                .unwrap();\n        }\n    }\n\n    macro_rules! assert_warnings {\n        ($py:expr, $body:expr, [$(($category:ty, $message:literal)),+] $(,)? ) => {{\n            $crate::test_utils::CatchWarnings::enter($py, |w| {\n                use $crate::types::{PyListMethods, PyStringMethods};\n                $body;\n                let expected_warnings = [$((<$category as $crate::type_object::PyTypeInfo>::type_object($py), $message)),+];\n                assert_eq!(w.len(), expected_warnings.len());\n                for (warning, (category, message)) in w.iter().zip(expected_warnings) {\n\n                    assert!(warning.getattr(\"category\").unwrap().is(&category));\n                    assert_eq!(\n                        warning.getattr(\"message\").unwrap().str().unwrap().to_string_lossy(),\n                        message\n                    );\n                }\n\n                Ok(())\n            })\n            .unwrap();\n        }};\n    }\n\n    #[allow(unused_imports, reason = \"not all tests use this macro\")]\n    pub(crate) use assert_warnings;\n\n    pub fn generate_unique_module_name(base: &str) -> std::ffi::CString {\n        let uuid = Uuid::new_v4().simple().to_string();\n        std::ffi::CString::new(format!(\"{base}_{uuid}\")).unwrap()\n    }\n}\n\n#[allow(unused_imports, reason = \"some integration tests use just the macros\")]\npub use inner::*;\n"
  },
  {
    "path": "tests/test_variable_arguments.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\nuse pyo3::types::{PyDict, PyTuple};\n\nmod test_utils;\n\n#[pyclass]\nstruct MyClass {}\n\n#[pymethods]\nimpl MyClass {\n    #[staticmethod]\n    #[pyo3(signature = (*args))]\n    fn test_args(args: Bound<'_, PyTuple>) -> Bound<'_, PyTuple> {\n        args\n    }\n\n    #[staticmethod]\n    #[pyo3(signature = (**kwargs))]\n    fn test_kwargs(kwargs: Option<Bound<'_, PyDict>>) -> Option<Bound<'_, PyDict>> {\n        kwargs\n    }\n}\n\n#[test]\nfn variable_args() {\n    Python::attach(|py| {\n        let my_obj = py.get_type::<MyClass>();\n        py_assert!(py, my_obj, \"my_obj.test_args() == ()\");\n        py_assert!(py, my_obj, \"my_obj.test_args(1) == (1,)\");\n        py_assert!(py, my_obj, \"my_obj.test_args(1, 2) == (1, 2)\");\n    });\n}\n\n#[test]\nfn variable_kwargs() {\n    Python::attach(|py| {\n        let my_obj = py.get_type::<MyClass>();\n        py_assert!(py, my_obj, \"my_obj.test_kwargs() == None\");\n        py_assert!(py, my_obj, \"my_obj.test_kwargs(test=1) == {'test': 1}\");\n        py_assert!(\n            py,\n            my_obj,\n            \"my_obj.test_kwargs(test1=1, test2=2) == {'test1':1, 'test2':2}\"\n        );\n    });\n}\n"
  },
  {
    "path": "tests/test_various.rs",
    "content": "#![cfg(feature = \"macros\")]\n\nuse pyo3::prelude::*;\nuse pyo3::py_run;\nuse pyo3::types::PyTuple;\n\nuse std::fmt;\n\nmod test_utils;\n\n#[pyclass]\nstruct MutRefArg {\n    n: i32,\n}\n\n#[pymethods]\nimpl MutRefArg {\n    fn get(&self) -> i32 {\n        self.n\n    }\n    fn set_other(&self, mut other: PyRefMut<'_, MutRefArg>) {\n        other.n = 100;\n    }\n}\n\n#[test]\nfn mut_ref_arg() {\n    Python::attach(|py| {\n        let inst1 = Py::new(py, MutRefArg { n: 0 }).unwrap();\n        let inst2 = Py::new(py, MutRefArg { n: 0 }).unwrap();\n\n        py_run!(py, inst1 inst2, \"inst1.set_other(inst2)\");\n        let inst2 = inst2.bind(py).borrow();\n        assert_eq!(inst2.n, 100);\n    });\n}\n\n#[pyclass]\nstruct PyUsize {\n    #[pyo3(get)]\n    pub value: usize,\n}\n\n#[pyfunction]\nfn get_zero() -> PyUsize {\n    PyUsize { value: 0 }\n}\n\n#[test]\n/// Checks that we can use return a custom class in arbitrary function and use those functions\n/// both in rust and python\nfn return_custom_class() {\n    Python::attach(|py| {\n        // Using from rust\n        assert_eq!(get_zero().value, 0);\n\n        // Using from python\n        let get_zero = wrap_pyfunction!(get_zero)(py).unwrap();\n        py_assert!(py, get_zero, \"get_zero().value == 0\");\n    });\n}\n\n#[test]\nfn intopytuple_primitive() {\n    Python::attach(|py| {\n        let tup = (1, 2, \"foo\");\n        py_assert!(py, tup, \"tup == (1, 2, 'foo')\");\n        py_assert!(py, tup, \"tup[0] == 1\");\n        py_assert!(py, tup, \"tup[1] == 2\");\n        py_assert!(py, tup, \"tup[2] == 'foo'\");\n    });\n}\n\n#[pyclass]\nstruct SimplePyClass {}\n\n#[test]\nfn intopytuple_pyclass() {\n    Python::attach(|py| {\n        let tup = (\n            Py::new(py, SimplePyClass {}).unwrap(),\n            Py::new(py, SimplePyClass {}).unwrap(),\n        );\n        py_assert!(py, tup, \"type(tup[0]).__name__ == 'SimplePyClass'\");\n        py_assert!(py, tup, \"type(tup[0]).__name__ == type(tup[1]).__name__\");\n        py_assert!(py, tup, \"tup[0] != tup[1]\");\n    });\n}\n\n#[test]\nfn pytuple_primitive_iter() {\n    Python::attach(|py| {\n        let tup = PyTuple::new(py, [1u32, 2, 3].iter()).unwrap();\n        py_assert!(py, tup, \"tup == (1, 2, 3)\");\n    });\n}\n\n#[test]\nfn pytuple_pyclass_iter() {\n    Python::attach(|py| {\n        let tup = PyTuple::new(\n            py,\n            [\n                Py::new(py, SimplePyClass {}).unwrap(),\n                Py::new(py, SimplePyClass {}).unwrap(),\n            ]\n            .iter(),\n        )\n        .unwrap();\n        py_assert!(py, tup, \"type(tup[0]).__name__ == 'SimplePyClass'\");\n        py_assert!(py, tup, \"type(tup[0]).__name__ == type(tup[0]).__name__\");\n        py_assert!(py, tup, \"tup[0] != tup[1]\");\n    });\n}\n\n#[test]\n#[cfg(any(Py_3_9, not(Py_LIMITED_API)))]\nfn test_pickle() {\n    use pyo3::types::PyDict;\n\n    #[pyclass(dict, module = \"test_module\")]\n    struct PickleSupport {}\n\n    #[pymethods]\n    impl PickleSupport {\n        #[new]\n        fn new() -> PickleSupport {\n            PickleSupport {}\n        }\n\n        pub fn __reduce__<'py>(\n            slf: &Bound<'py, Self>,\n            py: Python<'py>,\n        ) -> PyResult<(Bound<'py, PyAny>, Bound<'py, PyTuple>, Bound<'py, PyAny>)> {\n            let cls = slf.getattr(\"__class__\")?;\n            let dict = slf.getattr(\"__dict__\")?;\n            Ok((cls, PyTuple::empty(py), dict))\n        }\n    }\n\n    fn add_module(module: Bound<'_, PyModule>) -> PyResult<()> {\n        PyModule::import(module.py(), \"sys\")?\n            .dict()\n            .get_item(\"modules\")\n            .unwrap()\n            .unwrap()\n            .cast::<PyDict>()?\n            .set_item(module.name()?, module)\n    }\n\n    Python::attach(|py| {\n        let module = PyModule::new(py, \"test_module\").unwrap();\n        module.add_class::<PickleSupport>().unwrap();\n        add_module(module).unwrap();\n        let inst = Py::new(py, PickleSupport {}).unwrap();\n        py_run!(\n            py,\n            inst,\n            r#\"\n        inst.a = 1\n        assert inst.__dict__ == {'a': 1}\n\n        import pickle\n        inst2 = pickle.loads(pickle.dumps(inst))\n\n        assert inst2.__dict__ == {'a': 1}\n    \"#\n        );\n    });\n}\n\n/// Testing https://github.com/PyO3/pyo3/issues/1106. A result type that\n/// implements `From<MyError> for PyErr` should be automatically converted\n/// when using `#[pyfunction]`.\n///\n/// This only makes sure that valid `Result` types do work. For an invalid\n/// enum type, see `ui/invalid_result_conversion.py`.\n#[derive(Debug)]\nstruct MyError {\n    pub descr: &'static str,\n}\n\nimpl fmt::Display for MyError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"My error message: {}\", self.descr)\n    }\n}\n\n/// Important for the automatic conversion to `PyErr`.\nimpl From<MyError> for PyErr {\n    fn from(err: MyError) -> pyo3::PyErr {\n        pyo3::exceptions::PyOSError::new_err(err.to_string())\n    }\n}\n\n#[pyfunction]\nfn result_conversion_function() -> Result<(), MyError> {\n    Err(MyError {\n        descr: \"something went wrong\",\n    })\n}\n\n#[test]\nfn test_result_conversion() {\n    Python::attach(|py| {\n        wrap_pyfunction!(result_conversion_function)(py).unwrap();\n    });\n}\n"
  },
  {
    "path": "tests/ui/abi3_dict.rs",
    "content": "//! With abi3, dict not supported until python 3.9 or greater\nuse pyo3::prelude::*;\n\n#[pyclass(dict)]\nstruct TestClass {}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/abi3_dict.stderr",
    "content": "error[E0080]: evaluation panicked: `dict` requires Python >= 3.9 when using the `abi3` feature\n --> tests/ui/abi3_dict.rs:4:11\n  |\n4 | #[pyclass(dict)]\n  |           ^^^^ evaluation of `_::ASSERT_DICT_SUPPORTED` failed here\n  |\n  = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "tests/ui/abi3_inheritance.rs",
    "content": "use pyo3::exceptions::PyException;\nuse pyo3::prelude::*;\n\n#[pyclass(extends=PyException)]\n#[derive(Clone)]\nstruct MyException {\n    code: u32,\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/abi3_inheritance.stderr",
    "content": "error[E0277]: pyclass `PyException` cannot be subclassed\n --> tests/ui/abi3_inheritance.rs:4:1\n  |\n4 | #[pyclass(extends=PyException)]\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required for `#[pyclass(extends=PyException)]`\n  |\n  = help: the trait `PyClassBaseType` is not implemented for `PyException`\n  = note: `PyException` must have `#[pyclass(subclass)]` to be eligible for subclassing\n  = note: with the `abi3` feature enabled, PyO3 does not support subclassing native types\nhelp: the trait `PyClassBaseType` is implemented for `PyAny`\n --> src/types/any.rs\n  |\n  | impl crate::impl_::pyclass::PyClassBaseType for PyAny {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: pyclass `PyException` cannot be subclassed\n --> tests/ui/abi3_inheritance.rs:4:19\n  |\n4 | #[pyclass(extends=PyException)]\n  |                   ^^^^^^^^^^^ required for `#[pyclass(extends=PyException)]`\n  |\n  = help: the trait `PyClassBaseType` is not implemented for `PyException`\n  = note: `PyException` must have `#[pyclass(subclass)]` to be eligible for subclassing\n  = note: with the `abi3` feature enabled, PyO3 does not support subclassing native types\nhelp: the trait `PyClassBaseType` is implemented for `PyAny`\n --> src/types/any.rs\n  |\n  | impl crate::impl_::pyclass::PyClassBaseType for PyAny {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nnote: required by a bound in `PyClassImpl::BaseType`\n --> src/impl_/pyclass.rs\n  |\n  |     type BaseType: PyTypeInfo + PyClassBaseType;\n  |                                 ^^^^^^^^^^^^^^^ required by this bound in `PyClassImpl::BaseType`\n\nwarning: use of deprecated associated constant `pyo3::impl_::deprecated::HasAutomaticFromPyObject::<true>::MSG`: The `FromPyObject` implementation for `#[pyclass]` types which implement `Clone` is changing to an opt-in option. Use `#[pyclass(from_py_object)]` to opt-in to the `FromPyObject` derive now, or `#[pyclass(skip_from_py_object)]` to skip the `FromPyObject` implementation.\n --> tests/ui/abi3_inheritance.rs:4:1\n  |\n4 | #[pyclass(extends=PyException)]\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = note: `#[warn(deprecated)]` on by default\n  = note: this warning originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "tests/ui/abi3_nativetype_inheritance.rs",
    "content": "//! With abi3, we cannot inherit native types.\nuse pyo3::prelude::*;\nuse pyo3::types::PyDict;\n\n#[pyclass(extends=PyDict)]\nstruct TestClass {}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/abi3_nativetype_inheritance.stderr",
    "content": "error[E0277]: pyclass `PyDict` cannot be subclassed\n --> tests/ui/abi3_nativetype_inheritance.rs:5:1\n  |\n5 | #[pyclass(extends=PyDict)]\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required for `#[pyclass(extends=PyDict)]`\n  |\n  = help: the trait `PyClassBaseType` is not implemented for `PyDict`\n  = note: `PyDict` must have `#[pyclass(subclass)]` to be eligible for subclassing\n  = note: with the `abi3` feature enabled, PyO3 does not support subclassing native types\nhelp: the trait `PyClassBaseType` is implemented for `PyAny`\n --> src/types/any.rs\n  |\n  | impl crate::impl_::pyclass::PyClassBaseType for PyAny {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: pyclass `PyDict` cannot be subclassed\n --> tests/ui/abi3_nativetype_inheritance.rs:5:19\n  |\n5 | #[pyclass(extends=PyDict)]\n  |                   ^^^^^^ required for `#[pyclass(extends=PyDict)]`\n  |\n  = help: the trait `PyClassBaseType` is not implemented for `PyDict`\n  = note: `PyDict` must have `#[pyclass(subclass)]` to be eligible for subclassing\n  = note: with the `abi3` feature enabled, PyO3 does not support subclassing native types\nhelp: the trait `PyClassBaseType` is implemented for `PyAny`\n --> src/types/any.rs\n  |\n  | impl crate::impl_::pyclass::PyClassBaseType for PyAny {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nnote: required by a bound in `PyClassImpl::BaseType`\n --> src/impl_/pyclass.rs\n  |\n  |     type BaseType: PyTypeInfo + PyClassBaseType;\n  |                                 ^^^^^^^^^^^^^^^ required by this bound in `PyClassImpl::BaseType`\n"
  },
  {
    "path": "tests/ui/abi3_weakref.rs",
    "content": "//! With abi3, weakref not supported until python 3.9 or greater\nuse pyo3::prelude::*;\n\n#[pyclass(weakref)]\nstruct TestClass {}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/abi3_weakref.stderr",
    "content": "error[E0080]: evaluation panicked: `weakref` requires Python >= 3.9 when using the `abi3` feature\n --> tests/ui/abi3_weakref.rs:4:11\n  |\n4 | #[pyclass(weakref)]\n  |           ^^^^^^^ evaluation of `_::ASSERT_WEAKREF_SUPPORTED` failed here\n  |\n  = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "tests/ui/ambiguous_associated_items.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass(eq)]\n#[derive(PartialEq)]\npub enum SimpleItems {\n    Error,\n    Output,\n    Target,\n}\n\n#[pyclass]\npub enum ComplexItems {\n    Error(Py<PyAny>),\n    Output(Py<PyAny>),\n    Target(Py<PyAny>),\n}\n\n#[derive(IntoPyObject)]\nenum DeriveItems {\n    Error(Py<PyAny>),\n    Output(Py<PyAny>),\n    Target(Py<PyAny>),\n}\n\n#[pyclass(from_py_object)]\n#[derive(Clone)]\npub enum SimpleItemsFromPyObject {\n    Error,\n    Output,\n    Target,\n}\n\n#[pyclass(from_py_object)]\n#[derive(Clone)]\npub enum ComplexItemsFromPyObject {\n    Error(i32),\n    Output(i32),\n    Target(i32),\n}\n\n#[derive(FromPyObject, Clone)]\nenum DeriveItemsFromPyObject {\n    Error(i32),\n    Output(i32),\n    Target(i32),\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/deprecated_pyfn.rs",
    "content": "#![deny(deprecated)]\n\nuse pyo3::prelude::*;\n\n#[pymodule]\nfn module_with_pyfn(m: &Bound<'_, PyModule>) -> PyResult<()> {\n    #[pyfn(m)]\n    fn foo() {}\n\n    Ok(())\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/deprecated_pyfn.stderr",
    "content": "error: use of deprecated constant `module_with_pyfn::PYFN_ATTRIBUTE`: `pyfn` will be removed in a future PyO3 version, use declarative `#[pymodule]` with `mod` instead\n --> tests/ui/deprecated_pyfn.rs:7:7\n  |\n7 |     #[pyfn(m)]\n  |       ^^^^\n  |\nnote: the lint level is defined here\n --> tests/ui/deprecated_pyfn.rs:1:9\n  |\n1 | #![deny(deprecated)]\n  |         ^^^^^^^^^^\n"
  },
  {
    "path": "tests/ui/duplicate_pymodule_submodule.rs",
    "content": "#[pyo3::pymodule]\nmod mymodule {\n\t#[pyo3::pymodule(submodule)]\n\tmod submod {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/duplicate_pymodule_submodule.stderr",
    "content": "error: `submodule` may only be specified once (it is implicitly always specified for nested modules)\n --> tests/ui/duplicate_pymodule_submodule.rs:4:2\n  |\n4 |     mod submod {}\n  |     ^^^\n\nerror[E0425]: cannot find value `_PYO3_DEF` in module `submod`\n --> tests/ui/duplicate_pymodule_submodule.rs:1:1\n  |\n1 | #[pyo3::pymodule]\n  | ^^^^^^^^^^^^^^^^^ not found in `submod`\n  |\n  = note: this error originates in the attribute macro `pyo3::pymodule` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider importing this static\n  |\n3 +     use crate::mymodule::_PYO3_DEF;\n  |\n"
  },
  {
    "path": "tests/ui/empty.rs",
    "content": "// see invalid_pymodule_in_root.rs\n"
  },
  {
    "path": "tests/ui/forbid_unsafe.rs",
    "content": "#![forbid(unsafe_code)]\n#![forbid(unsafe_op_in_unsafe_fn)]\n\nuse pyo3::*;\n\n#[expect(unexpected_cfgs)]\n#[path = \"../../src/tests/hygiene/mod.rs\"]\nmod hygiene;\n\nmod gh_4394 {\n    use pyo3::prelude::*;\n\n    #[derive(Eq, Ord, PartialEq, PartialOrd, Clone)]\n    #[pyclass(get_all, skip_from_py_object)]\n    pub struct VersionSpecifier {\n        pub(crate) operator: Operator,\n        pub(crate) version: Version,\n    }\n\n    #[derive(Eq, Ord, PartialEq, PartialOrd, Debug, Hash, Clone, Copy)]\n    #[pyo3::pyclass(eq, eq_int, skip_from_py_object)]\n    pub enum Operator {\n        Equal,\n    }\n\n    #[derive(Clone, Eq, PartialEq, PartialOrd, Ord)]\n    #[pyclass(skip_from_py_object)]\n    pub struct Version;\n}\n\nmod from_py_with {\n    use pyo3::prelude::*;\n    use pyo3::types::PyBytes;\n\n    fn bytes_from_py(bytes: &Bound<'_, PyAny>) -> PyResult<Vec<u8>> {\n        Ok(bytes.cast::<PyBytes>()?.as_bytes().to_vec())\n    }\n\n    #[pyfunction]\n    fn f(#[pyo3(from_py_with = bytes_from_py)] _bytes: Vec<u8>) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/get_set_all.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass(set_all)]\nstruct Foo;\n\n#[pyclass(set_all)]\nstruct Foo2{\n    #[pyo3(set)]\n    field: u8,\n}\n\n#[pyclass(get_all)]\nstruct Foo3;\n\n#[pyclass(get_all)]\nstruct Foo4{\n    #[pyo3(get)]\n    field: u8,\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/get_set_all.stderr",
    "content": "error: `set_all` on an unit struct does nothing, because unit structs have no fields\n --> tests/ui/get_set_all.rs:3:11\n  |\n3 | #[pyclass(set_all)]\n  |           ^^^^^^^\n\nerror: useless `set` - the struct is already annotated with `set_all`\n --> tests/ui/get_set_all.rs:8:12\n  |\n8 |     #[pyo3(set)]\n  |            ^^^\n\nerror: `get_all` on an unit struct does nothing, because unit structs have no fields\n  --> tests/ui/get_set_all.rs:12:11\n   |\n12 | #[pyclass(get_all)]\n   |           ^^^^^^^\n\nerror: useless `get` - the struct is already annotated with `get_all`\n  --> tests/ui/get_set_all.rs:17:12\n   |\n17 |     #[pyo3(get)]\n   |            ^^^\n"
  },
  {
    "path": "tests/ui/immutable_type.rs",
    "content": "use pyo3::prelude::*;\r\n\r\n#[pyclass(immutable_type)]\r\nstruct ImmutableType {}\r\n\r\nfn main() {}\r\n"
  },
  {
    "path": "tests/ui/immutable_type.stderr",
    "content": "error[E0080]: evaluation panicked: `immutable_type` requires Python >= 3.10 (or >= 3.14 when using the `abi3` feature)\n --> tests/ui/immutable_type.rs:3:11\n  |\n3 | #[pyclass(immutable_type)]\n  |           ^^^^^^^^^^^^^^ evaluation of `_::ASSERT_IMMUTABLE_SUPPORTED` failed here\n  |\n  = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "tests/ui/invalid_annotation.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyfunction]\n#[pyo3(signature = (a: \"int\"))]\nfn check(a: usize) -> usize {\n    a\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_annotation.stderr",
    "content": "error: Type annotations in the signature is only supported with the `experimental-inspect` feature\n --> tests/ui/invalid_annotation.rs:4:24\n  |\n4 | #[pyo3(signature = (a: \"int\"))]\n  |                        ^^^^^\n"
  },
  {
    "path": "tests/ui/invalid_annotation_return.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyfunction]\n#[pyo3(signature = (a) -> \"int\")]\nfn check(a: usize) -> usize {\n    a\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_annotation_return.stderr",
    "content": "error: Return type annotation in the signature is only supported with the `experimental-inspect` feature\n --> tests/ui/invalid_annotation_return.rs:4:27\n  |\n4 | #[pyo3(signature = (a) -> \"int\")]\n  |                           ^^^^^\n"
  },
  {
    "path": "tests/ui/invalid_argument_attributes.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyfunction]\nfn invalid_attribute(#[pyo3(get)] _param: String) {}\n\n#[pyfunction]\nfn from_py_with_no_value(#[pyo3(from_py_with)] _param: String) {}\n\n#[pyfunction]\nfn from_py_with_string(#[pyo3(\"from_py_with\")] _param: String) {}\n\n#[pyfunction]\nfn from_py_with_value_not_found(#[pyo3(from_py_with = func)] _param: String) {}\n\n#[pyfunction]\nfn from_py_with_repeated(#[pyo3(from_py_with = func, from_py_with = func)] _param: String) {}\n\nfn bytes_from_py(bytes: &Bound<'_, pyo3::types::PyBytes>) -> Vec<u8> {\n    bytes.as_bytes().to_vec()\n}\n\n#[pyfunction]\nfn f(#[pyo3(from_py_with = \"bytes_from_py\")] _bytes: Vec<u8>) {}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_argument_attributes.stderr",
    "content": "error: expected `cancel_handle` or `from_py_with`\n --> tests/ui/invalid_argument_attributes.rs:4:29\n  |\n4 | fn invalid_attribute(#[pyo3(get)] _param: String) {}\n  |                             ^^^\n\nerror: expected `=`\n --> tests/ui/invalid_argument_attributes.rs:7:45\n  |\n7 | fn from_py_with_no_value(#[pyo3(from_py_with)] _param: String) {}\n  |                                             ^\n\nerror: expected `cancel_handle` or `from_py_with`\n  --> tests/ui/invalid_argument_attributes.rs:10:31\n   |\n10 | fn from_py_with_string(#[pyo3(\"from_py_with\")] _param: String) {}\n   |                               ^^^^^^^^^^^^^^\n\nerror: `from_py_with` may only be specified once per argument\n  --> tests/ui/invalid_argument_attributes.rs:16:54\n   |\n16 | fn from_py_with_repeated(#[pyo3(from_py_with = func, from_py_with = func)] _param: String) {}\n   |                                                      ^^^^^^^^^^^^\n\nerror: expected identifier\n  --> tests/ui/invalid_argument_attributes.rs:23:28\n   |\n23 | fn f(#[pyo3(from_py_with = \"bytes_from_py\")] _bytes: Vec<u8>) {}\n   |                            ^^^^^^^^^^^^^^^\n\nerror[E0425]: cannot find value `func` in this scope\n  --> tests/ui/invalid_argument_attributes.rs:13:55\n   |\n13 | fn from_py_with_value_not_found(#[pyo3(from_py_with = func)] _param: String) {}\n   |                                                       ^^^^ not found in this scope\n"
  },
  {
    "path": "tests/ui/invalid_async.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyfunction]\nasync fn check(){}\n\n#[pyclass]\npub(crate) struct AsyncRange {\n    count: i32,\n    target: i32,\n}\n#[pymethods]\nimpl AsyncRange {\n    async fn __anext__(mut _pyself: PyRefMut<'_, Self>) -> PyResult<i32> {\n        Ok(0)\n    }\n\n    async fn foo(&self) {}\n}\n\nfn main() {}"
  },
  {
    "path": "tests/ui/invalid_async.stderr",
    "content": "error: async functions are only supported with the `experimental-async` feature\n --> tests/ui/invalid_async.rs:4:1\n  |\n4 | async fn check(){}\n  | ^^^^^\n\nerror: async functions are only supported with the `experimental-async` feature\n  --> tests/ui/invalid_async.rs:13:5\n   |\n13 |     async fn __anext__(mut _pyself: PyRefMut<'_, Self>) -> PyResult<i32> {\n   |     ^^^^^\n\nerror: async functions are only supported with the `experimental-async` feature\n  --> tests/ui/invalid_async.rs:17:5\n   |\n17 |     async fn foo(&self) {}\n   |     ^^^^^\n"
  },
  {
    "path": "tests/ui/invalid_base_class.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::PyBool;\n\n#[pyclass(extends=PyBool)]\nstruct ExtendsBool;\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_base_class.stderr",
    "content": "error[E0277]: pyclass `PyBool` cannot be subclassed\n --> tests/ui/invalid_base_class.rs:4:1\n  |\n4 | #[pyclass(extends=PyBool)]\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required for `#[pyclass(extends=PyBool)]`\n  |\n  = help: the trait `PyClassBaseType` is not implemented for `PyBool`\n  = note: `PyBool` must have `#[pyclass(subclass)]` to be eligible for subclassing\n  = help: the following other types implement trait `PyClassBaseType`:\n            PyAny\n            PyArithmeticError\n            PyAssertionError\n            PyAttributeError\n            PyBaseException\n            PyBaseExceptionGroup\n            PyBlockingIOError\n            PyBrokenPipeError\n          and $N others\n  = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: pyclass `PyBool` cannot be subclassed\n --> tests/ui/invalid_base_class.rs:4:19\n  |\n4 | #[pyclass(extends=PyBool)]\n  |                   ^^^^^^ required for `#[pyclass(extends=PyBool)]`\n  |\n  = help: the trait `PyClassBaseType` is not implemented for `PyBool`\n  = note: `PyBool` must have `#[pyclass(subclass)]` to be eligible for subclassing\n  = help: the following other types implement trait `PyClassBaseType`:\n            PyAny\n            PyArithmeticError\n            PyAssertionError\n            PyAttributeError\n            PyBaseException\n            PyBaseExceptionGroup\n            PyBlockingIOError\n            PyBrokenPipeError\n          and $N others\nnote: required by a bound in `PyClassImpl::BaseType`\n --> src/impl_/pyclass.rs\n  |\n  |     type BaseType: PyTypeInfo + PyClassBaseType;\n  |                                 ^^^^^^^^^^^^^^^ required by this bound in `PyClassImpl::BaseType`\n"
  },
  {
    "path": "tests/ui/invalid_cancel_handle.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyfunction]\nasync fn cancel_handle_repeated(#[pyo3(cancel_handle, cancel_handle)] _param: String) {}\n\n#[pyfunction]\nasync fn cancel_handle_repeated2(\n    #[pyo3(cancel_handle)] _param: String,\n    #[pyo3(cancel_handle)] _param2: String,\n) {\n}\n\n#[pyfunction]\nfn cancel_handle_synchronous(#[pyo3(cancel_handle)] _param: String) {}\n\n#[pyfunction]\nasync fn cancel_handle_wrong_type(#[pyo3(cancel_handle)] _param: String) {}\n\n#[pyfunction]\nasync fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {}\n\n#[pyfunction]\nasync fn cancel_handle_and_from_py_with(\n    #[pyo3(cancel_handle, from_py_with = cancel_handle)] _param: pyo3::coroutine::CancelHandle,\n) {\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_cancel_handle.stderr",
    "content": "error: `cancel_handle` may only be specified once per argument\n --> tests/ui/invalid_cancel_handle.rs:4:55\n  |\n4 | async fn cancel_handle_repeated(#[pyo3(cancel_handle, cancel_handle)] _param: String) {}\n  |                                                       ^^^^^^^^^^^^^\n\nerror: `cancel_handle` may only be specified once\n --> tests/ui/invalid_cancel_handle.rs:9:28\n  |\n9 |     #[pyo3(cancel_handle)] _param2: String,\n  |                            ^^^^^^^\n\nerror: `cancel_handle` attribute can only be used with `async fn`\n  --> tests/ui/invalid_cancel_handle.rs:14:53\n   |\n14 | fn cancel_handle_synchronous(#[pyo3(cancel_handle)] _param: String) {}\n   |                                                     ^^^^^^\n\nerror: `from_py_with` and `cancel_handle` cannot be specified together\n  --> tests/ui/invalid_cancel_handle.rs:24:12\n   |\n24 |     #[pyo3(cancel_handle, from_py_with = cancel_handle)] _param: pyo3::coroutine::CancelHandle,\n   |            ^^^^^^^^^^^^^\n\nerror[E0308]: mismatched types\n  --> tests/ui/invalid_cancel_handle.rs:16:1\n   |\n16 | #[pyfunction]\n   | ^^^^^^^^^^^^^\n   | |\n   | expected `String`, found `CancelHandle`\n   | arguments to this function are incorrect\n   |\nnote: function defined here\n  --> tests/ui/invalid_cancel_handle.rs:17:10\n   |\n17 | async fn cancel_handle_wrong_type(#[pyo3(cancel_handle)] _param: String) {}\n   |          ^^^^^^^^^^^^^^^^^^^^^^^^                        --------------\n   = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: `CancelHandle` cannot be used as a Python function argument\n  --> tests/ui/invalid_cancel_handle.rs:20:50\n   |\n20 | async fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {}\n   |                                                  ^^^^ the trait `PyClass` is not implemented for `CancelHandle`\n   |\n   = note: implement `FromPyObject` to enable using `CancelHandle` as a function argument\n   = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]`\n   = help: the trait `PyClass` is implemented for `pyo3::coroutine::Coroutine`\n   = note: required for `CancelHandle` to implement `FromPyObject<'_, '_>`\n   = note: required for `CancelHandle` to implement `PyFunctionArgument<'_, '_, '_, true>`\nnote: required by a bound in `extract_argument`\n  --> src/impl_/extract_argument.rs\n   |\n   | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>(\n   |        ---------------- required by a bound in this function\n...\n   |     T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>,\n   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument`\n\nerror[E0277]: `CancelHandle` cannot be used as a Python function argument\n  --> tests/ui/invalid_cancel_handle.rs:20:50\n   |\n20 | async fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {}\n   |                                                  ^^^^ the trait `Clone` is not implemented for `CancelHandle`\n   |\n   = note: implement `FromPyObject` to enable using `CancelHandle` as a function argument\n   = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]`\n   = help: the following other types implement trait `PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>`:\n             `&'a pyo3::Bound<'py, T>` implements `PyFunctionArgument<'a, '_, 'py, false>`\n             `&'holder T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n             `&'holder mut T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n             `Option<T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n   = note: required for `CancelHandle` to implement `FromPyObject<'_, '_>`\n   = note: required for `CancelHandle` to implement `PyFunctionArgument<'_, '_, '_, true>`\nnote: required by a bound in `extract_argument`\n  --> src/impl_/extract_argument.rs\n   |\n   | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>(\n   |        ---------------- required by a bound in this function\n...\n   |     T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>,\n   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument`\n\nerror[E0277]: `CancelHandle` cannot be used as a Python function argument\n  --> tests/ui/invalid_cancel_handle.rs:20:50\n   |\n20 | async fn missing_cancel_handle_attribute(_param: pyo3::coroutine::CancelHandle) {}\n   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `PyFunctionArgument<'_, '_, '_, false>` is not implemented for `CancelHandle`\n   |\n   = note: implement `FromPyObject` to enable using `CancelHandle` as a function argument\n   = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]`\n   = help: the following other types implement trait `PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>`:\n             `&'a pyo3::Bound<'py, T>` implements `PyFunctionArgument<'a, '_, 'py, false>`\n             `&'holder T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n             `&'holder mut T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n             `Option<T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n"
  },
  {
    "path": "tests/ui/invalid_closure.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::{PyCFunction, PyDict, PyTuple};\n\nfn main() {\n    let fun: Py<PyCFunction> = Python::attach(|py| {\n        let local_data = vec![0, 1, 2, 3, 4];\n        let ref_: &[u8] = &local_data;\n\n        let closure_fn =\n            |_args: &Bound<'_, PyTuple>, _kwargs: Option<&Bound<'_, PyDict>>| -> PyResult<()> {\n                println!(\"This is five: {:?}\", ref_.len());\n                Ok(())\n            };\n        PyCFunction::new_closure(py, None, None, closure_fn)\n            .unwrap()\n            .into()\n    });\n\n    Python::attach(|py| {\n        fun.call0(py).unwrap();\n    });\n}\n"
  },
  {
    "path": "tests/ui/invalid_closure.stderr",
    "content": "error[E0597]: `local_data` does not live long enough\n  --> tests/ui/invalid_closure.rs:7:27\n   |\n 6 |         let local_data = vec![0, 1, 2, 3, 4];\n   |             ---------- binding `local_data` declared here\n 7 |         let ref_: &[u8] = &local_data;\n   |                           ^^^^^^^^^^^ borrowed value does not live long enough\n...\n14 |         PyCFunction::new_closure(py, None, None, closure_fn)\n   |         ---------------------------------------------------- argument requires that `local_data` is borrowed for `'static`\n...\n17 |     });\n   |     - `local_data` dropped here while still borrowed\n   |\nnote: requirement that the value outlives `'static` introduced here\n  --> src/types/function.rs\n   |\n   |         F: Fn(&Bound<'_, PyTuple>, Option<&Bound<'_, PyDict>>) -> R + Send + 'static,\n   |                                                                              ^^^^^^^\n"
  },
  {
    "path": "tests/ui/invalid_frompy_derive.rs",
    "content": "use pyo3::FromPyObject;\n\n#[derive(FromPyObject)]\nstruct Foo();\n\n#[derive(FromPyObject)]\nstruct Foo2 {}\n\n#[derive(FromPyObject)]\nenum EmptyEnum {}\n\n#[derive(FromPyObject)]\nenum EnumWithEmptyTupleVar {\n    EmptyTuple(),\n    Valid(String),\n}\n\n#[derive(FromPyObject)]\nenum EnumWithEmptyStructVar {\n    EmptyStruct {},\n    Valid(String),\n}\n\n#[derive(FromPyObject)]\n#[pyo3(transparent)]\nstruct EmptyTransparentTup();\n\n#[derive(FromPyObject)]\n#[pyo3(transparent)]\nstruct EmptyTransparentStruct {}\n\n#[derive(FromPyObject)]\nenum EnumWithTransparentEmptyTupleVar {\n    #[pyo3(transparent)]\n    EmptyTuple(),\n    Valid(String),\n}\n\n#[derive(FromPyObject)]\nenum EnumWithTransparentEmptyStructVar {\n    #[pyo3(transparent)]\n    EmptyStruct {},\n    Valid(String),\n}\n\n#[derive(FromPyObject)]\n#[pyo3(transparent)]\nstruct TransparentTupTooManyFields(String, String);\n\n#[derive(FromPyObject)]\n#[pyo3(transparent)]\nstruct TransparentStructTooManyFields {\n    foo: String,\n    bar: String,\n}\n\n#[derive(FromPyObject)]\nenum EnumWithTransparentTupleTooMany {\n    #[pyo3(transparent)]\n    EmptyTuple(String, String),\n    Valid(String),\n}\n\n#[derive(FromPyObject)]\nenum EnumWithTransparentStructTooMany {\n    #[pyo3(transparent)]\n    EmptyStruct {\n        foo: String,\n        bar: String,\n    },\n    Valid(String),\n}\n\n#[derive(FromPyObject)]\nstruct UnknownAttribute {\n    #[pyo3(attr)]\n    a: String,\n}\n\n#[derive(FromPyObject)]\nstruct InvalidAttributeArg {\n    #[pyo3(attribute(1))]\n    a: String,\n}\n\n#[derive(FromPyObject)]\nstruct TooManyAttributeArgs {\n    #[pyo3(attribute(\"a\", \"b\"))]\n    a: String,\n}\n\n#[derive(FromPyObject)]\nstruct EmptyAttributeArg {\n    #[pyo3(attribute(\"\"))]\n    a: String,\n}\n\n#[derive(FromPyObject)]\nstruct NoAttributeArg {\n    #[pyo3(attribute())]\n    a: String,\n}\n\n#[derive(FromPyObject)]\nstruct TooManyitemArgs {\n    #[pyo3(item(\"a\", \"b\"))]\n    a: String,\n}\n\n#[derive(FromPyObject)]\nstruct NoItemArg {\n    #[pyo3(item())]\n    a: String,\n}\n\n#[derive(FromPyObject)]\nstruct ItemAndAttribute {\n    #[pyo3(item, attribute)]\n    a: String,\n}\n\n#[derive(FromPyObject)]\n#[pyo3(unknown = \"should not work\")]\nstruct UnknownContainerAttr {\n    a: String,\n}\n\n#[derive(FromPyObject)]\n#[pyo3(annotation = \"should not work\")]\nstruct AnnotationOnStruct {\n    a: String,\n}\n\n#[derive(FromPyObject)]\nenum InvalidAnnotatedEnum {\n    #[pyo3(annotation = 1)]\n    Foo(String),\n}\n\n#[derive(FromPyObject)]\nenum TooManyLifetimes<'a, 'b> {\n    Foo(&'a str),\n    Bar(&'b str),\n}\n\n#[derive(FromPyObject)]\nunion Union {\n    a: usize,\n}\n\n#[derive(FromPyObject)]\nenum UnitEnum {\n    Unit,\n}\n\n#[derive(FromPyObject)]\nstruct InvalidFromPyWith {\n    #[pyo3(from_py_with)]\n    field: String,\n}\n\n#[derive(FromPyObject)]\nstruct InvalidFromPyWithNotFound {\n    #[pyo3(from_py_with = func)]\n    field: String,\n}\n\n#[derive(FromPyObject)]\nstruct InvalidTupleGetter(#[pyo3(item(\"foo\"))] String);\n\n#[derive(FromPyObject)]\n#[pyo3(transparent)]\nstruct InvalidTransparentWithGetter {\n    #[pyo3(item(\"foo\"))]\n    field: String,\n}\n\n#[derive(FromPyObject)]\n#[pyo3(from_item_all)]\nstruct FromItemAllOnTuple(String);\n\n#[derive(FromPyObject)]\n#[pyo3(from_item_all)]\n#[pyo3(transparent)]\nstruct FromItemAllWithTransparent {\n    field: String,\n}\n\n#[derive(FromPyObject)]\n#[pyo3(from_item_all, from_item_all)]\nstruct MultipleFromItemAll {\n    field: String,\n}\n\n#[derive(FromPyObject)]\n#[pyo3(from_item_all)]\nstruct UselessItemAttr {\n    #[pyo3(item)]\n    field: String,\n}\n\n#[derive(FromPyObject)]\n#[pyo3(from_item_all)]\nstruct FromItemAllConflictAttr {\n    #[pyo3(attribute)]\n    field: String,\n}\n\n#[derive(FromPyObject)]\n#[pyo3(from_item_all)]\nstruct FromItemAllConflictAttrWithArgs {\n    #[pyo3(attribute(\"f\"))]\n    field: String,\n}\n\n#[derive(FromPyObject)]\nstruct StructWithOnlyDefaultValues {\n    #[pyo3(default)]\n    field: String,\n}\n\n#[derive(FromPyObject)]\nenum EnumVariantWithOnlyDefaultValues {\n    Foo {\n        #[pyo3(default)]\n        field: String,\n    },\n}\n\n#[derive(FromPyObject)]\nstruct NamedTuplesWithDefaultValues(#[pyo3(default)] String);\n\n#[derive(FromPyObject)]\n#[pyo3(rename_all = \"camelCase\", rename_all = \"kebab-case\")]\nstruct MultipleRenames {\n    snake_case: String,\n}\n\n#[derive(FromPyObject)]\n#[pyo3(rename_all = \"camelCase\")]\nstruct RenameAllTuple(String);\n\n#[derive(FromPyObject)]\nenum RenameAllEnum {\n    #[pyo3(rename_all = \"camelCase\")]\n    Tuple(String),\n}\n\n#[derive(FromPyObject)]\n#[pyo3(transparent, rename_all = \"camelCase\")]\nstruct RenameAllTransparent {\n    inner: String,\n}\n\n#[derive(FromPyObject)]\n#[pyo3(rename_all = \"camelCase\")]\nenum UselessRenameAllEnum {\n    #[pyo3(rename_all = \"camelCase\")]\n    Tuple { inner_field: String },\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_frompy_derive.stderr",
    "content": "error: cannot derive FromPyObject for empty structs and variants\n --> tests/ui/invalid_frompy_derive.rs:4:11\n  |\n4 | struct Foo();\n  |           ^^\n\nerror: cannot derive FromPyObject for empty structs and variants\n --> tests/ui/invalid_frompy_derive.rs:7:13\n  |\n7 | struct Foo2 {}\n  |             ^^\n\nerror: cannot derive FromPyObject for empty enum\n  --> tests/ui/invalid_frompy_derive.rs:10:6\n   |\n10 | enum EmptyEnum {}\n   |      ^^^^^^^^^\n\nerror: cannot derive FromPyObject for empty structs and variants\n  --> tests/ui/invalid_frompy_derive.rs:14:15\n   |\n14 |     EmptyTuple(),\n   |               ^^\n\nerror: cannot derive FromPyObject for empty structs and variants\n  --> tests/ui/invalid_frompy_derive.rs:20:17\n   |\n20 |     EmptyStruct {},\n   |                 ^^\n\nerror: cannot derive FromPyObject for empty structs and variants\n  --> tests/ui/invalid_frompy_derive.rs:26:27\n   |\n26 | struct EmptyTransparentTup();\n   |                           ^^\n\nerror: cannot derive FromPyObject for empty structs and variants\n  --> tests/ui/invalid_frompy_derive.rs:30:31\n   |\n30 | struct EmptyTransparentStruct {}\n   |                               ^^\n\nerror: cannot derive FromPyObject for empty structs and variants\n  --> tests/ui/invalid_frompy_derive.rs:35:15\n   |\n35 |     EmptyTuple(),\n   |               ^^\n\nerror: cannot derive FromPyObject for empty structs and variants\n  --> tests/ui/invalid_frompy_derive.rs:42:17\n   |\n42 |     EmptyStruct {},\n   |                 ^^\n\nerror: transparent structs and variants can only have 1 field\n  --> tests/ui/invalid_frompy_derive.rs:48:35\n   |\n48 | struct TransparentTupTooManyFields(String, String);\n   |                                   ^^^^^^^^^^^^^^^^\n\nerror: transparent structs and variants can only have 1 field\n  --> tests/ui/invalid_frompy_derive.rs:52:39\n   |\n52 |   struct TransparentStructTooManyFields {\n   |  _______________________________________^\n53 | |     foo: String,\n54 | |     bar: String,\n55 | | }\n   | |_^\n\nerror: transparent structs and variants can only have 1 field\n  --> tests/ui/invalid_frompy_derive.rs:60:15\n   |\n60 |     EmptyTuple(String, String),\n   |               ^^^^^^^^^^^^^^^^\n\nerror: transparent structs and variants can only have 1 field\n  --> tests/ui/invalid_frompy_derive.rs:67:17\n   |\n67 |       EmptyStruct {\n   |  _________________^\n68 | |         foo: String,\n69 | |         bar: String,\n70 | |     },\n   | |_____^\n\nerror: expected one of: `attribute`, `item`, `from_py_with`, `into_py_with`, `default`\n  --> tests/ui/invalid_frompy_derive.rs:76:12\n   |\n76 |     #[pyo3(attr)]\n   |            ^^^^\n\nerror: expected string literal\n  --> tests/ui/invalid_frompy_derive.rs:82:22\n   |\n82 |     #[pyo3(attribute(1))]\n   |                      ^\n\nerror: expected at most one argument: `attribute` or `attribute(\"name\")`\n  --> tests/ui/invalid_frompy_derive.rs:88:25\n   |\n88 |     #[pyo3(attribute(\"a\", \"b\"))]\n   |                         ^\n\nerror: attribute name cannot be empty\n  --> tests/ui/invalid_frompy_derive.rs:94:22\n   |\n94 |     #[pyo3(attribute(\"\"))]\n   |                      ^^\n\nerror: unexpected end of input, expected string literal\n   --> tests/ui/invalid_frompy_derive.rs:100:22\n    |\n100 |     #[pyo3(attribute())]\n    |                      ^\n\nerror: expected at most one argument: `item` or `item(key)`\n   --> tests/ui/invalid_frompy_derive.rs:106:20\n    |\n106 |     #[pyo3(item(\"a\", \"b\"))]\n    |                    ^\n\nerror: unexpected end of input, expected literal\n   --> tests/ui/invalid_frompy_derive.rs:112:17\n    |\n112 |     #[pyo3(item())]\n    |                 ^\n\nerror: only one of `attribute` or `item` can be provided\n   --> tests/ui/invalid_frompy_derive.rs:118:18\n    |\n118 |     #[pyo3(item, attribute)]\n    |                  ^^^^^^^^^\n\nerror: expected one of: `transparent`, `from_item_all`, `annotation`, `crate`, `rename_all`\n   --> tests/ui/invalid_frompy_derive.rs:123:8\n    |\n123 | #[pyo3(unknown = \"should not work\")]\n    |        ^^^^^^^\n\nerror: `annotation` is unsupported for structs\n   --> tests/ui/invalid_frompy_derive.rs:129:21\n    |\n129 | #[pyo3(annotation = \"should not work\")]\n    |                     ^^^^^^^^^^^^^^^^^\n\nerror: expected string literal\n   --> tests/ui/invalid_frompy_derive.rs:136:25\n    |\n136 |     #[pyo3(annotation = 1)]\n    |                         ^\n\nerror: FromPyObject can be derived with at most one lifetime parameter\n   --> tests/ui/invalid_frompy_derive.rs:141:22\n    |\n141 | enum TooManyLifetimes<'a, 'b> {\n    |                      ^\n\nerror: #[derive(FromPyObject)] is not supported for unions\n   --> tests/ui/invalid_frompy_derive.rs:147:1\n    |\n147 | union Union {\n    | ^^^^^\n\nerror: cannot derive FromPyObject for empty structs and variants\n   --> tests/ui/invalid_frompy_derive.rs:151:10\n    |\n151 | #[derive(FromPyObject)]\n    |          ^^^^^^^^^^^^\n    |\n    = note: this error originates in the derive macro `FromPyObject` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror: expected `=`\n   --> tests/ui/invalid_frompy_derive.rs:158:24\n    |\n158 |     #[pyo3(from_py_with)]\n    |                        ^\n\nerror: `getter` is not permitted on tuple struct elements.\n   --> tests/ui/invalid_frompy_derive.rs:169:27\n    |\n169 | struct InvalidTupleGetter(#[pyo3(item(\"foo\"))] String);\n    |                           ^\n\nerror: `transparent` structs may not have a `getter` for the inner field\n   --> tests/ui/invalid_frompy_derive.rs:175:5\n    |\n175 |     field: String,\n    |     ^^^^^\n\nerror: `transparent` structs may not have a `getter` for the inner field\n   --> tests/ui/invalid_frompy_derive.rs:186:5\n    |\n186 |     field: String,\n    |     ^^^^^\n\nerror: `from_item_all` may only be specified once\n   --> tests/ui/invalid_frompy_derive.rs:190:23\n    |\n190 | #[pyo3(from_item_all, from_item_all)]\n    |                       ^^^^^^^^^^^^^\n\nerror: Useless `item` - the struct is already annotated with `from_item_all`\n   --> tests/ui/invalid_frompy_derive.rs:196:8\n    |\n196 | #[pyo3(from_item_all)]\n    |        ^^^^^^^^^^^^^\n\nerror: The struct is already annotated with `from_item_all`, `attribute` is not allowed\n   --> tests/ui/invalid_frompy_derive.rs:203:8\n    |\n203 | #[pyo3(from_item_all)]\n    |        ^^^^^^^^^^^^^\n\nerror: The struct is already annotated with `from_item_all`, `attribute` is not allowed\n   --> tests/ui/invalid_frompy_derive.rs:210:8\n    |\n210 | #[pyo3(from_item_all)]\n    |        ^^^^^^^^^^^^^\n\nerror: cannot derive FromPyObject for structs and variants with only default values\n   --> tests/ui/invalid_frompy_derive.rs:217:36\n    |\n217 |   struct StructWithOnlyDefaultValues {\n    |  ____________________________________^\n218 | |     #[pyo3(default)]\n219 | |     field: String,\n220 | | }\n    | |_^\n\nerror: cannot derive FromPyObject for structs and variants with only default values\n   --> tests/ui/invalid_frompy_derive.rs:224:9\n    |\n224 |       Foo {\n    |  _________^\n225 | |         #[pyo3(default)]\n226 | |         field: String,\n227 | |     },\n    | |_____^\n\nerror: `default` is not permitted on tuple struct elements.\n   --> tests/ui/invalid_frompy_derive.rs:231:37\n    |\n231 | struct NamedTuplesWithDefaultValues(#[pyo3(default)] String);\n    |                                     ^\n\nerror: `rename_all` may only be specified once\n   --> tests/ui/invalid_frompy_derive.rs:234:34\n    |\n234 | #[pyo3(rename_all = \"camelCase\", rename_all = \"kebab-case\")]\n    |                                  ^^^^^^^^^^\n\nerror: `rename_all` is useless on tuple structs and variants.\n   --> tests/ui/invalid_frompy_derive.rs:240:8\n    |\n240 | #[pyo3(rename_all = \"camelCase\")]\n    |        ^^^^^^^^^^\n\nerror: `rename_all` is useless on tuple structs and variants.\n   --> tests/ui/invalid_frompy_derive.rs:245:12\n    |\n245 |     #[pyo3(rename_all = \"camelCase\")]\n    |            ^^^^^^^^^^\n\nerror: `rename_all` is not permitted on `transparent` structs and variants\n   --> tests/ui/invalid_frompy_derive.rs:250:21\n    |\n250 | #[pyo3(transparent, rename_all = \"camelCase\")]\n    |                     ^^^^^^^^^^\n\nerror: Useless variant `rename_all` - enum is already annotated with `rename_all\n   --> tests/ui/invalid_frompy_derive.rs:258:12\n    |\n258 |     #[pyo3(rename_all = \"camelCase\")]\n    |            ^^^^^^^^^^\n\nerror[E0425]: cannot find value `func` in this scope\n   --> tests/ui/invalid_frompy_derive.rs:164:27\n    |\n164 |     #[pyo3(from_py_with = func)]\n    |                           ^^^^ not found in this scope\n"
  },
  {
    "path": "tests/ui/invalid_frozen_pyclass_borrow.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass(frozen)]\npub struct Foo {\n    #[pyo3(get)]\n    field: u32,\n}\n\n#[pymethods]\nimpl Foo {\n    fn mut_method(&mut self) {}\n}\n\nfn borrow_mut_fails(foo: Py<Foo>, py: Python) {\n    let borrow = foo.bind(py).borrow_mut();\n}\n\n#[pyclass(subclass)]\nstruct MutableBase;\n\n#[pyclass(frozen, extends = MutableBase)]\nstruct ImmutableChild;\n\nfn borrow_mut_of_child_fails(child: Py<ImmutableChild>, py: Python) {\n    let borrow = child.bind(py).borrow_mut();\n}\n\nfn py_get_of_mutable_class_fails(class: Py<MutableBase>) {\n    class.get();\n}\n\nfn pyclass_get_of_mutable_class_fails(class: &Bound<'_, MutableBase>) {\n    class.get();\n}\n\n#[pyclass(frozen)]\npub struct SetOnFrozenClass {\n    #[pyo3(set)]\n    field: u32,\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_frozen_pyclass_borrow.stderr",
    "content": "error: cannot use `#[pyo3(set)]` on a `frozen` class\n  --> tests/ui/invalid_frozen_pyclass_borrow.rs:38:12\n   |\n38 |     #[pyo3(set)]\n   |            ^^^\n\nerror[E0271]: type mismatch resolving `<Foo as PyClass>::Frozen == False`\n  --> tests/ui/invalid_frozen_pyclass_borrow.rs:11:19\n   |\n11 |     fn mut_method(&mut self) {}\n   |                   ^ type mismatch resolving `<Foo as PyClass>::Frozen == False`\n   |\nnote: expected this to be `False`\n  --> tests/ui/invalid_frozen_pyclass_borrow.rs:3:1\n   |\n 3 | #[pyclass(frozen)]\n   | ^^^^^^^^^^^^^^^^^^\nnote: required by a bound in `extract_pyclass_ref_mut`\n  --> src/impl_/extract_argument.rs\n   |\n   | pub fn extract_pyclass_ref_mut<'a, 'holder, T: PyClass<Frozen = False>>(\n   |                                                        ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut`\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0271]: type mismatch resolving `<Foo as PyClass>::Frozen == False`\n --> tests/ui/invalid_frozen_pyclass_borrow.rs:9:1\n  |\n9 | #[pymethods]\n  | ^^^^^^^^^^^^ type mismatch resolving `<Foo as PyClass>::Frozen == False`\n  |\nnote: expected this to be `False`\n --> tests/ui/invalid_frozen_pyclass_borrow.rs:3:1\n  |\n3 | #[pyclass(frozen)]\n  | ^^^^^^^^^^^^^^^^^^\nnote: required by a bound in `PyClassGuardMut`\n --> src/pyclass/guard.rs\n  |\n  | pub struct PyClassGuardMut<'a, T: PyClass<Frozen = False>> {\n  |                                           ^^^^^^^^^^^^^^ required by this bound in `PyClassGuardMut`\n  = note: this error originates in the attribute macro `pymethods` which comes from the expansion of the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0271]: type mismatch resolving `<Foo as PyClass>::Frozen == False`\n  --> tests/ui/invalid_frozen_pyclass_borrow.rs:15:31\n   |\n15 |     let borrow = foo.bind(py).borrow_mut();\n   |                               ^^^^^^^^^^ type mismatch resolving `<Foo as PyClass>::Frozen == False`\n   |\nnote: expected this to be `False`\n  --> tests/ui/invalid_frozen_pyclass_borrow.rs:3:1\n   |\n 3 | #[pyclass(frozen)]\n   | ^^^^^^^^^^^^^^^^^^\nnote: required by a bound in `pyo3::Bound::<'py, T>::borrow_mut`\n  --> src/instance.rs\n   |\n   |     pub fn borrow_mut(&self) -> PyRefMut<'py, T>\n   |            ---------- required by a bound in this associated function\n   |     where\n   |         T: PyClass<Frozen = False>,\n   |                    ^^^^^^^^^^^^^^ required by this bound in `Bound::<'py, T>::borrow_mut`\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0271]: type mismatch resolving `<ImmutableChild as PyClass>::Frozen == False`\n  --> tests/ui/invalid_frozen_pyclass_borrow.rs:25:33\n   |\n25 |     let borrow = child.bind(py).borrow_mut();\n   |                                 ^^^^^^^^^^ type mismatch resolving `<ImmutableChild as PyClass>::Frozen == False`\n   |\nnote: expected this to be `False`\n  --> tests/ui/invalid_frozen_pyclass_borrow.rs:21:1\n   |\n21 | #[pyclass(frozen, extends = MutableBase)]\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nnote: required by a bound in `pyo3::Bound::<'py, T>::borrow_mut`\n  --> src/instance.rs\n   |\n   |     pub fn borrow_mut(&self) -> PyRefMut<'py, T>\n   |            ---------- required by a bound in this associated function\n   |     where\n   |         T: PyClass<Frozen = False>,\n   |                    ^^^^^^^^^^^^^^ required by this bound in `Bound::<'py, T>::borrow_mut`\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0271]: type mismatch resolving `<MutableBase as PyClass>::Frozen == True`\n  --> tests/ui/invalid_frozen_pyclass_borrow.rs:29:11\n   |\n29 |     class.get();\n   |           ^^^ type mismatch resolving `<MutableBase as PyClass>::Frozen == True`\n   |\nnote: expected this to be `True`\n  --> tests/ui/invalid_frozen_pyclass_borrow.rs:18:1\n   |\n18 | #[pyclass(subclass)]\n   | ^^^^^^^^^^^^^^^^^^^^\nnote: required by a bound in `pyo3::Py::<T>::get`\n  --> src/instance.rs\n   |\n   |     pub fn get(&self) -> &T\n   |            --- required by a bound in this associated function\n   |     where\n   |         T: PyClass<Frozen = True> + Sync,\n   |                    ^^^^^^^^^^^^^ required by this bound in `Py::<T>::get`\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0271]: type mismatch resolving `<MutableBase as PyClass>::Frozen == True`\n  --> tests/ui/invalid_frozen_pyclass_borrow.rs:33:11\n   |\n33 |     class.get();\n   |           ^^^ type mismatch resolving `<MutableBase as PyClass>::Frozen == True`\n   |\nnote: expected this to be `True`\n  --> tests/ui/invalid_frozen_pyclass_borrow.rs:18:1\n   |\n18 | #[pyclass(subclass)]\n   | ^^^^^^^^^^^^^^^^^^^^\nnote: required by a bound in `pyo3::Bound::<'py, T>::get`\n  --> src/instance.rs\n   |\n   |     pub fn get(&self) -> &T\n   |            --- required by a bound in this associated function\n   |     where\n   |         T: PyClass<Frozen = True> + Sync,\n   |                    ^^^^^^^^^^^^^ required by this bound in `Bound::<'py, T>::get`\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "tests/ui/invalid_intern_arg.rs",
    "content": "use pyo3::Python;\n\nfn main() {\n    let _foo = if true { \"foo\" } else { \"bar\" };\n    Python::attach(|py| py.import(pyo3::intern!(py, _foo)).unwrap());\n}\n"
  },
  {
    "path": "tests/ui/invalid_intern_arg.stderr",
    "content": "error[E0435]: attempt to use a non-constant value in a constant\n --> tests/ui/invalid_intern_arg.rs:5:53\n  |\n5 |     Python::attach(|py| py.import(pyo3::intern!(py, _foo)).unwrap());\n  |                                                     ^^^^ non-constant value\n  |\nhelp: consider using `let` instead of `static`\n --> src/sync.rs\n  |\n    -         static INTERNED: $crate::sync::Interned = $crate::sync::Interned::new($text);\n    +         let INTERNED: $crate::sync::Interned = $crate::sync::Interned::new($text);\n    |\n\nerror: lifetime may not live long enough\n --> tests/ui/invalid_intern_arg.rs:5:25\n  |\n5 |     Python::attach(|py| py.import(pyo3::intern!(py, _foo)).unwrap());\n  |                     --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`\n  |                     | |\n  |                     | return type of closure is pyo3::Bound<'2, PyModule>\n  |                     has type `Python<'1>`\n"
  },
  {
    "path": "tests/ui/invalid_intopy_derive.rs",
    "content": "use pyo3::{IntoPyObject, IntoPyObjectRef};\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nstruct Foo();\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nstruct Foo2 {}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nenum EmptyEnum {}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nenum EnumWithEmptyTupleVar {\n    EmptyTuple(),\n    Valid(String),\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nenum EnumWithEmptyStructVar {\n    EmptyStruct {},\n    Valid(String),\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\n#[pyo3(transparent)]\nstruct EmptyTransparentTup();\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\n#[pyo3(transparent)]\nstruct EmptyTransparentStruct {}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nenum EnumWithTransparentEmptyTupleVar {\n    #[pyo3(transparent)]\n    EmptyTuple(),\n    Valid(String),\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nenum EnumWithTransparentEmptyStructVar {\n    #[pyo3(transparent)]\n    EmptyStruct {},\n    Valid(String),\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\n#[pyo3(transparent)]\nstruct TransparentTupTooManyFields(String, String);\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\n#[pyo3(transparent)]\nstruct TransparentStructTooManyFields {\n    foo: String,\n    bar: String,\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nenum EnumWithTransparentTupleTooMany {\n    #[pyo3(transparent)]\n    EmptyTuple(String, String),\n    Valid(String),\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nenum EnumWithTransparentStructTooMany {\n    #[pyo3(transparent)]\n    EmptyStruct {\n        foo: String,\n        bar: String,\n    },\n    Valid(String),\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\n#[pyo3(unknown = \"should not work\")]\nstruct UnknownContainerAttr {\n    a: String,\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nunion Union {\n    a: usize,\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nenum UnitEnum {\n    Unit,\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nstruct TupleAttribute(#[pyo3(attribute)] String, usize);\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nstruct TupleItem(#[pyo3(item)] String, usize);\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nstruct StructAttribute {\n    #[pyo3(attribute)]\n    foo: String,\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\n#[pyo3(transparent)]\nstruct StructTransparentItem {\n    #[pyo3(item)]\n    foo: String,\n}\n\n#[derive(IntoPyObject)]\n#[pyo3(transparent)]\nstruct StructTransparentIntoPyWith {\n    #[pyo3(into_py_with = into)]\n    foo: String,\n}\n\n#[derive(IntoPyObjectRef)]\n#[pyo3(transparent)]\nstruct StructTransparentIntoPyWithRef {\n    #[pyo3(into_py_with = into_ref)]\n    foo: String,\n}\n\n#[derive(IntoPyObject)]\n#[pyo3(transparent)]\nstruct TupleTransparentIntoPyWith(#[pyo3(into_py_with = into)] String);\n\n#[derive(IntoPyObject)]\nenum EnumTupleIntoPyWith {\n    TransparentTuple(#[pyo3(into_py_with = into)] usize),\n}\n\n#[derive(IntoPyObject)]\nenum EnumStructIntoPyWith {\n    #[pyo3(transparent)]\n    TransparentStruct {\n        #[pyo3(into_py_with = into)]\n        a: usize,\n    },\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\n#[pyo3(transparent, rename_all = \"camelCase\")]\nstruct StructTransparentRenameAll {\n    foo_bar: String,\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\n#[pyo3(rename_all = \"camelCase\")]\nstruct StructTupleRenameAll(String, usize);\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nenum EnumTransparentVariantRenameAll {\n    #[pyo3(rename_all = \"camelCase\")]\n    #[pyo3(transparent)]\n    Variant { foo: String },\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nenum EnumTupleVariantRenameAll {\n    #[pyo3(rename_all = \"camelCase\")]\n    Variant(String, usize),\n}\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\n#[pyo3(rename_all = \"camelCase\")]\nenum EnumTopRenameAll {\n    Variant { foo: String },\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_intopy_derive.stderr",
    "content": "error: cannot derive `IntoPyObject` for empty structs\n --> tests/ui/invalid_intopy_derive.rs:4:11\n  |\n4 | struct Foo();\n  |           ^^\n\nerror: cannot derive `IntoPyObject` for empty structs\n --> tests/ui/invalid_intopy_derive.rs:7:13\n  |\n7 | struct Foo2 {}\n  |             ^^\n\nerror: cannot derive `IntoPyObject` for empty enum\n  --> tests/ui/invalid_intopy_derive.rs:10:6\n   |\n10 | enum EmptyEnum {}\n   |      ^^^^^^^^^\n\nerror: cannot derive `IntoPyObject` for empty variants\n  --> tests/ui/invalid_intopy_derive.rs:14:5\n   |\n14 |     EmptyTuple(),\n   |     ^^^^^^^^^^\n\nerror: cannot derive `IntoPyObject` for empty variants\n  --> tests/ui/invalid_intopy_derive.rs:20:5\n   |\n20 |     EmptyStruct {},\n   |     ^^^^^^^^^^^\n\nerror: cannot derive `IntoPyObject` for empty structs\n  --> tests/ui/invalid_intopy_derive.rs:26:27\n   |\n26 | struct EmptyTransparentTup();\n   |                           ^^\n\nerror: cannot derive `IntoPyObject` for empty structs\n  --> tests/ui/invalid_intopy_derive.rs:30:31\n   |\n30 | struct EmptyTransparentStruct {}\n   |                               ^^\n\nerror: cannot derive `IntoPyObject` for empty variants\n  --> tests/ui/invalid_intopy_derive.rs:35:5\n   |\n35 |     EmptyTuple(),\n   |     ^^^^^^^^^^\n\nerror: cannot derive `IntoPyObject` for empty variants\n  --> tests/ui/invalid_intopy_derive.rs:42:5\n   |\n42 |     EmptyStruct {},\n   |     ^^^^^^^^^^^\n\nerror: transparent structs and variants can only have 1 field\n  --> tests/ui/invalid_intopy_derive.rs:48:35\n   |\n48 | struct TransparentTupTooManyFields(String, String);\n   |                                   ^^^^^^^^^^^^^^^^\n\nerror: transparent structs and variants can only have 1 field\n  --> tests/ui/invalid_intopy_derive.rs:52:39\n   |\n52 |   struct TransparentStructTooManyFields {\n   |  _______________________________________^\n53 | |     foo: String,\n54 | |     bar: String,\n55 | | }\n   | |_^\n\nerror: transparent structs and variants can only have 1 field\n  --> tests/ui/invalid_intopy_derive.rs:60:15\n   |\n60 |     EmptyTuple(String, String),\n   |               ^^^^^^^^^^^^^^^^\n\nerror: transparent structs and variants can only have 1 field\n  --> tests/ui/invalid_intopy_derive.rs:67:17\n   |\n67 |       EmptyStruct {\n   |  _________________^\n68 | |         foo: String,\n69 | |         bar: String,\n70 | |     },\n   | |_____^\n\nerror: expected one of: `transparent`, `from_item_all`, `annotation`, `crate`, `rename_all`\n  --> tests/ui/invalid_intopy_derive.rs:75:8\n   |\n75 | #[pyo3(unknown = \"should not work\")]\n   |        ^^^^^^^\n\nerror: #[derive(`IntoPyObject`)] is not supported for unions\n  --> tests/ui/invalid_intopy_derive.rs:81:1\n   |\n81 | union Union {\n   | ^^^^^\n\nerror: cannot derive `IntoPyObject` for empty variants\n  --> tests/ui/invalid_intopy_derive.rs:87:5\n   |\n87 |     Unit,\n   |     ^^^^\n\nerror: `item` and `attribute` are not permitted on tuple struct elements.\n  --> tests/ui/invalid_intopy_derive.rs:91:30\n   |\n91 | struct TupleAttribute(#[pyo3(attribute)] String, usize);\n   |                              ^^^^^^^^^\n\nerror: `item` and `attribute` are not permitted on tuple struct elements.\n  --> tests/ui/invalid_intopy_derive.rs:94:25\n   |\n94 | struct TupleItem(#[pyo3(item)] String, usize);\n   |                         ^^^^\n\nerror: `transparent` structs may not have `item` nor `attribute` for the inner field\n   --> tests/ui/invalid_intopy_derive.rs:105:12\n    |\n105 |     #[pyo3(item)]\n    |            ^^^^\n\nerror: `into_py_with` is not permitted on `transparent` structs or variants\n   --> tests/ui/invalid_intopy_derive.rs:112:12\n    |\n112 |     #[pyo3(into_py_with = into)]\n    |            ^^^^^^^^^^^^\n\nerror: `into_py_with` is not permitted on `transparent` structs or variants\n   --> tests/ui/invalid_intopy_derive.rs:119:12\n    |\n119 |     #[pyo3(into_py_with = into_ref)]\n    |            ^^^^^^^^^^^^\n\nerror: `into_py_with` is not permitted on `transparent` structs\n   --> tests/ui/invalid_intopy_derive.rs:125:42\n    |\n125 | struct TupleTransparentIntoPyWith(#[pyo3(into_py_with = into)] String);\n    |                                          ^^^^^^^^^^^^\n\nerror: `into_py_with` is not permitted on `transparent` structs\n   --> tests/ui/invalid_intopy_derive.rs:129:29\n    |\n129 |     TransparentTuple(#[pyo3(into_py_with = into)] usize),\n    |                             ^^^^^^^^^^^^\n\nerror: `into_py_with` is not permitted on `transparent` structs or variants\n   --> tests/ui/invalid_intopy_derive.rs:136:16\n    |\n136 |         #[pyo3(into_py_with = into)]\n    |                ^^^^^^^^^^^^\n\nerror: `rename_all` is not permitted on `transparent` structs and variants\n   --> tests/ui/invalid_intopy_derive.rs:142:21\n    |\n142 | #[pyo3(transparent, rename_all = \"camelCase\")]\n    |                     ^^^^^^^^^^\n\nerror: `rename_all` is useless on tuple structs and variants.\n   --> tests/ui/invalid_intopy_derive.rs:148:8\n    |\n148 | #[pyo3(rename_all = \"camelCase\")]\n    |        ^^^^^^^^^^\n\nerror: `rename_all` is not permitted on `transparent` structs and variants\n   --> tests/ui/invalid_intopy_derive.rs:153:12\n    |\n153 |     #[pyo3(rename_all = \"camelCase\")]\n    |            ^^^^^^^^^^\n\nerror: `rename_all` is useless on tuple structs and variants.\n   --> tests/ui/invalid_intopy_derive.rs:160:12\n    |\n160 |     #[pyo3(rename_all = \"camelCase\")]\n    |            ^^^^^^^^^^\n\nerror: `rename_all` is not supported at top level for enums\n   --> tests/ui/invalid_intopy_derive.rs:165:8\n    |\n165 | #[pyo3(rename_all = \"camelCase\")]\n    |        ^^^^^^^^^^\n"
  },
  {
    "path": "tests/ui/invalid_intopy_with.rs",
    "content": "use pyo3::{IntoPyObject, IntoPyObjectRef};\n\n#[derive(IntoPyObject, IntoPyObjectRef)]\nstruct InvalidIntoPyWithFn {\n    #[pyo3(into_py_with = into)]\n    inner: String,\n}\n\nfn into(_a: String, _py: pyo3::Python<'_>) -> pyo3::PyResult<pyo3::Bound<'_, pyo3::PyAny>> {\n    todo!()\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_intopy_with.stderr",
    "content": "error[E0308]: mismatched types\n --> tests/ui/invalid_intopy_with.rs:5:27\n  |\n3 | #[derive(IntoPyObject, IntoPyObjectRef)]\n  |          ------------ expected due to this\n4 | struct InvalidIntoPyWithFn {\n5 |     #[pyo3(into_py_with = into)]\n  |                           ^^^^ expected fn pointer, found fn item\n  |\n  = note: expected fn pointer `for<'a> fn(Cow<'a, _>, Python<'py>) -> Result<pyo3::Bound<'py, PyAny>, PyErr>`\n                found fn item `for<'a> fn(String, Python<'a>) -> Result<pyo3::Bound<'a, PyAny>, PyErr> {into}`\n\nerror[E0308]: mismatched types\n --> tests/ui/invalid_intopy_with.rs:5:27\n  |\n3 | #[derive(IntoPyObject, IntoPyObjectRef)]\n  |                        --------------- expected due to this\n4 | struct InvalidIntoPyWithFn {\n5 |     #[pyo3(into_py_with = into)]\n  |                           ^^^^ expected fn pointer, found fn item\n  |\n  = note: expected fn pointer `for<'a> fn(Cow<'a, _>, Python<'py>) -> Result<pyo3::Bound<'py, PyAny>, PyErr>`\n                found fn item `for<'a> fn(String, Python<'a>) -> Result<pyo3::Bound<'a, PyAny>, PyErr> {into}`\n"
  },
  {
    "path": "tests/ui/invalid_property_args.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass]\nstruct ClassWithGetter {}\n\n#[pymethods]\nimpl ClassWithGetter {\n    #[getter]\n    fn getter_with_arg(&self, _py: Python<'_>, _index: u32) {}\n}\n\n#[pyclass]\nstruct ClassWithSetter {}\n\n#[pymethods]\nimpl ClassWithSetter {\n    #[setter]\n    fn setter_with_no_arg(&mut self, _py: Python<'_>) {}\n}\n\n#[pymethods]\nimpl ClassWithSetter {\n    #[setter]\n    fn setter_with_too_many_args(&mut self, _py: Python<'_>, _foo: u32, _bar: u32) {}\n}\n\n#[pyclass]\nstruct TupleGetterSetterNoName(#[pyo3(get, set)] i32);\n\n#[pyclass]\nstruct MultipleGet(#[pyo3(get, get)] i32);\n\n#[pyclass]\nstruct MultipleSet(#[pyo3(set, set)] i32);\n\n#[pyclass]\nstruct MultipleName(#[pyo3(name = \"foo\", name = \"bar\")] i32);\n\n#[pyclass]\nstruct NameWithoutGetSet(#[pyo3(name = \"value\")] i32);\n\n#[pyclass]\nstruct InvalidGetterType {\n    #[pyo3(get)]\n    value: ::std::marker::PhantomData<i32>,\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_property_args.stderr",
    "content": "error: getter function can only have one argument (of type pyo3::Python)\n --> tests/ui/invalid_property_args.rs:9:56\n  |\n9 |     fn getter_with_arg(&self, _py: Python<'_>, _index: u32) {}\n  |                                                        ^^^\n\nerror: setter function expected to have one argument\n  --> tests/ui/invalid_property_args.rs:18:8\n   |\n18 |     fn setter_with_no_arg(&mut self, _py: Python<'_>) {}\n   |        ^^^^^^^^^^^^^^^^^^\n\nerror: setter function can have at most two arguments ([pyo3::Python,] and value)\n  --> tests/ui/invalid_property_args.rs:24:79\n   |\n24 |     fn setter_with_too_many_args(&mut self, _py: Python<'_>, _foo: u32, _bar: u32) {}\n   |                                                                               ^^^\n\nerror: `get` and `set` with tuple struct fields require `name`\n  --> tests/ui/invalid_property_args.rs:28:50\n   |\n28 | struct TupleGetterSetterNoName(#[pyo3(get, set)] i32);\n   |                                                  ^^^\n\nerror: `get` may only be specified once\n  --> tests/ui/invalid_property_args.rs:31:32\n   |\n31 | struct MultipleGet(#[pyo3(get, get)] i32);\n   |                                ^^^\n\nerror: `set` may only be specified once\n  --> tests/ui/invalid_property_args.rs:34:32\n   |\n34 | struct MultipleSet(#[pyo3(set, set)] i32);\n   |                                ^^^\n\nerror: `name` may only be specified once\n  --> tests/ui/invalid_property_args.rs:37:42\n   |\n37 | struct MultipleName(#[pyo3(name = \"foo\", name = \"bar\")] i32);\n   |                                          ^^^^\n\nerror: `name` is useless without `get` or `set`\n  --> tests/ui/invalid_property_args.rs:40:33\n   |\n40 | struct NameWithoutGetSet(#[pyo3(name = \"value\")] i32);\n   |                                 ^^^^^^^^^^^^^^\n\nerror[E0277]: `PhantomData<i32>` cannot be converted to a Python object\n  --> tests/ui/invalid_property_args.rs:45:12\n   |\n45 |     value: ::std::marker::PhantomData<i32>,\n   |            ^ required by `#[pyo3(get)]` to create a readable property from a field of type `PhantomData<i32>`\n   |\n   = help: the trait `IntoPyObject<'_>` is not implemented for `PhantomData<i32>`\n   = note: implement `IntoPyObject` for `&PhantomData<i32>` or `IntoPyObject + Clone` for `PhantomData<i32>` to define the conversion\n   = help: the following other types implement trait `IntoPyObject<'py>`:\n             &&'a T\n             &&OsStr\n             &&Path\n             &&str\n             &'a (T0, T1)\n             &'a (T0, T1, T2)\n             &'a (T0, T1, T2, T3)\n             &'a (T0, T1, T2, T3, T4)\n           and $N others\n   = note: required for `PhantomData<i32>` to implement `for<'py> PyO3GetField<'py>`\nnote: required by a bound in `PyClassGetterGenerator::<ClassT, FieldT, OFFSET, false, false, IMPLEMENTS_INTOPYOBJECT>::generate`\n  --> src/impl_/pyclass.rs\n   |\n   |     pub const fn generate(&self, name: &'static CStr, doc: Option<&'static CStr>) -> PyMethodDefType\n   |                  -------- required by a bound in this associated function\n...\n   |         for<'py> FieldT: PyO3GetField<'py>,\n   |                          ^^^^^^^^^^^^^^^^^ required by this bound in `PyClassGetterGenerator::<ClassT, FieldT, OFFSET, false, false, IMPLEMENTS_INTOPYOBJECT>::generate`\n"
  },
  {
    "path": "tests/ui/invalid_proto_pymethods.rs",
    "content": "//! Check that some magic methods edge cases error as expected.\n//!\n//! For convenience use #[pyo3(name = \"__some_dunder__\")] to create the methods,\n//! so that the function names can describe the edge case to be rejected.\n\nuse pyo3::prelude::*;\nuse pyo3::pyclass::CompareOp;\n\n#[pyclass]\nstruct MyClass {}\n\n//\n// Argument counts\n//\n\n#[pymethods]\nimpl MyClass {\n    #[pyo3(name = \"__truediv__\")]\n    fn truediv_expects_one_argument(&self) -> PyResult<()> {\n        Ok(())\n    }\n}\n\n#[pymethods]\nimpl MyClass {\n    #[pyo3(name = \"__truediv__\")]\n    fn truediv_expects_one_argument_py(&self, _py: Python<'_>) -> PyResult<()> {\n        Ok(())\n    }\n}\n\n//\n// Forbidden attributes\n//\n\n#[pymethods]\nimpl MyClass {\n    #[pyo3(name = \"__bool__\", signature = ())]\n    fn signature_is_forbidden(&self) -> bool {\n        true\n    }\n}\n\n#[pymethods]\nimpl MyClass {\n    #[pyo3(name = \"__bool__\", text_signature = \"\")]\n    fn text_signature_is_forbidden(&self) -> bool {\n        true\n    }\n}\n\n#[pyclass]\nstruct EqAndRichcmp;\n\n#[pymethods]\nimpl EqAndRichcmp {\n    fn __eq__(&self, _other: &Self) -> bool {\n        true\n    }\n\n    fn __richcmp__(&self, _other: &Self, _op: CompareOp) -> bool {\n        true\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_proto_pymethods.stderr",
    "content": "error: Expected 1 arguments, got 0\n  --> tests/ui/invalid_proto_pymethods.rs:19:8\n   |\n19 |     fn truediv_expects_one_argument(&self) -> PyResult<()> {\n   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: Expected 1 arguments, got 0\n  --> tests/ui/invalid_proto_pymethods.rs:27:8\n   |\n27 |     fn truediv_expects_one_argument_py(&self, _py: Python<'_>) -> PyResult<()> {\n   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: `signature` cannot be used with magic method `__bool__`\n  --> tests/ui/invalid_proto_pymethods.rs:38:31\n   |\n38 |     #[pyo3(name = \"__bool__\", signature = ())]\n   |                               ^^^^^^^^^\n\nerror: `text_signature` cannot be used with magic method `__bool__`\n  --> tests/ui/invalid_proto_pymethods.rs:46:31\n   |\n46 |     #[pyo3(name = \"__bool__\", text_signature = \"\")]\n   |                               ^^^^^^^^^^^^^^\n\nerror[E0592]: duplicate definitions with name `__pymethod___richcmp____`\n  --> tests/ui/invalid_proto_pymethods.rs:55:1\n   |\n55 | #[pymethods]\n   | ^^^^^^^^^^^^\n   | |\n   | duplicate definitions for `__pymethod___richcmp____`\n   | other definition for `__pymethod___richcmp____`\n   |\n   = note: this error originates in the macro `::pyo3::impl_::pyclass::generate_pyclass_richcompare_slot` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_proto_pymethods.rs:55:1\n   |\n55 | #[pymethods]\n   | ^^^^^^^^^^^^ multiple `__pymethod___richcmp____` found\n   |\nnote: candidate #1 is defined in an impl for the type `EqAndRichcmp`\n  --> tests/ui/invalid_proto_pymethods.rs:55:1\n   |\n55 | #[pymethods]\n   | ^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `EqAndRichcmp`\n  --> tests/ui/invalid_proto_pymethods.rs:55:1\n   |\n55 | #[pymethods]\n   | ^^^^^^^^^^^^\n   = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_proto_pymethods.rs:55:1\n   |\n55 | #[pymethods]\n   | ^^^^^^^^^^^^ multiple `__pymethod___richcmp____` found\n   |\nnote: candidate #1 is defined in an impl for the type `EqAndRichcmp`\n  --> tests/ui/invalid_proto_pymethods.rs:55:1\n   |\n55 | #[pymethods]\n   | ^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `EqAndRichcmp`\n  --> tests/ui/invalid_proto_pymethods.rs:55:1\n   |\n55 | #[pymethods]\n   | ^^^^^^^^^^^^\n   = note: this error originates in the macro `::pyo3::impl_::pyclass::generate_pyclass_richcompare_slot` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "tests/ui/invalid_pycallargs.rs",
    "content": "use pyo3::prelude::*;\r\n\r\nfn main() {\r\n    Python::attach(|py| {\r\n        let any = py.None().into_bound(py);\r\n        any.call1(\"foo\");\r\n    })\r\n}\r\n"
  },
  {
    "path": "tests/ui/invalid_pycallargs.stderr",
    "content": "error[E0277]: `&str` cannot used as a Python `call` argument\n --> tests/ui/invalid_pycallargs.rs:6:19\n  |\n6 |         any.call1(\"foo\");\n  |             ----- ^^^^^ the trait `PyCallArgs<'_>` is not implemented for `&str`\n  |             |\n  |             required by a bound introduced by this call\n  |\n  = note: `PyCallArgs` is implemented for Rust tuples, `Bound<'py, PyTuple>` and `Py<PyTuple>`\n  = note: if your type is convertible to `PyTuple` via `IntoPyObject`, call `<arg>.into_pyobject(py)` manually\n  = note: if you meant to pass the type as a single argument, wrap it in a 1-tuple, `(<arg>,)`\n  = help: the following other types implement trait `PyCallArgs<'py>`:\n            &'a (T0, T1)\n            &'a (T0, T1, T2)\n            &'a (T0, T1, T2, T3)\n            &'a (T0, T1, T2, T3, T4)\n            &'a (T0, T1, T2, T3, T4, T5)\n            &'a (T0, T1, T2, T3, T4, T5, T6)\n            &'a (T0, T1, T2, T3, T4, T5, T6, T7)\n            &'a (T0, T1, T2, T3, T4, T5, T6, T7, T8)\n          and $N others\nnote: required by a bound in `call1`\n --> src/types/any.rs\n  |\n  |     fn call1<A>(&self, args: A) -> PyResult<Bound<'py, PyAny>>\n  |        ----- required by a bound in this associated function\n  |     where\n  |         A: PyCallArgs<'py>;\n  |            ^^^^^^^^^^^^^^^ required by this bound in `PyAnyMethods::call1`\nhelp: use a unary tuple instead\n  |\n6 |         any.call1((\"foo\",));\n  |                   +     ++\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_args.rs",
    "content": "use pyo3::prelude::*;\nuse std::fmt::{Display, Formatter};\n\n#[pyclass(extend=pyo3::types::PyDict)]\nstruct TypoIntheKey {}\n\n#[pyclass(extends = \"PyDict\")]\nstruct InvalidExtends {}\n\n#[pyclass(name = m::MyClass)]\nstruct InvalidName {}\n\n#[pyclass(name = \"Custom Name\")]\nstruct InvalidName2 {}\n\n#[pyclass(name = CustomName)]\nstruct DeprecatedName {}\n\n#[pyclass(rename_all = camelCase)]\nstruct InvalidRenamingRule {}\n\n#[pyclass(rename_all = \"Camel-Case\")]\nstruct InvalidRenamingRule2 {}\n\n#[pyclass(module = my_module)]\nstruct InvalidModule {}\n\n#[pyclass(weakrev)]\nstruct InvalidArg {}\n\n#[pyclass(mapping, sequence)]\nstruct CannotBeMappingAndSequence {}\n\n#[pyclass(eq)]\nstruct EqOptRequiresEq {}\n\n#[pyclass(eq)]\n#[derive(PartialEq)]\nstruct EqOptAndManualRichCmp {}\n\n#[pymethods]\nimpl EqOptAndManualRichCmp {\n    fn __richcmp__(\n        &self,\n        _py: Python,\n        _other: Bound<'_, PyAny>,\n        _op: pyo3::pyclass::CompareOp,\n    ) -> PyResult<Py<PyAny>> {\n        todo!()\n    }\n}\n\n#[pyclass(eq_int)]\nstruct NoEqInt {}\n\n#[pyclass(frozen, eq, hash)]\n#[derive(PartialEq)]\nstruct HashOptRequiresHash;\n\n#[pyclass(hash)]\n#[derive(Hash)]\nstruct HashWithoutFrozenAndEq;\n\n#[pyclass(frozen, eq, hash)]\n#[derive(PartialEq, Hash)]\nstruct HashOptAndManualHash {}\n\n#[pymethods]\nimpl HashOptAndManualHash {\n    fn __hash__(&self) -> u64 {\n        todo!()\n    }\n}\n\n#[pyclass(ord)]\nstruct InvalidOrderedStruct {\n    inner: i32,\n}\n\n#[pyclass]\nstruct MultipleErrors {\n    #[pyo3(foo)]\n    #[pyo3(blah)]\n    x: i32,\n    #[pyo3(pop)]\n    y: i32,\n}\n\n#[pyclass(str)]\nstruct StrOptAndManualStr {}\n\nimpl Display for StrOptAndManualStr {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{}\", self)\n    }\n}\n\n#[pymethods]\nimpl StrOptAndManualStr {\n    fn __str__(&self) -> String {\n        todo!()\n    }\n}\n\n#[pyclass(str = \"{\")]\n#[derive(PartialEq)]\nstruct Coord(u32, u32, u32);\n\n#[pyclass(str = \"{$}\")]\n#[derive(PartialEq)]\nstruct Coord2(u32, u32, u32);\n\n#[pyclass(str = \"X: {aaaa}, Y: {y}, Z: {z}\", skip_from_py_object)]\n#[derive(PartialEq, Eq, Clone, PartialOrd)]\npub struct Point {\n    x: i32,\n    y: i32,\n    z: i32,\n}\n\n#[pyclass(str = \"X: {x}, Y: {y}}}, Z: {zzz}\", skip_from_py_object)]\n#[derive(PartialEq, Eq, Clone, PartialOrd)]\npub struct Point2 {\n    x: i32,\n    y: i32,\n    z: i32,\n}\n\n#[pyclass(str = \"{0}, {162543}, {2}\")]\n#[derive(PartialEq)]\nstruct Coord3(u32, u32, u32);\n\n#[pyclass(name = \"aaa\", str = \"unsafe: {unsafe_variable}\")]\nstruct StructRenamingWithStrFormatter {\n    #[pyo3(name = \"unsafe\", get, set)]\n    unsafe_variable: usize,\n}\n\n#[pyclass(name = \"aaa\", str = \"unsafe: {unsafe_variable}\")]\nstruct StructRenamingWithStrFormatter2 {\n    unsafe_variable: usize,\n}\n\n#[pyclass(str = \"unsafe: {unsafe_variable}\")]\nstruct StructRenamingWithStrFormatter3 {\n    #[pyo3(name = \"unsafe\", get, set)]\n    unsafe_variable: usize,\n}\n\n#[pyclass(rename_all = \"SCREAMING_SNAKE_CASE\", str = \"{a_a}, {b_b}, {c_d_e}\")]\nstruct RenameAllVariantsStruct {\n    a_a: u32,\n    b_b: u32,\n    c_d_e: String,\n}\n\n#[pyclass(str = \"{:?}\")]\n#[derive(Debug)]\nstruct StructWithNoMember {\n    a: String,\n    b: String,\n}\n\n#[pyclass(str = \"{}\")]\n#[derive(Debug)]\nstruct StructWithNoMember2 {\n    a: String,\n    b: String,\n}\n\n#[pyclass(eq, str = \"Stuff...\")]\n#[derive(Debug, PartialEq)]\npub enum MyEnumInvalidStrFmt {\n    Variant,\n    OtherVariant,\n}\n\nimpl Display for MyEnumInvalidStrFmt {\n    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {\n        write!(f, \"{:?}\", self)\n    }\n}\n\n#[pyclass(from_py_object, skip_from_py_object)]\nstruct StructTooManyFromPyObject {\n    a: String,\n    b: String,\n}\n\n#[pyclass(from_py_object)]\nstruct StructFromPyObjectNoClone {\n    a: String,\n    b: String,\n}\n\n#[pyclass]\n#[derive(Clone)]\nstruct StructImplicitFromPyObjectDeprecated {\n    a: String,\n    b: String,\n}\n\n#[pyclass(new = \"from_fields\")]\nstruct NonPythonField {\n    field: Box<dyn std::error::Error + Send + Sync>,\n}\n\n#[pyclass(new = \"from_fields\")]\nstruct NewFromFieldsWithManualNew {\n    field: i32,\n}\n\n#[pymethods]\nimpl NewFromFieldsWithManualNew {\n    #[new]\n    fn new(field: i32) -> Self {\n        Self { field }\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_args.stderr",
    "content": "error: expected one of: `crate`, `dict`, `eq`, `eq_int`, `extends`, `freelist`, `frozen`, `get_all`, `hash`, `immutable_type`, `mapping`, `module`, `name`, `ord`, `rename_all`, `sequence`, `set_all`, `new`, `str`, `subclass`, `unsendable`, `weakref`, `generic`, `from_py_object`, `skip_from_py_object`\n --> tests/ui/invalid_pyclass_args.rs:4:11\n  |\n4 | #[pyclass(extend=pyo3::types::PyDict)]\n  |           ^^^^^^\n\nerror: expected identifier\n --> tests/ui/invalid_pyclass_args.rs:7:21\n  |\n7 | #[pyclass(extends = \"PyDict\")]\n  |                     ^^^^^^^^\n\nerror: expected string literal\n  --> tests/ui/invalid_pyclass_args.rs:10:18\n   |\n10 | #[pyclass(name = m::MyClass)]\n   |                  ^\n\nerror: expected a single identifier in double quotes\n  --> tests/ui/invalid_pyclass_args.rs:13:18\n   |\n13 | #[pyclass(name = \"Custom Name\")]\n   |                  ^^^^^^^^^^^^^\n\nerror: expected string literal\n  --> tests/ui/invalid_pyclass_args.rs:16:18\n   |\n16 | #[pyclass(name = CustomName)]\n   |                  ^^^^^^^^^^\n\nerror: expected string literal\n  --> tests/ui/invalid_pyclass_args.rs:19:24\n   |\n19 | #[pyclass(rename_all = camelCase)]\n   |                        ^^^^^^^^^\n\nerror: expected a valid renaming rule, possible values are: \"camelCase\", \"kebab-case\", \"lowercase\", \"PascalCase\", \"SCREAMING-KEBAB-CASE\", \"SCREAMING_SNAKE_CASE\", \"snake_case\", \"UPPERCASE\"\n  --> tests/ui/invalid_pyclass_args.rs:22:24\n   |\n22 | #[pyclass(rename_all = \"Camel-Case\")]\n   |                        ^^^^^^^^^^^^\n\nerror: expected string literal\n  --> tests/ui/invalid_pyclass_args.rs:25:20\n   |\n25 | #[pyclass(module = my_module)]\n   |                    ^^^^^^^^^\n\nerror: expected one of: `crate`, `dict`, `eq`, `eq_int`, `extends`, `freelist`, `frozen`, `get_all`, `hash`, `immutable_type`, `mapping`, `module`, `name`, `ord`, `rename_all`, `sequence`, `set_all`, `new`, `str`, `subclass`, `unsendable`, `weakref`, `generic`, `from_py_object`, `skip_from_py_object`\n  --> tests/ui/invalid_pyclass_args.rs:28:11\n   |\n28 | #[pyclass(weakrev)]\n   |           ^^^^^^^\n\nerror: a `#[pyclass]` cannot be both a `mapping` and a `sequence`\n  --> tests/ui/invalid_pyclass_args.rs:32:8\n   |\n32 | struct CannotBeMappingAndSequence {}\n   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: `eq_int` can only be used on simple enums.\n  --> tests/ui/invalid_pyclass_args.rs:53:11\n   |\n53 | #[pyclass(eq_int)]\n   |           ^^^^^^\n\nerror: The `hash` option requires the `frozen` option.\n  --> tests/ui/invalid_pyclass_args.rs:60:11\n   |\n60 | #[pyclass(hash)]\n   |           ^^^^\n\nerror: The `hash` option requires the `eq` option.\n  --> tests/ui/invalid_pyclass_args.rs:60:11\n   |\n60 | #[pyclass(hash)]\n   |           ^^^^\n\nerror: The `ord` option requires the `eq` option.\n  --> tests/ui/invalid_pyclass_args.rs:75:11\n   |\n75 | #[pyclass(ord)]\n   |           ^^^\n\nerror: expected one of: `get`, `set`, `name`\n  --> tests/ui/invalid_pyclass_args.rs:82:12\n   |\n82 |     #[pyo3(foo)]\n   |            ^^^\n\nerror: expected one of: `get`, `set`, `name`\n  --> tests/ui/invalid_pyclass_args.rs:83:12\n   |\n83 |     #[pyo3(blah)]\n   |            ^^^^\n\nerror: expected one of: `get`, `set`, `name`\n  --> tests/ui/invalid_pyclass_args.rs:85:12\n   |\n85 |     #[pyo3(pop)]\n   |            ^^^\n\nerror: invalid format string: expected `}` but string was terminated\n   --> tests/ui/invalid_pyclass_args.rs:105:19\n    |\n105 | #[pyclass(str = \"{\")]\n    |                  -^ expected `}` in format string\n    |                  |\n    |                  because of this opening brace\n    |\n    = note: if you intended to print `{`, you can escape it using `{{`\n\nerror: invalid format string: expected `}`, found `$`\n   --> tests/ui/invalid_pyclass_args.rs:109:19\n    |\n109 | #[pyclass(str = \"{$}\")]\n    |                  -^ expected `}` in format string\n    |                  |\n    |                  because of this opening brace\n    |\n    = note: if you intended to print `{`, you can escape it using `{{`\n\nerror: The format string syntax is incompatible with any renaming via `name` or `rename_all`\n   --> tests/ui/invalid_pyclass_args.rs:133:31\n    |\n133 | #[pyclass(name = \"aaa\", str = \"unsafe: {unsafe_variable}\")]\n    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: The format string syntax is incompatible with any renaming via `name` or `rename_all`\n   --> tests/ui/invalid_pyclass_args.rs:139:31\n    |\n139 | #[pyclass(name = \"aaa\", str = \"unsafe: {unsafe_variable}\")]\n    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: The format string syntax is incompatible with any renaming via `name` or `rename_all`\n   --> tests/ui/invalid_pyclass_args.rs:144:17\n    |\n144 | #[pyclass(str = \"unsafe: {unsafe_variable}\")]\n    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: The format string syntax is incompatible with any renaming via `name` or `rename_all`\n   --> tests/ui/invalid_pyclass_args.rs:150:54\n    |\n150 | #[pyclass(rename_all = \"SCREAMING_SNAKE_CASE\", str = \"{a_a}, {b_b}, {c_d_e}\")]\n    |                                                      ^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: No member found, you must provide a named or positionally specified member.\n   --> tests/ui/invalid_pyclass_args.rs:157:17\n    |\n157 | #[pyclass(str = \"{:?}\")]\n    |                 ^^^^^^\n\nerror: No member found, you must provide a named or positionally specified member.\n   --> tests/ui/invalid_pyclass_args.rs:164:17\n    |\n164 | #[pyclass(str = \"{}\")]\n    |                 ^^^^\n\nerror: The format string syntax cannot be used with enums\n   --> tests/ui/invalid_pyclass_args.rs:171:21\n    |\n171 | #[pyclass(eq, str = \"Stuff...\")]\n    |                     ^^^^^^^^^^\n\nerror: `skip_from_py_object` and `from_py_object` are mutually exclusive\n   --> tests/ui/invalid_pyclass_args.rs:184:27\n    |\n184 | #[pyclass(from_py_object, skip_from_py_object)]\n    |                           ^^^^^^^^^^^^^^^^^^^\n\nerror[E0277]: the trait bound `StructFromPyObjectNoClone: Clone` is not satisfied\n   --> tests/ui/invalid_pyclass_args.rs:190:11\n    |\n190 | #[pyclass(from_py_object)]\n    |           ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `StructFromPyObjectNoClone`\n    |\n    = help: see issue #48214\nhelp: consider annotating `StructFromPyObjectNoClone` with `#[derive(Clone)]`\n    |\n191 + #[derive(Clone)]\n192 | struct StructFromPyObjectNoClone {\n    |\n\nerror[E0119]: conflicting implementations of trait `PyClassNewTextSignature` for type `NewFromFieldsWithManualNew`\n   --> tests/ui/invalid_pyclass_args.rs:213:1\n    |\n208 | #[pyclass(new = \"from_fields\")]\n    | ------------------------------- first implementation here\n...\n213 | #[pymethods]\n    | ^^^^^^^^^^^^ conflicting implementation for `NewFromFieldsWithManualNew`\n    |\n    = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: `Box<dyn std::error::Error + Send + Sync>` cannot be used as a Python function argument\n   --> tests/ui/invalid_pyclass_args.rs:205:12\n    |\n205 |     field: Box<dyn std::error::Error + Send + Sync>,\n    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `PyFunctionArgument<'_, '_, '_, false>` is not implemented for `Box<dyn std::error::Error + Send + Sync>`\n    |\n    = note: implement `FromPyObject` to enable using `Box<dyn std::error::Error + Send + Sync>` as a function argument\n    = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]`\nhelp: the following other types implement trait `PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>`\n   --> src/impl_/extract_argument.rs\n    |\n    | / impl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false>\n    | |     for &'holder Bound<'py, T>\n    | | where\n    | |     T: PyTypeCheck,\n    | |___________________^ `&'holder pyo3::Bound<'py, T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n...\n    | / impl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option<T>\n    | | where\n    | |     T: PyFunctionArgument<'a, 'holder, 'py, false>,\n    | |___________________________________________________^ `Option<T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n...\n    |   impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T {\n    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'holder T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n...\n    | / impl<'a, 'holder, T: PyClass<Frozen = False>> PyFunctionArgument<'a, 'holder, '_, false>\n    | |     for &'holder mut T\n    | |______________________^ `&'holder mut T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n\nerror[E0592]: duplicate definitions with name `__pymethod___richcmp____`\n  --> tests/ui/invalid_pyclass_args.rs:37:1\n   |\n37 | #[pyclass(eq)]\n   | ^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___richcmp____`\n...\n41 | #[pymethods]\n   | ------------ other definition for `__pymethod___richcmp____`\n   |\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0592]: duplicate definitions with name `__pymethod___hash____`\n  --> tests/ui/invalid_pyclass_args.rs:64:1\n   |\n64 | #[pyclass(frozen, eq, hash)]\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___hash____`\n...\n68 | #[pymethods]\n   | ------------ other definition for `__pymethod___hash____`\n   |\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0592]: duplicate definitions with name `__pymethod___str____`\n  --> tests/ui/invalid_pyclass_args.rs:89:1\n   |\n89 | #[pyclass(str)]\n   | ^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___str____`\n...\n98 | #[pymethods]\n   | ------------ other definition for `__pymethod___str____`\n   |\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0592]: duplicate definitions with name `__pymethod___new____`\n   --> tests/ui/invalid_pyclass_args.rs:208:1\n    |\n208 | #[pyclass(new = \"from_fields\")]\n    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___new____`\n...\n213 | #[pymethods]\n    | ------------ other definition for `__pymethod___new____`\n    |\n    = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0369]: binary operation `==` cannot be applied to type `&EqOptRequiresEq`\n  --> tests/ui/invalid_pyclass_args.rs:34:11\n   |\n34 | #[pyclass(eq)]\n   |           ^^\n   |\nnote: an implementation of `PartialEq` might be missing for `EqOptRequiresEq`\n  --> tests/ui/invalid_pyclass_args.rs:35:1\n   |\n35 | struct EqOptRequiresEq {}\n   | ^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq`\nhelp: consider annotating `EqOptRequiresEq` with `#[derive(PartialEq)]`\n   |\n35 + #[derive(PartialEq)]\n36 | struct EqOptRequiresEq {}\n   |\n\nerror[E0369]: binary operation `!=` cannot be applied to type `&EqOptRequiresEq`\n  --> tests/ui/invalid_pyclass_args.rs:34:11\n   |\n34 | #[pyclass(eq)]\n   |           ^^\n   |\nnote: an implementation of `PartialEq` might be missing for `EqOptRequiresEq`\n  --> tests/ui/invalid_pyclass_args.rs:35:1\n   |\n35 | struct EqOptRequiresEq {}\n   | ^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq`\nhelp: consider annotating `EqOptRequiresEq` with `#[derive(PartialEq)]`\n   |\n35 + #[derive(PartialEq)]\n36 | struct EqOptRequiresEq {}\n   |\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_pyclass_args.rs:37:1\n   |\n37 | #[pyclass(eq)]\n   | ^^^^^^^^^^^^^^ multiple `__pymethod___richcmp____` found\n   |\nnote: candidate #1 is defined in an impl for the type `EqOptAndManualRichCmp`\n  --> tests/ui/invalid_pyclass_args.rs:37:1\n   |\n37 | #[pyclass(eq)]\n   | ^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `EqOptAndManualRichCmp`\n  --> tests/ui/invalid_pyclass_args.rs:41:1\n   |\n41 | #[pymethods]\n   | ^^^^^^^^^^^^\n   = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_pyclass_args.rs:41:1\n   |\n41 | #[pymethods]\n   | ^^^^^^^^^^^^ multiple `__pymethod___richcmp____` found\n   |\nnote: candidate #1 is defined in an impl for the type `EqOptAndManualRichCmp`\n  --> tests/ui/invalid_pyclass_args.rs:37:1\n   |\n37 | #[pyclass(eq)]\n   | ^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `EqOptAndManualRichCmp`\n  --> tests/ui/invalid_pyclass_args.rs:41:1\n   |\n41 | #[pymethods]\n   | ^^^^^^^^^^^^\n   = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: the trait bound `HashOptRequiresHash: Hash` is not satisfied\n  --> tests/ui/invalid_pyclass_args.rs:56:23\n   |\n56 | #[pyclass(frozen, eq, hash)]\n   |                       ^^^^ the trait `Hash` is not implemented for `HashOptRequiresHash`\n   |\nhelp: consider annotating `HashOptRequiresHash` with `#[derive(Hash)]`\n   |\n58 + #[derive(Hash)]\n59 | struct HashOptRequiresHash;\n   |\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_pyclass_args.rs:64:1\n   |\n64 | #[pyclass(frozen, eq, hash)]\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `__pymethod___hash____` found\n   |\nnote: candidate #1 is defined in an impl for the type `HashOptAndManualHash`\n  --> tests/ui/invalid_pyclass_args.rs:64:1\n   |\n64 | #[pyclass(frozen, eq, hash)]\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `HashOptAndManualHash`\n  --> tests/ui/invalid_pyclass_args.rs:68:1\n   |\n68 | #[pymethods]\n   | ^^^^^^^^^^^^\n   = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_pyclass_args.rs:68:1\n   |\n68 | #[pymethods]\n   | ^^^^^^^^^^^^ multiple `__pymethod___hash____` found\n   |\nnote: candidate #1 is defined in an impl for the type `HashOptAndManualHash`\n  --> tests/ui/invalid_pyclass_args.rs:64:1\n   |\n64 | #[pyclass(frozen, eq, hash)]\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `HashOptAndManualHash`\n  --> tests/ui/invalid_pyclass_args.rs:68:1\n   |\n68 | #[pymethods]\n   | ^^^^^^^^^^^^\n   = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_pyclass_args.rs:89:1\n   |\n89 | #[pyclass(str)]\n   | ^^^^^^^^^^^^^^^ multiple `__pymethod___str____` found\n   |\nnote: candidate #1 is defined in an impl for the type `StrOptAndManualStr`\n  --> tests/ui/invalid_pyclass_args.rs:89:1\n   |\n89 | #[pyclass(str)]\n   | ^^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `StrOptAndManualStr`\n  --> tests/ui/invalid_pyclass_args.rs:98:1\n   |\n98 | #[pymethods]\n   | ^^^^^^^^^^^^\n   = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_pyclass_args.rs:98:1\n   |\n98 | #[pymethods]\n   | ^^^^^^^^^^^^ multiple `__pymethod___str____` found\n   |\nnote: candidate #1 is defined in an impl for the type `StrOptAndManualStr`\n  --> tests/ui/invalid_pyclass_args.rs:89:1\n   |\n89 | #[pyclass(str)]\n   | ^^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `StrOptAndManualStr`\n  --> tests/ui/invalid_pyclass_args.rs:98:1\n   |\n98 | #[pymethods]\n   | ^^^^^^^^^^^^\n   = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0609]: no field `aaaa` on type `&Point`\n   --> tests/ui/invalid_pyclass_args.rs:113:17\n    |\n113 | #[pyclass(str = \"X: {aaaa}, Y: {y}, Z: {z}\", skip_from_py_object)]\n    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown field\n    |\n    = note: available fields are: `x`, `y`, `z`\n\nerror[E0609]: no field `zzz` on type `&Point2`\n   --> tests/ui/invalid_pyclass_args.rs:121:17\n    |\n121 | #[pyclass(str = \"X: {x}, Y: {y}}}, Z: {zzz}\", skip_from_py_object)]\n    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown field\n    |\n    = note: available fields are: `x`, `y`, `z`\n\nerror[E0609]: no field `162543` on type `&Coord3`\n   --> tests/ui/invalid_pyclass_args.rs:129:17\n    |\n129 | #[pyclass(str = \"{0}, {162543}, {2}\")]\n    |                 ^^^^^^^^^^^^^^^^^^^^ unknown field\n    |\n    = note: available fields are: `0`, `1`, `2`\n\nwarning: use of deprecated associated constant `pyo3::impl_::deprecated::HasAutomaticFromPyObject::<true>::MSG`: The `FromPyObject` implementation for `#[pyclass]` types which implement `Clone` is changing to an opt-in option. Use `#[pyclass(from_py_object)]` to opt-in to the `FromPyObject` derive now, or `#[pyclass(skip_from_py_object)]` to skip the `FromPyObject` implementation.\n   --> tests/ui/invalid_pyclass_args.rs:196:1\n    |\n196 | #[pyclass]\n    | ^^^^^^^^^^\n    |\n    = note: `#[warn(deprecated)]` on by default\n    = note: this warning originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: `Box<dyn std::error::Error + Send + Sync>` cannot be used as a Python function argument\n   --> tests/ui/invalid_pyclass_args.rs:205:12\n    |\n205 |     field: Box<dyn std::error::Error + Send + Sync>,\n    |            ^^^ the trait `pyo3::PyClass` is not implemented for `Box<dyn std::error::Error + Send + Sync>`\n    |\n    = note: implement `FromPyObject` to enable using `Box<dyn std::error::Error + Send + Sync>` as a function argument\n    = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]`\n    = help: the following other types implement trait `pyo3::PyClass`:\n              Coord\n              Coord2\n              Coord3\n              EqOptAndManualRichCmp\n              EqOptRequiresEq\n              HashOptAndManualHash\n              HashOptRequiresHash\n              NewFromFieldsWithManualNew\n            and $N others\n    = note: required for `Box<dyn std::error::Error + Send + Sync>` to implement `pyo3::FromPyObject<'_, '_>`\n    = note: required for `Box<dyn std::error::Error + Send + Sync>` to implement `PyFunctionArgument<'_, '_, '_, true>`\nnote: required by a bound in `extract_argument`\n   --> src/impl_/extract_argument.rs\n    |\n    | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>(\n    |        ---------------- required by a bound in this function\n...\n    |     T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>,\n    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument`\n\nerror[E0277]: `Box<dyn std::error::Error + Send + Sync>` cannot be used as a Python function argument\n   --> tests/ui/invalid_pyclass_args.rs:205:12\n    |\n205 |     field: Box<dyn std::error::Error + Send + Sync>,\n    |            ^^^ the trait `ExtractPyClassWithClone` is not implemented for `Box<dyn std::error::Error + Send + Sync>`\n    |\n    = note: implement `FromPyObject` to enable using `Box<dyn std::error::Error + Send + Sync>` as a function argument\n    = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]`\n    = help: the following other types implement trait `ExtractPyClassWithClone`:\n              Coord\n              Coord2\n              Coord3\n              EqOptAndManualRichCmp\n              EqOptRequiresEq\n              HashOptAndManualHash\n              HashOptRequiresHash\n              NewFromFieldsWithManualNew\n            and $N others\n    = note: required for `Box<dyn std::error::Error + Send + Sync>` to implement `pyo3::FromPyObject<'_, '_>`\n    = note: required for `Box<dyn std::error::Error + Send + Sync>` to implement `PyFunctionArgument<'_, '_, '_, true>`\nnote: required by a bound in `extract_argument`\n   --> src/impl_/extract_argument.rs\n    |\n    | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>(\n    |        ---------------- required by a bound in this function\n...\n    |     T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>,\n    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument`\n\nerror[E0277]: the trait bound `dyn std::error::Error + Send + Sync: Clone` is not satisfied\n   --> tests/ui/invalid_pyclass_args.rs:205:12\n    |\n205 |     field: Box<dyn std::error::Error + Send + Sync>,\n    |            ^^^ the trait `Clone` is not implemented for `dyn std::error::Error + Send + Sync`\n    |\nhelp: the following other types implement trait `PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>`\n   --> src/impl_/extract_argument.rs\n    |\n    | / impl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false>\n    | |     for &'holder Bound<'py, T>\n    | | where\n    | |     T: PyTypeCheck,\n    | |___________________^ `&'holder pyo3::Bound<'py, T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n...\n    | / impl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option<T>\n    | | where\n    | |     T: PyFunctionArgument<'a, 'holder, 'py, false>,\n    | |___________________________________________________^ `Option<T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n...\n    |   impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T {\n    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'holder T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n...\n    | / impl<'a, 'holder, T: PyClass<Frozen = False>> PyFunctionArgument<'a, 'holder, '_, false>\n    | |     for &'holder mut T\n    | |______________________^ `&'holder mut T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n    = note: required for `Box<dyn std::error::Error + Send + Sync>` to implement `Clone`\n    = note: required for `Box<dyn std::error::Error + Send + Sync>` to implement `pyo3::FromPyObject<'_, '_>`\n    = note: required for `Box<dyn std::error::Error + Send + Sync>` to implement `PyFunctionArgument<'_, '_, '_, true>`\nnote: required by a bound in `extract_argument`\n   --> src/impl_/extract_argument.rs\n    |\n    | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>(\n    |        ---------------- required by a bound in this function\n...\n    |     T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>,\n    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument`\n\nerror[E0034]: multiple applicable items in scope\n   --> tests/ui/invalid_pyclass_args.rs:208:1\n    |\n208 | #[pyclass(new = \"from_fields\")]\n    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ multiple `__pymethod___new____` found\n    |\nnote: candidate #1 is defined in an impl for the type `NewFromFieldsWithManualNew`\n   --> tests/ui/invalid_pyclass_args.rs:208:1\n    |\n208 | #[pyclass(new = \"from_fields\")]\n    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `NewFromFieldsWithManualNew`\n   --> tests/ui/invalid_pyclass_args.rs:213:1\n    |\n213 | #[pymethods]\n    | ^^^^^^^^^^^^\n    = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n   --> tests/ui/invalid_pyclass_args.rs:213:1\n    |\n213 | #[pymethods]\n    | ^^^^^^^^^^^^ multiple `__pymethod___new____` found\n    |\nnote: candidate #1 is defined in an impl for the type `NewFromFieldsWithManualNew`\n   --> tests/ui/invalid_pyclass_args.rs:208:1\n    |\n208 | #[pyclass(new = \"from_fields\")]\n    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `NewFromFieldsWithManualNew`\n   --> tests/ui/invalid_pyclass_args.rs:213:1\n    |\n213 | #[pymethods]\n    | ^^^^^^^^^^^^\n    = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_doc.rs",
    "content": "use pyo3::prelude::*;\n\n#[doc = \"This \\0 contains a nul byte!\"]\n#[pyclass]\nstruct InvalidDocWithNulByte {}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_doc.stderr",
    "content": "error: Python doc may not contain nul byte, found nul at position 5\n --> tests/ui/invalid_pyclass_doc.rs:3:9\n  |\n3 | #[doc = \"This \\0 contains a nul byte!\"]\n  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_enum.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass(subclass)]\nenum NotBaseClass {\n    X,\n    Y,\n}\n\n#[pyclass(extends = PyList)]\nenum NotDerivedClass {\n    X,\n    Y,\n}\n\n#[pyclass]\nenum NoEmptyEnum {}\n\n#[pyclass]\nenum NoUnitVariants {\n    StructVariant { field: i32 },\n    UnitVariant,\n}\n\n#[pyclass]\nenum SimpleNoSignature {\n    #[pyo3(constructor = (a, b))]\n    A,\n    B,\n}\n\n#[pyclass(eq, eq_int)]\nenum SimpleEqOptRequiresPartialEq {\n    A,\n    B,\n}\n\n#[pyclass(eq)]\nenum ComplexEqOptRequiresPartialEq {\n    A(i32),\n    B { msg: String },\n}\n\n#[pyclass(eq_int)]\nenum SimpleEqIntWithoutEq {\n    A,\n    B,\n}\n\n#[pyclass(eq_int)]\nenum NoEqInt {\n    A(i32),\n    B { msg: String },\n}\n\n#[pyclass(frozen, eq, eq_int, hash)]\n#[derive(PartialEq)]\nenum SimpleHashOptRequiresHash {\n    A,\n    B,\n}\n\n#[pyclass(frozen, eq, hash)]\n#[derive(PartialEq)]\nenum ComplexHashOptRequiresHash {\n    A(i32),\n    B { msg: String },\n}\n\n#[pyclass(hash)]\n#[derive(Hash)]\nenum SimpleHashOptRequiresFrozenAndEq {\n    A,\n    B,\n}\n\n#[pyclass(hash)]\n#[derive(Hash)]\nenum ComplexHashOptRequiresEq {\n    A(i32),\n    B { msg: String },\n}\n\n#[pyclass(ord)]\nenum InvalidOrderedComplexEnum {\n    VariantA (i32),\n    VariantB { msg: String }\n}\n\n#[pyclass(eq,ord)]\n#[derive(PartialEq)]\nenum InvalidOrderedComplexEnum2 {\n    VariantA (i32),\n    VariantB { msg: String }\n}\n\n#[pyclass(eq)]\n#[derive(PartialEq)]\nenum AllEnumVariantsDisabled {\n    #[cfg(any())]\n    DisabledA,\n    #[cfg(not(all()))]\n    DisabledB,\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_enum.stderr",
    "content": "error: enums can't be inherited by other classes\n --> tests/ui/invalid_pyclass_enum.rs:3:11\n  |\n3 | #[pyclass(subclass)]\n  |           ^^^^^^^^\n\nerror: enums can't extend from other classes\n --> tests/ui/invalid_pyclass_enum.rs:9:11\n  |\n9 | #[pyclass(extends = PyList)]\n  |           ^^^^^^^\n\nerror: #[pyclass] can't be used on enums without any variants\n  --> tests/ui/invalid_pyclass_enum.rs:16:18\n   |\n16 | enum NoEmptyEnum {}\n   |                  ^^\n\nerror: Unit variant `UnitVariant` is not yet supported in a complex enum\n       = help: change to an empty tuple variant instead: `UnitVariant()`\n       = note: the enum is complex because of non-unit variant `StructVariant`\n  --> tests/ui/invalid_pyclass_enum.rs:21:5\n   |\n21 |     UnitVariant,\n   |     ^^^^^^^^^^^\n\nerror: `constructor` can't be used on a simple enum variant\n  --> tests/ui/invalid_pyclass_enum.rs:26:12\n   |\n26 |     #[pyo3(constructor = (a, b))]\n   |            ^^^^^^^^^^^\n\nerror: The `eq_int` option requires the `eq` option.\n  --> tests/ui/invalid_pyclass_enum.rs:43:11\n   |\n43 | #[pyclass(eq_int)]\n   |           ^^^^^^\n\nerror: `eq_int` can only be used on simple enums.\n  --> tests/ui/invalid_pyclass_enum.rs:49:11\n   |\n49 | #[pyclass(eq_int)]\n   |           ^^^^^^\n\nerror: The `hash` option requires the `frozen` option.\n  --> tests/ui/invalid_pyclass_enum.rs:69:11\n   |\n69 | #[pyclass(hash)]\n   |           ^^^^\n\nerror: The `hash` option requires the `eq` option.\n  --> tests/ui/invalid_pyclass_enum.rs:69:11\n   |\n69 | #[pyclass(hash)]\n   |           ^^^^\n\nerror: The `hash` option requires the `eq` option.\n  --> tests/ui/invalid_pyclass_enum.rs:76:11\n   |\n76 | #[pyclass(hash)]\n   |           ^^^^\n\nerror: The `ord` option requires the `eq` option.\n  --> tests/ui/invalid_pyclass_enum.rs:83:11\n   |\n83 | #[pyclass(ord)]\n   |           ^^^\n\nerror: #[pyclass] can't be used on enums without any variants - all variants of enum `AllEnumVariantsDisabled` have been configured out by cfg attributes\n  --> tests/ui/invalid_pyclass_enum.rs:98:6\n   |\n98 | enum AllEnumVariantsDisabled {\n   |      ^^^^^^^^^^^^^^^^^^^^^^^\n\nerror[E0369]: binary operation `==` cannot be applied to type `&SimpleEqOptRequiresPartialEq`\n  --> tests/ui/invalid_pyclass_enum.rs:31:11\n   |\n31 | #[pyclass(eq, eq_int)]\n   |           ^^\n   |\nnote: an implementation of `PartialEq` might be missing for `SimpleEqOptRequiresPartialEq`\n  --> tests/ui/invalid_pyclass_enum.rs:32:1\n   |\n32 | enum SimpleEqOptRequiresPartialEq {\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq`\nhelp: consider annotating `SimpleEqOptRequiresPartialEq` with `#[derive(PartialEq)]`\n   |\n32 + #[derive(PartialEq)]\n33 | enum SimpleEqOptRequiresPartialEq {\n   |\n\nerror[E0369]: binary operation `!=` cannot be applied to type `&SimpleEqOptRequiresPartialEq`\n  --> tests/ui/invalid_pyclass_enum.rs:31:11\n   |\n31 | #[pyclass(eq, eq_int)]\n   |           ^^\n   |\nnote: an implementation of `PartialEq` might be missing for `SimpleEqOptRequiresPartialEq`\n  --> tests/ui/invalid_pyclass_enum.rs:32:1\n   |\n32 | enum SimpleEqOptRequiresPartialEq {\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq`\nhelp: consider annotating `SimpleEqOptRequiresPartialEq` with `#[derive(PartialEq)]`\n   |\n32 + #[derive(PartialEq)]\n33 | enum SimpleEqOptRequiresPartialEq {\n   |\n\nerror[E0369]: binary operation `==` cannot be applied to type `&ComplexEqOptRequiresPartialEq`\n  --> tests/ui/invalid_pyclass_enum.rs:37:11\n   |\n37 | #[pyclass(eq)]\n   |           ^^\n   |\nnote: an implementation of `PartialEq` might be missing for `ComplexEqOptRequiresPartialEq`\n  --> tests/ui/invalid_pyclass_enum.rs:38:1\n   |\n38 | enum ComplexEqOptRequiresPartialEq {\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq`\nhelp: consider annotating `ComplexEqOptRequiresPartialEq` with `#[derive(PartialEq)]`\n   |\n38 + #[derive(PartialEq)]\n39 | enum ComplexEqOptRequiresPartialEq {\n   |\n\nerror[E0369]: binary operation `!=` cannot be applied to type `&ComplexEqOptRequiresPartialEq`\n  --> tests/ui/invalid_pyclass_enum.rs:37:11\n   |\n37 | #[pyclass(eq)]\n   |           ^^\n   |\nnote: an implementation of `PartialEq` might be missing for `ComplexEqOptRequiresPartialEq`\n  --> tests/ui/invalid_pyclass_enum.rs:38:1\n   |\n38 | enum ComplexEqOptRequiresPartialEq {\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialEq`\nhelp: consider annotating `ComplexEqOptRequiresPartialEq` with `#[derive(PartialEq)]`\n   |\n38 + #[derive(PartialEq)]\n39 | enum ComplexEqOptRequiresPartialEq {\n   |\n\nerror[E0277]: the trait bound `SimpleHashOptRequiresHash: Hash` is not satisfied\n  --> tests/ui/invalid_pyclass_enum.rs:55:31\n   |\n55 | #[pyclass(frozen, eq, eq_int, hash)]\n   |                               ^^^^ the trait `Hash` is not implemented for `SimpleHashOptRequiresHash`\n   |\nhelp: consider annotating `SimpleHashOptRequiresHash` with `#[derive(Hash)]`\n   |\n57 + #[derive(Hash)]\n58 | enum SimpleHashOptRequiresHash {\n   |\n\nerror[E0277]: the trait bound `ComplexHashOptRequiresHash: Hash` is not satisfied\n  --> tests/ui/invalid_pyclass_enum.rs:62:23\n   |\n62 | #[pyclass(frozen, eq, hash)]\n   |                       ^^^^ the trait `Hash` is not implemented for `ComplexHashOptRequiresHash`\n   |\nhelp: consider annotating `ComplexHashOptRequiresHash` with `#[derive(Hash)]`\n   |\n64 + #[derive(Hash)]\n65 | enum ComplexHashOptRequiresHash {\n   |\n\nerror[E0369]: binary operation `>` cannot be applied to type `&InvalidOrderedComplexEnum2`\n  --> tests/ui/invalid_pyclass_enum.rs:89:14\n   |\n89 | #[pyclass(eq,ord)]\n   |              ^^^\n   |\nnote: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2`\n  --> tests/ui/invalid_pyclass_enum.rs:91:1\n   |\n91 | enum InvalidOrderedComplexEnum2 {\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd`\nhelp: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]`\n   |\n91 + #[derive(PartialEq, PartialOrd)]\n92 | enum InvalidOrderedComplexEnum2 {\n   |\n\nerror[E0369]: binary operation `<` cannot be applied to type `&InvalidOrderedComplexEnum2`\n  --> tests/ui/invalid_pyclass_enum.rs:89:14\n   |\n89 | #[pyclass(eq,ord)]\n   |              ^^^\n   |\nnote: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2`\n  --> tests/ui/invalid_pyclass_enum.rs:91:1\n   |\n91 | enum InvalidOrderedComplexEnum2 {\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd`\nhelp: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]`\n   |\n91 + #[derive(PartialEq, PartialOrd)]\n92 | enum InvalidOrderedComplexEnum2 {\n   |\n\nerror[E0369]: binary operation `<=` cannot be applied to type `&InvalidOrderedComplexEnum2`\n  --> tests/ui/invalid_pyclass_enum.rs:89:14\n   |\n89 | #[pyclass(eq,ord)]\n   |              ^^^\n   |\nnote: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2`\n  --> tests/ui/invalid_pyclass_enum.rs:91:1\n   |\n91 | enum InvalidOrderedComplexEnum2 {\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd`\nhelp: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]`\n   |\n91 + #[derive(PartialEq, PartialOrd)]\n92 | enum InvalidOrderedComplexEnum2 {\n   |\n\nerror[E0369]: binary operation `>=` cannot be applied to type `&InvalidOrderedComplexEnum2`\n  --> tests/ui/invalid_pyclass_enum.rs:89:14\n   |\n89 | #[pyclass(eq,ord)]\n   |              ^^^\n   |\nnote: an implementation of `PartialOrd` might be missing for `InvalidOrderedComplexEnum2`\n  --> tests/ui/invalid_pyclass_enum.rs:91:1\n   |\n91 | enum InvalidOrderedComplexEnum2 {\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ must implement `PartialOrd`\nhelp: consider annotating `InvalidOrderedComplexEnum2` with `#[derive(PartialEq, PartialOrd)]`\n   |\n91 + #[derive(PartialEq, PartialOrd)]\n92 | enum InvalidOrderedComplexEnum2 {\n   |\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_generic.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::PyType;\n\n#[pyclass(generic)]\nstruct ClassRedefinesClassGetItem {}\n\n#[pymethods]\nimpl ClassRedefinesClassGetItem {\n    #[new]\n    fn new() -> ClassRedefinesClassGetItem {\n        Self {}\n    }\n\n    #[classmethod]\n    pub fn __class_getitem__(\n        cls: &Bound<'_, PyType>,\n        key: &Bound<'_, PyAny>,\n    ) -> PyResult<Py<PyAny>> {\n        pyo3::types::PyGenericAlias::new(cls.py(), cls.as_any(), key)\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_generic.stderr",
    "content": "error[E0592]: duplicate definitions with name `__pymethod___class_getitem____`\n --> tests/ui/invalid_pyclass_generic.rs:4:1\n  |\n4 | #[pyclass(generic)]\n  | ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `__pymethod___class_getitem____`\n...\n7 | #[pymethods]\n  | ------------ other definition for `__pymethod___class_getitem____`\n  |\n  = note: this error originates in the macro `::pyo3::impl_::pymethods::maybe_define_fastcall_function_with_keywords` which comes from the expansion of the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0592]: duplicate definitions with name `__class_getitem__`\n  --> tests/ui/invalid_pyclass_generic.rs:4:1\n   |\n 4 |   #[pyclass(generic)]\n   |   ^^^^^^^^^^^^^^^^^^^ duplicate definitions for `__class_getitem__`\n...\n15 | /     pub fn __class_getitem__(\n16 | |         cls: &Bound<'_, PyType>,\n17 | |         key: &Bound<'_, PyAny>,\n18 | |     ) -> PyResult<Py<PyAny>> {\n   | |____________________________- other definition for `__class_getitem__`\n   |\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n --> tests/ui/invalid_pyclass_generic.rs:4:1\n  |\n4 | #[pyclass(generic)]\n  | ^^^^^^^^^^^^^^^^^^^ multiple `__pymethod___class_getitem____` found\n  |\nnote: candidate #1 is defined in an impl for the type `ClassRedefinesClassGetItem`\n --> tests/ui/invalid_pyclass_generic.rs:4:1\n  |\n4 | #[pyclass(generic)]\n  | ^^^^^^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `ClassRedefinesClassGetItem`\n --> tests/ui/invalid_pyclass_generic.rs:7:1\n  |\n7 | #[pymethods]\n  | ^^^^^^^^^^^^\n  = note: this error originates in the attribute macro `pyclass` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_pyclass_generic.rs:4:1\n   |\n 4 | #[pyclass(generic)]\n   | ^^^^^^^^^^^^^^^^^^^ multiple `__class_getitem__` found\n   |\nnote: candidate #1 is defined in an impl for the type `ClassRedefinesClassGetItem`\n  --> tests/ui/invalid_pyclass_generic.rs:4:1\n   |\n 4 | #[pyclass(generic)]\n   | ^^^^^^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `ClassRedefinesClassGetItem`\n  --> tests/ui/invalid_pyclass_generic.rs:15:5\n   |\n15 | /     pub fn __class_getitem__(\n16 | |         cls: &Bound<'_, PyType>,\n17 | |         key: &Bound<'_, PyAny>,\n18 | |     ) -> PyResult<Py<PyAny>> {\n   | |____________________________^\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n --> tests/ui/invalid_pyclass_generic.rs:4:1\n  |\n4 | #[pyclass(generic)]\n  | ^^^^^^^^^^^^^^^^^^^ multiple `wrap` found\n  |\n  = note: candidate #1 is defined in an impl for the type `IntoPyObjectConverter<Result<T, E>>`\n  = note: candidate #2 is defined in an impl for the type `IntoPyObjectConverter<T>`\n  = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0308]: mismatched types\n  --> tests/ui/invalid_pyclass_generic.rs:19:9\n   |\n18 |     ) -> PyResult<Py<PyAny>> {\n   |          ------------------- expected `Result<pyo3::Py<pyo3::PyAny>, PyErr>` because of return type\n19 |         pyo3::types::PyGenericAlias::new(cls.py(), cls.as_any(), key)\n   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result<Py<PyAny>, PyErr>`, found `Result<Bound<'_, PyGenericAlias>, PyErr>`\n   |\n   = note: expected enum `Result<pyo3::Py<pyo3::PyAny>, PyErr>`\n              found enum `Result<pyo3::Bound<'_, PyGenericAlias>, PyErr>`\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_pyclass_generic.rs:15:12\n   |\n15 |     pub fn __class_getitem__(\n   |            ^^^^^^^^^^^^^^^^^ multiple `__pymethod___class_getitem____` found\n   |\nnote: candidate #1 is defined in an impl for the type `ClassRedefinesClassGetItem`\n  --> tests/ui/invalid_pyclass_generic.rs:4:1\n   |\n 4 | #[pyclass(generic)]\n   | ^^^^^^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `ClassRedefinesClassGetItem`\n  --> tests/ui/invalid_pyclass_generic.rs:7:1\n   |\n 7 | #[pymethods]\n   | ^^^^^^^^^^^^\n   = note: this error originates in the macro `::pyo3::impl_::pymethods::maybe_define_fastcall_function_with_keywords` which comes from the expansion of the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_pyclass_generic.rs:15:12\n   |\n15 |     pub fn __class_getitem__(\n   |            ^^^^^^^^^^^^^^^^^ multiple `__class_getitem__` found\n   |\nnote: candidate #1 is defined in an impl for the type `ClassRedefinesClassGetItem`\n  --> tests/ui/invalid_pyclass_generic.rs:4:1\n   |\n 4 | #[pyclass(generic)]\n   | ^^^^^^^^^^^^^^^^^^^\nnote: candidate #2 is defined in an impl for the type `ClassRedefinesClassGetItem`\n  --> tests/ui/invalid_pyclass_generic.rs:15:5\n   |\n15 | /     pub fn __class_getitem__(\n16 | |         cls: &Bound<'_, PyType>,\n17 | |         key: &Bound<'_, PyAny>,\n18 | |     ) -> PyResult<Py<PyAny>> {\n   | |____________________________^\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0034]: multiple applicable items in scope\n  --> tests/ui/invalid_pyclass_generic.rs:18:10\n   |\n18 |     ) -> PyResult<Py<PyAny>> {\n   |          ^^^^^^^^ multiple `wrap` found\n   |\n   = note: candidate #1 is defined in an impl for the type `IntoPyObjectConverter<Result<T, E>>`\n   = note: candidate #2 is defined in an impl for the type `IntoPyObjectConverter<T>`\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_init.rs",
    "content": "use pyo3::prelude::*;\r\n\r\n#[pyclass]\r\nstruct InvalidInitReturn;\r\n\r\n#[pymethods]\r\nimpl InvalidInitReturn {\r\n    fn __init__(&self) -> i32 {\r\n        0\r\n    }\r\n}\r\n\r\nfn main() {}\r\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_init.stderr",
    "content": "error[E0277]: the trait bound `i32: IntoPyCallbackOutput<'_, i32>` is not satisfied\n --> tests/ui/invalid_pyclass_init.rs:8:27\n  |\n8 |     fn __init__(&self) -> i32 {\n  |                           ^^^ the trait `IntoPyCallbackOutput<'_, i32>` is not implemented for `i32`\n  |\nhelp: the following other types implement trait `IntoPyCallbackOutput<'py, Target>`\n --> src/impl_/callback.rs\n  |\n  | impl IntoPyCallbackOutput<'_, ffi::Py_ssize_t> for usize {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `usize` implements `IntoPyCallbackOutput<'_, isize>`\n...\n  | impl IntoPyCallbackOutput<'_, usize> for usize {\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `usize` implements `IntoPyCallbackOutput<'_, usize>`\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_item.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass]\nfn foo() {}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pyclass_item.stderr",
    "content": "error: #[pyclass] only supports structs and enums.\n --> tests/ui/invalid_pyclass_item.rs:4:1\n  |\n4 | fn foo() {}\n  | ^^^^^^^^^^^\n"
  },
  {
    "path": "tests/ui/invalid_pyfunction_argument.rs",
    "content": "use pyo3::prelude::*;\nuse std::sync::atomic::AtomicPtr;\n\n#[pyfunction]\nfn invalid_pyfunction_argument(arg: AtomicPtr<()>) {\n    let _ = arg;\n}\n\n#[pyclass(skip_from_py_object)]\n#[derive(Clone)]\nstruct Foo;\n\n#[pyfunction]\nfn skip_from_py_object_without_custom_from_py_object(arg: Foo) {\n    let _ = arg;\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pyfunction_argument.stderr",
    "content": "error[E0277]: `AtomicPtr<()>` cannot be used as a Python function argument\n --> tests/ui/invalid_pyfunction_argument.rs:5:37\n  |\n5 | fn invalid_pyfunction_argument(arg: AtomicPtr<()>) {\n  |                                     ^^^^^^^^^ the trait `PyClass` is not implemented for `AtomicPtr<()>`\n  |\n  = note: implement `FromPyObject` to enable using `AtomicPtr<()>` as a function argument\n  = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]`\nhelp: the trait `PyClass` is implemented for `Foo`\n --> tests/ui/invalid_pyfunction_argument.rs:9:1\n  |\n9 | #[pyclass(skip_from_py_object)]\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  = note: required for `AtomicPtr<()>` to implement `FromPyObject<'_, '_>`\n  = note: required for `AtomicPtr<()>` to implement `PyFunctionArgument<'_, '_, '_, true>`\nnote: required by a bound in `extract_argument`\n --> src/impl_/extract_argument.rs\n  |\n  | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>(\n  |        ---------------- required by a bound in this function\n...\n  |     T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>,\n  |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument`\n  = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0277]: `AtomicPtr<()>` cannot be used as a Python function argument\n --> tests/ui/invalid_pyfunction_argument.rs:5:37\n  |\n5 | fn invalid_pyfunction_argument(arg: AtomicPtr<()>) {\n  |                                     ^^^^^^^^^ the trait `Clone` is not implemented for `AtomicPtr<()>`\n  |\n  = note: implement `FromPyObject` to enable using `AtomicPtr<()>` as a function argument\n  = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]`\nhelp: the following other types implement trait `PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>`\n --> src/impl_/extract_argument.rs\n  |\n  | / impl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false>\n  | |     for &'holder Bound<'py, T>\n  | | where\n  | |     T: PyTypeCheck,\n  | |___________________^ `&'holder pyo3::Bound<'py, T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n...\n  | / impl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option<T>\n  | | where\n  | |     T: PyFunctionArgument<'a, 'holder, 'py, false>,\n  | |___________________________________________________^ `Option<T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n...\n  |   impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T {\n  |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'holder T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n...\n  | / impl<'a, 'holder, T: PyClass<Frozen = False>> PyFunctionArgument<'a, 'holder, '_, false>\n  | |     for &'holder mut T\n  | |______________________^ `&'holder mut T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n  = note: required for `AtomicPtr<()>` to implement `FromPyObject<'_, '_>`\n  = note: required for `AtomicPtr<()>` to implement `PyFunctionArgument<'_, '_, '_, true>`\nnote: required by a bound in `extract_argument`\n --> src/impl_/extract_argument.rs\n  |\n  | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>(\n  |        ---------------- required by a bound in this function\n...\n  |     T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>,\n  |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument`\n\nerror[E0277]: `AtomicPtr<()>` cannot be used as a Python function argument\n --> tests/ui/invalid_pyfunction_argument.rs:5:37\n  |\n5 | fn invalid_pyfunction_argument(arg: AtomicPtr<()>) {\n  |                                     ^^^^^^^^^ the trait `ExtractPyClassWithClone` is not implemented for `AtomicPtr<()>`\n  |\n  = note: implement `FromPyObject` to enable using `AtomicPtr<()>` as a function argument\n  = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]`\nhelp: the following other types implement trait `PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>`\n --> src/impl_/extract_argument.rs\n  |\n  | / impl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false>\n  | |     for &'holder Bound<'py, T>\n  | | where\n  | |     T: PyTypeCheck,\n  | |___________________^ `&'holder pyo3::Bound<'py, T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n...\n  | / impl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option<T>\n  | | where\n  | |     T: PyFunctionArgument<'a, 'holder, 'py, false>,\n  | |___________________________________________________^ `Option<T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n...\n  |   impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T {\n  |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'holder T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n...\n  | / impl<'a, 'holder, T: PyClass<Frozen = False>> PyFunctionArgument<'a, 'holder, '_, false>\n  | |     for &'holder mut T\n  | |______________________^ `&'holder mut T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n  = note: required for `AtomicPtr<()>` to implement `FromPyObject<'_, '_>`\n  = note: required for `AtomicPtr<()>` to implement `PyFunctionArgument<'_, '_, '_, true>`\nnote: required by a bound in `extract_argument`\n --> src/impl_/extract_argument.rs\n  |\n  | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>(\n  |        ---------------- required by a bound in this function\n...\n  |     T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>,\n  |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument`\n\nerror[E0277]: `Foo` cannot be used as a Python function argument\n  --> tests/ui/invalid_pyfunction_argument.rs:14:59\n   |\n14 | fn skip_from_py_object_without_custom_from_py_object(arg: Foo) {\n   |                                                           ^^^ unsatisfied trait bound\n   |\nhelp: the trait `ExtractPyClassWithClone` is not implemented for `Foo`\n  --> tests/ui/invalid_pyfunction_argument.rs:11:1\n   |\n11 | struct Foo;\n   | ^^^^^^^^^^\n   = note: implement `FromPyObject` to enable using `Foo` as a function argument\n   = note: `Python<'py>` is also a valid argument type to pass the Python token into `#[pyfunction]`s and `#[pymethods]`\nhelp: the following other types implement trait `PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>`\n  --> src/impl_/extract_argument.rs\n   |\n   | / impl<'a, 'holder, 'py, T: 'a + 'py> PyFunctionArgument<'a, 'holder, 'py, false>\n   | |     for &'holder Bound<'py, T>\n   | | where\n   | |     T: PyTypeCheck,\n   | |___________________^ `&'holder pyo3::Bound<'py, T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n...\n   | / impl<'a, 'holder, 'py, T> PyFunctionArgument<'a, 'holder, 'py, false> for Option<T>\n   | | where\n   | |     T: PyFunctionArgument<'a, 'holder, 'py, false>,\n   | |___________________________________________________^ `Option<T>` implements `PyFunctionArgument<'a, 'holder, 'py, false>`\n...\n   |   impl<'a, 'holder, T: PyClass> PyFunctionArgument<'a, 'holder, '_, false> for &'holder T {\n   |   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&'holder T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n...\n   | / impl<'a, 'holder, T: PyClass<Frozen = False>> PyFunctionArgument<'a, 'holder, '_, false>\n   | |     for &'holder mut T\n   | |______________________^ `&'holder mut T` implements `PyFunctionArgument<'a, 'holder, '_, false>`\n   = note: required for `Foo` to implement `FromPyObject<'_, '_>`\n   = note: required for `Foo` to implement `PyFunctionArgument<'_, '_, '_, true>`\nnote: required by a bound in `extract_argument`\n  --> src/impl_/extract_argument.rs\n   |\n   | pub fn extract_argument<'a, 'holder, 'py, T, const IMPLEMENTS_FROMPYOBJECT: bool>(\n   |        ---------------- required by a bound in this function\n...\n   |     T: PyFunctionArgument<'a, 'holder, 'py, IMPLEMENTS_FROMPYOBJECT>,\n   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `extract_argument`\n"
  },
  {
    "path": "tests/ui/invalid_pyfunction_definition.rs",
    "content": "#[pyo3::pymodule]\nmod pyo3_scratch {\n    use pyo3::prelude::*;\n\n    #[pyclass]\n    struct Foo {}\n\n    #[pymethods]\n    impl Foo {\n        #[pyfunction]\n        fn bug() {}\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pyfunction_definition.stderr",
    "content": "error: functions inside #[pymethods] do not need to be annotated with #[pyfunction]\n  --> tests/ui/invalid_pyfunction_definition.rs:11:9\n   |\n11 |         fn bug() {}\n   |         ^^\n"
  },
  {
    "path": "tests/ui/invalid_pyfunction_signatures.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::{PyDict, PyTuple};\n\n#[pyfunction]\n#[pyo3(signature = ())]\nfn function_with_one_argument_empty_signature(_x: i32) {}\n\n#[pyfunction]\n#[pyo3(signature = (x))]\nfn function_with_one_entry_signature_no_args() {}\n\n#[pyfunction]\n#[pyo3(signature = (x))]\nfn function_with_incorrect_argument_names(y: i32) {\n    let _ = y;\n}\n\n#[pyfunction(x)]\n#[pyo3(signature = (x))]\nfn function_with_both_args_and_signature(x: i32) {\n    let _ = x;\n}\n\n#[pyfunction]\n#[pyo3(signature = (*, *args))]\nfn function_with_args_after_args_sep(args: &PyTuple) {\n    let _ = args;\n}\n\n#[pyfunction]\n#[pyo3(signature = (*, *))]\nfn function_with_args_sep_after_args_sep() {}\n\n#[pyfunction]\n#[pyo3(signature = (**kwargs, *args))]\nfn function_with_args_after_kwargs(kwargs: Option<&PyDict>, args: &PyTuple) {\n    let _ = args;\n    let _ = kwargs;\n}\n\n#[pyfunction]\n#[pyo3(signature = (**kwargs_a, **kwargs_b))]\nfn function_with_kwargs_after_kwargs(kwargs_a: Option<&PyDict>, kwargs_b: Option<&PyDict>) {\n    let _ = kwargs_a;\n    let _ = kwargs_b;\n}\n\n#[pyfunction(signature = (py))]\nfn signature_contains_py(py: Python<'_>) {\n    let _ = py;\n}\n\n#[pyclass]\nstruct MyClass;\n\n#[pymethods]\nimpl MyClass {\n    #[pyo3(signature = (**kwargs, *, *args, x))]\n    fn multiple_errors_same_order(kwargs: Option<&PyDict>, args: &PyTuple, x: i32) {\n        let _ = kwargs;\n        let _ = args;\n        let _ = x;\n    }\n\n    #[pyo3(signature = (**kwargs, *, *args, x))]\n    fn multiple_errors_different_order(args: &PyTuple, x: i32, kwargs: Option<&PyDict>) {\n        let _ = kwargs;\n        let _ = args;\n        let _ = x;\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pyfunction_signatures.stderr",
    "content": "error: missing signature entry for argument `_x`\n --> tests/ui/invalid_pyfunction_signatures.rs:5:8\n  |\n5 | #[pyo3(signature = ())]\n  |        ^^^^^^^^^\n\nerror: signature entry does not have a corresponding function argument\n --> tests/ui/invalid_pyfunction_signatures.rs:9:21\n  |\n9 | #[pyo3(signature = (x))]\n  |                     ^\n\nerror: expected argument from function definition `y` but got argument `x`\n  --> tests/ui/invalid_pyfunction_signatures.rs:13:21\n   |\n13 | #[pyo3(signature = (x))]\n   |                     ^\n\nerror: expected one of: `name`, `pass_module`, `signature`, `text_signature`, `crate`, `warn`\n  --> tests/ui/invalid_pyfunction_signatures.rs:18:14\n   |\n18 | #[pyfunction(x)]\n   |              ^\n\nerror: `*args` not allowed after `*`\n  --> tests/ui/invalid_pyfunction_signatures.rs:25:24\n   |\n25 | #[pyo3(signature = (*, *args))]\n   |                        ^\n\nerror: `*` not allowed after `*`\n  --> tests/ui/invalid_pyfunction_signatures.rs:31:24\n   |\n31 | #[pyo3(signature = (*, *))]\n   |                        ^\n\nerror: `*args` not allowed after `**kwargs`\n  --> tests/ui/invalid_pyfunction_signatures.rs:35:31\n   |\n35 | #[pyo3(signature = (**kwargs, *args))]\n   |                               ^\n\nerror: `**kwargs_b` not allowed after `**kwargs_a`\n  --> tests/ui/invalid_pyfunction_signatures.rs:42:33\n   |\n42 | #[pyo3(signature = (**kwargs_a, **kwargs_b))]\n   |                                 ^\n\nerror: arguments of type `Python` must not be part of the signature\n  --> tests/ui/invalid_pyfunction_signatures.rs:48:27\n   |\n48 | #[pyfunction(signature = (py))]\n   |                           ^^\n\nerror: expected argument from function definition `args` but got argument `kwargs`\n  --> tests/ui/invalid_pyfunction_signatures.rs:58:27\n   |\n58 |     #[pyo3(signature = (**kwargs, *, *args, x))]\n   |                           ^^^^^^\n\nerror: expected argument from function definition `x` but got argument `kwargs`\n  --> tests/ui/invalid_pyfunction_signatures.rs:65:27\n   |\n65 |     #[pyo3(signature = (**kwargs, *, *args, x))]\n   |                           ^^^^^^\n"
  },
  {
    "path": "tests/ui/invalid_pyfunction_warn.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyfunction]\n#[pyo3(warn)]\nfn no_parenthesis_deprecated() {}\n\n#[pyfunction]\n#[pyo3(warn())]\nfn no_message_deprecated() {}\n\n#[pyfunction]\n#[pyo3(warn(category = pyo3::exceptions::PyDeprecationWarning))]\nfn no_message_deprecated_with_category() {}\n\n#[pyfunction]\n#[pyo3(warn(category = pyo3::exceptions::PyDeprecationWarning, message = ,))]\nfn empty_message_deprecated_with_category() {}\n\n#[pyfunction]\n#[pyo3(warn(message = \"deprecated function\", category = ,))]\nfn empty_category_deprecated_with_message() {}\n\n#[pyfunction]\n#[pyo3(warn(message = \"deprecated function\", random_key))]\nfn random_key_deprecated() {}\n\n#[pyclass]\nstruct DeprecatedMethodContainer {}\n\n#[pymethods]\nimpl DeprecatedMethodContainer {\n    #[classattr]\n    #[pyo3(warn(message = \"deprecated class attr\"))]\n    fn deprecated_class_attr() -> i32 {\n        5\n    }\n}\n\n#[pymethods]\nimpl DeprecatedMethodContainer {\n    #[pyo3(warn(message = \"deprecated __traverse__\"))]\n    fn __traverse__(&self, _visit: pyo3::gc::PyVisit<'_>) -> Result<(), pyo3::PyTraverseError> {\n        Ok(())\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pyfunction_warn.stderr",
    "content": "error: unexpected end of input, expected parentheses\n --> tests/ui/invalid_pyfunction_warn.rs:4:12\n  |\n4 | #[pyo3(warn)]\n  |            ^\n\nerror: missing `message` in `warn` attribute\n --> tests/ui/invalid_pyfunction_warn.rs:8:13\n  |\n8 | #[pyo3(warn())]\n  |             ^\n\nerror: missing `message` in `warn` attribute\n  --> tests/ui/invalid_pyfunction_warn.rs:12:62\n   |\n12 | #[pyo3(warn(category = pyo3::exceptions::PyDeprecationWarning))]\n   |                                                              ^\n\nerror: expected string literal\n  --> tests/ui/invalid_pyfunction_warn.rs:16:74\n   |\n16 | #[pyo3(warn(category = pyo3::exceptions::PyDeprecationWarning, message = ,))]\n   |                                                                          ^\n\nerror: expected identifier\n  --> tests/ui/invalid_pyfunction_warn.rs:20:57\n   |\n20 | #[pyo3(warn(message = \"deprecated function\", category = ,))]\n   |                                                         ^\n\nerror: expected `message` or `category`\n  --> tests/ui/invalid_pyfunction_warn.rs:24:46\n   |\n24 | #[pyo3(warn(message = \"deprecated function\", random_key))]\n   |                                              ^^^^^^^^^^\n\nerror: #[classattr] cannot be used with #[pyo3(warn)]\n  --> tests/ui/invalid_pyfunction_warn.rs:33:12\n   |\n33 |     #[pyo3(warn(message = \"deprecated class attr\"))]\n   |            ^^^^\n\nerror: __traverse__ cannot be used with #[pyo3(warn)]\n  --> tests/ui/invalid_pyfunction_warn.rs:41:12\n   |\n41 |     #[pyo3(warn(message = \"deprecated __traverse__\"))]\n   |            ^^^^\n"
  },
  {
    "path": "tests/ui/invalid_pyfunctions.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::{PyDict, PyString, PyTuple};\n\n#[pyfunction]\nfn generic_function<T>(_value: T) {}\n\n#[pyfunction]\nfn impl_trait_function(_impl_trait: impl AsRef<PyAny>) {}\n\n#[pyfunction]\nfn wildcard_argument(_: i32) {}\n\n#[pyfunction]\nfn destructured_argument((_a, _b): (i32, i32)) {}\n\n#[pyfunction]\n#[pyo3(signature=(*args))]\nfn function_with_optional_args(args: Option<Bound<'_, PyTuple>>) {\n    let _ = args;\n}\n\n#[pyfunction]\n#[pyo3(signature=(**kwargs))]\nfn function_with_required_kwargs(kwargs: Bound<'_, PyDict>) {\n    let _ = kwargs;\n}\n\n#[pyfunction(pass_module)]\nfn pass_module_but_no_arguments<'py>() {}\n\n#[pyfunction(pass_module)]\nfn first_argument_not_module<'a, 'py>(\n    _string: &str,\n    module: &'a Bound<'py, PyModule>,\n) -> PyResult<Bound<'py, PyString>> {\n    module.name()\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pyfunctions.stderr",
    "content": "error: Python functions cannot have generic type parameters\n --> tests/ui/invalid_pyfunctions.rs:5:21\n  |\n5 | fn generic_function<T>(_value: T) {}\n  |                     ^\n\nerror: Python functions cannot have `impl Trait` arguments\n --> tests/ui/invalid_pyfunctions.rs:8:37\n  |\n8 | fn impl_trait_function(_impl_trait: impl AsRef<PyAny>) {}\n  |                                     ^^^^\n\nerror: wildcard argument names are not supported\n  --> tests/ui/invalid_pyfunctions.rs:11:22\n   |\n11 | fn wildcard_argument(_: i32) {}\n   |                      ^\n\nerror: destructuring in arguments is not supported\n  --> tests/ui/invalid_pyfunctions.rs:14:26\n   |\n14 | fn destructured_argument((_a, _b): (i32, i32)) {}\n   |                          ^^^^^^^^\n\nerror: args cannot be optional\n  --> tests/ui/invalid_pyfunctions.rs:18:32\n   |\n18 | fn function_with_optional_args(args: Option<Bound<'_, PyTuple>>) {\n   |                                ^^^^\n\nerror: kwargs must be Option<_>\n  --> tests/ui/invalid_pyfunctions.rs:24:34\n   |\n24 | fn function_with_required_kwargs(kwargs: Bound<'_, PyDict>) {\n   |                                  ^^^^^^\n\nerror: expected `&PyModule` or `Py<PyModule>` as first argument with `pass_module`\n  --> tests/ui/invalid_pyfunctions.rs:29:37\n   |\n29 | fn pass_module_but_no_arguments<'py>() {}\n   |                                     ^^\n\nerror[E0277]: the trait bound `&str: From<BoundRef<'_, '_, pyo3::types::PyModule>>` is not satisfied\n  --> tests/ui/invalid_pyfunctions.rs:33:14\n   |\n33 |     _string: &str,\n   |              ^ the trait `From<BoundRef<'_, '_, pyo3::types::PyModule>>` is not implemented for `&str`\n   |\n   = help: the following other types implement trait `From<T>`:\n             `String` implements `From<&String>`\n             `String` implements `From<&mut str>`\n             `String` implements `From<&str>`\n             `String` implements `From<Box<str>>`\n             `String` implements `From<Cow<'_, str>>`\n             `String` implements `From<char>`\n   = note: required for `BoundRef<'_, '_, pyo3::types::PyModule>` to implement `Into<&str>`\n"
  },
  {
    "path": "tests/ui/invalid_pymethod_enum.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass]\nenum ComplexEnum {\n    Int { int: i32 },\n    Str { string: String },\n}\n\n#[pymethods]\nimpl ComplexEnum {\n    fn mutate_in_place(&mut self) {\n        *self = match self {\n            ComplexEnum::Int { int } => ComplexEnum::Str { string: int.to_string() },\n            ComplexEnum::Str { string } => ComplexEnum::Int { int: string.len() as i32 },\n        }\n    }\n}\n\n#[pyclass]\nenum TupleEnum {\n    Int(i32),\n    Str(String),\n}\n\n#[pymethods]\nimpl TupleEnum {\n    fn mutate_in_place(&mut self) {\n        *self = match self {\n            TupleEnum::Int(int) => TupleEnum::Str(int.to_string()),\n            TupleEnum::Str(string) => TupleEnum::Int(string.len() as i32),\n        }\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymethod_enum.stderr",
    "content": "error[E0271]: type mismatch resolving `<ComplexEnum as PyClass>::Frozen == False`\n  --> tests/ui/invalid_pymethod_enum.rs:11:24\n   |\n11 |     fn mutate_in_place(&mut self) {\n   |                        ^ type mismatch resolving `<ComplexEnum as PyClass>::Frozen == False`\n   |\nnote: expected this to be `False`\n  --> tests/ui/invalid_pymethod_enum.rs:3:1\n   |\n 3 | #[pyclass]\n   | ^^^^^^^^^^\nnote: required by a bound in `extract_pyclass_ref_mut`\n  --> src/impl_/extract_argument.rs\n   |\n   | pub fn extract_pyclass_ref_mut<'a, 'holder, T: PyClass<Frozen = False>>(\n   |                                                        ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut`\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0271]: type mismatch resolving `<ComplexEnum as PyClass>::Frozen == False`\n --> tests/ui/invalid_pymethod_enum.rs:9:1\n  |\n9 | #[pymethods]\n  | ^^^^^^^^^^^^ type mismatch resolving `<ComplexEnum as PyClass>::Frozen == False`\n  |\nnote: expected this to be `False`\n --> tests/ui/invalid_pymethod_enum.rs:3:1\n  |\n3 | #[pyclass]\n  | ^^^^^^^^^^\nnote: required by a bound in `PyClassGuardMut`\n --> src/pyclass/guard.rs\n  |\n  | pub struct PyClassGuardMut<'a, T: PyClass<Frozen = False>> {\n  |                                           ^^^^^^^^^^^^^^ required by this bound in `PyClassGuardMut`\n  = note: this error originates in the attribute macro `pymethods` which comes from the expansion of the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0271]: type mismatch resolving `<TupleEnum as PyClass>::Frozen == False`\n  --> tests/ui/invalid_pymethod_enum.rs:27:24\n   |\n27 |     fn mutate_in_place(&mut self) {\n   |                        ^ type mismatch resolving `<TupleEnum as PyClass>::Frozen == False`\n   |\nnote: expected this to be `False`\n  --> tests/ui/invalid_pymethod_enum.rs:19:1\n   |\n19 | #[pyclass]\n   | ^^^^^^^^^^\nnote: required by a bound in `extract_pyclass_ref_mut`\n  --> src/impl_/extract_argument.rs\n   |\n   | pub fn extract_pyclass_ref_mut<'a, 'holder, T: PyClass<Frozen = False>>(\n   |                                                        ^^^^^^^^^^^^^^ required by this bound in `extract_pyclass_ref_mut`\n   = note: this error originates in the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0271]: type mismatch resolving `<TupleEnum as PyClass>::Frozen == False`\n  --> tests/ui/invalid_pymethod_enum.rs:25:1\n   |\n25 | #[pymethods]\n   | ^^^^^^^^^^^^ type mismatch resolving `<TupleEnum as PyClass>::Frozen == False`\n   |\nnote: expected this to be `False`\n  --> tests/ui/invalid_pymethod_enum.rs:19:1\n   |\n19 | #[pyclass]\n   | ^^^^^^^^^^\nnote: required by a bound in `PyClassGuardMut`\n  --> src/pyclass/guard.rs\n   |\n   | pub struct PyClassGuardMut<'a, T: PyClass<Frozen = False>> {\n   |                                           ^^^^^^^^^^^^^^ required by this bound in `PyClassGuardMut`\n   = note: this error originates in the attribute macro `pymethods` which comes from the expansion of the attribute macro `pyclass` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "tests/ui/invalid_pymethod_names.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass]\nstruct TestClass {\n    num: u32,\n}\n\n#[pymethods]\nimpl TestClass {\n    #[pyo3(name = \"num\")]\n    #[getter(number)]\n    fn get_num(&self) -> u32 { self.num }\n}\n\n#[pymethods]\nimpl TestClass {\n    #[pyo3(name = \"foo\")]\n    #[pyo3(name = \"bar\")]\n    fn qux(&self) -> u32 { self.num }\n}\n\n#[pymethods]\nimpl TestClass {\n    #[pyo3(name = \"makenew\")]\n    #[new]\n    fn new(&self) -> Self { Self { num: 0 } }\n}\n\n#[pymethods]\nimpl TestClass {\n    #[getter(1)]\n    fn get_one(&self) -> Self { Self { num: 0 } }\n}\n\n#[pymethods]\nimpl TestClass {\n    #[getter = 1]\n    fn get_two(&self) -> Self { Self { num: 0 } }\n}\n\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymethod_names.stderr",
    "content": "error: `name` may only be specified once\n  --> tests/ui/invalid_pymethod_names.rs:11:14\n   |\n11 |     #[getter(number)]\n   |              ^^^^^^\n\nerror: `name` may only be specified once\n  --> tests/ui/invalid_pymethod_names.rs:18:12\n   |\n18 |     #[pyo3(name = \"bar\")]\n   |            ^^^^\n\nerror: `name` not allowed with `#[new]`\n  --> tests/ui/invalid_pymethod_names.rs:24:19\n   |\n24 |     #[pyo3(name = \"makenew\")]\n   |                   ^^^^^^^^^\n\nerror: expected ident or string literal for property name\n  --> tests/ui/invalid_pymethod_names.rs:31:14\n   |\n31 |     #[getter(1)]\n   |              ^\n\nerror: expected `#[getter(name)]` to set the name\n  --> tests/ui/invalid_pymethod_names.rs:37:14\n   |\n37 |     #[getter = 1]\n   |              ^\n"
  },
  {
    "path": "tests/ui/invalid_pymethod_receiver.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass]\nstruct MyClass {}\n\n#[pymethods]\nimpl MyClass {\n    fn method_with_invalid_self_type(_slf: i32, _py: Python<'_>, _index: u32) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymethod_receiver.stderr",
    "content": "error[E0277]: the trait bound `i32: TryFrom<BoundRef<'_, '_, MyClass>>` is not satisfied\n --> tests/ui/invalid_pymethod_receiver.rs:8:44\n  |\n8 |     fn method_with_invalid_self_type(_slf: i32, _py: Python<'_>, _index: u32) {}\n  |                                            ^^^ the trait `From<BoundRef<'_, '_, MyClass>>` is not implemented for `i32`\n  |\n  = help: the following other types implement trait `From<T>`:\n            `i32` implements `From<bool>`\n            `i32` implements `From<i16>`\n            `i32` implements `From<i8>`\n            `i32` implements `From<u16>`\n            `i32` implements `From<u8>`\n  = note: required for `BoundRef<'_, '_, MyClass>` to implement `Into<i32>`\n  = note: required for `i32` to implement `TryFrom<BoundRef<'_, '_, MyClass>>`\n"
  },
  {
    "path": "tests/ui/invalid_pymethods.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass]\nstruct MyClass {}\n\n#[pymethods]\nimpl MyClass {\n    #[classattr]\n    fn class_attr_with_args(_foo: i32) {}\n\n    #[classattr(foobar)]\n    const CLASS_ATTR_WITH_ATTRIBUTE_ARG: i32 = 3;\n\n    fn staticmethod_without_attribute() {}\n\n    #[staticmethod]\n    fn staticmethod_with_receiver(&self) {}\n\n    #[classmethod]\n    fn classmethod_with_receiver(&self) {}\n\n    #[classmethod]\n    fn classmethod_missing_argument() -> Self {\n        Self {}\n    }\n}\n\nstruct NotATypeObject;\n\n#[pymethods]\nimpl MyClass {\n    #[classmethod]\n    fn classmethod_wrong_first_argument(_t: NotATypeObject) -> Self {\n        Self {}\n    }\n}\n\n#[pymethods]\nimpl MyClass {\n    #[getter(x)]\n    fn getter_without_receiver() {}\n}\n\n#[pymethods]\nimpl MyClass {\n    #[setter(x)]\n    fn setter_without_receiver() {}\n}\n\n#[pymethods]\nimpl MyClass {\n    #[pyo3(name = \"__call__\", text_signature = \"()\")]\n    fn text_signature_on_call() {}\n\n    #[getter(x)]\n    #[pyo3(text_signature = \"()\")]\n    fn text_signature_on_getter(&self) {}\n\n    #[setter(x)]\n    #[pyo3(text_signature = \"()\")]\n    fn text_signature_on_setter(&self) {}\n\n    #[classattr]\n    #[pyo3(text_signature = \"()\")]\n    fn text_signature_on_classattr() {}\n\n    #[pyo3(text_signature = 1)]\n    fn invalid_text_signature() {}\n\n    #[pyo3(text_signature = \"()\")]\n    #[pyo3(text_signature = None)]\n    fn duplicate_text_signature() {}\n}\n\n#[pymethods]\nimpl MyClass {\n    #[getter(x)]\n    #[pyo3(signature = ())]\n    fn signature_on_getter(&self) {}\n\n    #[setter(x)]\n    #[pyo3(signature = ())]\n    fn signature_on_setter(&self) {}\n\n    #[classattr]\n    #[pyo3(signature = ())]\n    fn signature_on_classattr() {}\n}\n\n#[pymethods]\nimpl MyClass {\n    #[new]\n    #[classmethod]\n    #[staticmethod]\n    #[classattr]\n    #[getter(x)]\n    #[setter(x)]\n    fn multiple_method_types() {}\n}\n\n#[pymethods]\nimpl MyClass {\n    #[new(signature = ())]\n    fn new_takes_no_arguments(&self) {}\n}\n\n#[pymethods]\nimpl MyClass {\n    #[new = ()] // in this form there's no suggestion to move arguments to `#[pyo3()]` attribute\n    fn new_takes_no_arguments_nv(&self) {}\n}\n\n#[pymethods]\nimpl MyClass {\n    #[classmethod(signature = ())]\n    fn classmethod_takes_no_arguments(&self) {}\n}\n\n#[pymethods]\nimpl MyClass {\n    #[staticmethod(signature = ())]\n    fn staticmethod_takes_no_arguments(&self) {}\n}\n\n#[pymethods]\nimpl MyClass {\n    #[classattr(signature = ())]\n    fn classattr_takes_no_arguments(&self) {}\n}\n\n#[pymethods]\nimpl MyClass {\n    fn generic_method<T>(_value: T) {}\n}\n\n#[pymethods]\nimpl MyClass {\n    fn impl_trait_method_first_arg(_impl_trait: impl AsRef<PyAny>) {}\n\n    fn impl_trait_method_second_arg(&self, _impl_trait: impl AsRef<PyAny>) {}\n}\n\n#[pymethods]\nimpl MyClass {\n    #[pyo3(pass_module)]\n    fn method_cannot_pass_module(&self, _m: &PyModule) {}\n}\n\n#[pymethods]\nimpl MyClass {\n    fn method_self_by_value(self) {}\n}\n\nmacro_rules! macro_invocation {\n    () => {};\n}\n\n#[pymethods]\nimpl MyClass {\n    macro_invocation!();\n}\n\n#[pymethods]\nimpl MyClass {\n    #[staticmethod]\n    #[classmethod]\n    fn multiple_errors_static_and_class_method() {}\n\n    #[staticmethod]\n    fn multiple_errors_staticmethod_with_receiver(&self) {}\n\n    #[classmethod]\n    fn multiple_errors_classmethod_with_receiver(&self) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymethods.stderr",
    "content": "error: #[classattr] can only have one argument (of type pyo3::Python)\n --> tests/ui/invalid_pymethods.rs:9:35\n  |\n9 |     fn class_attr_with_args(_foo: i32) {}\n  |                                   ^^^\n\nerror: `#[classattr]` does not take any arguments\n  --> tests/ui/invalid_pymethods.rs:11:5\n   |\n11 |     #[classattr(foobar)]\n   |     ^\n\nerror: static method needs #[staticmethod] attribute\n  --> tests/ui/invalid_pymethods.rs:14:5\n   |\n14 |     fn staticmethod_without_attribute() {}\n   |     ^^\n\nerror: unexpected receiver\n  --> tests/ui/invalid_pymethods.rs:17:35\n   |\n17 |     fn staticmethod_with_receiver(&self) {}\n   |                                   ^\n\nerror: Expected `&Bound<PyType>` or `Py<PyType>` as the first argument to `#[classmethod]`\n  --> tests/ui/invalid_pymethods.rs:20:33\n   |\n20 |     fn classmethod_with_receiver(&self) {}\n   |                                 ^^^^^^^\n\nerror: Expected `&Bound<PyType>` or `Py<PyType>` as the first argument to `#[classmethod]`\n  --> tests/ui/invalid_pymethods.rs:23:36\n   |\n23 |     fn classmethod_missing_argument() -> Self {\n   |                                    ^^\n\nerror: expected receiver for `#[getter]`\n  --> tests/ui/invalid_pymethods.rs:41:5\n   |\n41 |     fn getter_without_receiver() {}\n   |     ^^\n\nerror: expected receiver for `#[setter]`\n  --> tests/ui/invalid_pymethods.rs:47:5\n   |\n47 |     fn setter_without_receiver() {}\n   |     ^^\n\nerror: static method needs #[staticmethod] attribute\n  --> tests/ui/invalid_pymethods.rs:53:5\n   |\n53 |     fn text_signature_on_call() {}\n   |     ^^\n\nerror: `text_signature` not allowed with `getter`\n  --> tests/ui/invalid_pymethods.rs:56:12\n   |\n56 |     #[pyo3(text_signature = \"()\")]\n   |            ^^^^^^^^^^^^^^\n\nerror: `text_signature` not allowed with `setter`\n  --> tests/ui/invalid_pymethods.rs:60:12\n   |\n60 |     #[pyo3(text_signature = \"()\")]\n   |            ^^^^^^^^^^^^^^\n\nerror: `text_signature` not allowed with `classattr`\n  --> tests/ui/invalid_pymethods.rs:64:12\n   |\n64 |     #[pyo3(text_signature = \"()\")]\n   |            ^^^^^^^^^^^^^^\n\nerror: expected a string literal or `None`\n  --> tests/ui/invalid_pymethods.rs:67:30\n   |\n67 |     #[pyo3(text_signature = 1)]\n   |                              ^\n\nerror: `text_signature` may only be specified once\n  --> tests/ui/invalid_pymethods.rs:71:12\n   |\n71 |     #[pyo3(text_signature = None)]\n   |            ^^^^^^^^^^^^^^\n\nerror: `signature` not allowed with `getter`\n  --> tests/ui/invalid_pymethods.rs:78:12\n   |\n78 |     #[pyo3(signature = ())]\n   |            ^^^^^^^^^\n\nerror: `signature` not allowed with `setter`\n  --> tests/ui/invalid_pymethods.rs:82:12\n   |\n82 |     #[pyo3(signature = ())]\n   |            ^^^^^^^^^\n\nerror: `signature` not allowed with `classattr`\n  --> tests/ui/invalid_pymethods.rs:86:12\n   |\n86 |     #[pyo3(signature = ())]\n   |            ^^^^^^^^^\n\nerror: `#[new]` may not be combined with `#[classmethod]` `#[staticmethod]`, `#[classattr]`, `#[getter]`, and `#[setter]`\n  --> tests/ui/invalid_pymethods.rs:92:7\n   |\n92 |     #[new]\n   |       ^^^\n\nerror: `#[new]` does not take any arguments\n       = help: did you mean `#[new] #[pyo3(signature = ())]`?\n   --> tests/ui/invalid_pymethods.rs:103:7\n    |\n103 |     #[new(signature = ())]\n    |       ^^^\n\nerror: `#[new]` does not take any arguments\n       = note: this was previously accepted and ignored\n   --> tests/ui/invalid_pymethods.rs:109:11\n    |\n109 |     #[new = ()] // in this form there's no suggestion to move arguments to `#[pyo3()]` attribute\n    |           ^\n\nerror: `#[classmethod]` does not take any arguments\n       = help: did you mean `#[classmethod] #[pyo3(signature = ())]`?\n   --> tests/ui/invalid_pymethods.rs:115:7\n    |\n115 |     #[classmethod(signature = ())]\n    |       ^^^^^^^^^^^\n\nerror: `#[staticmethod]` does not take any arguments\n       = help: did you mean `#[staticmethod] #[pyo3(signature = ())]`?\n   --> tests/ui/invalid_pymethods.rs:121:7\n    |\n121 |     #[staticmethod(signature = ())]\n    |       ^^^^^^^^^^^^\n\nerror: `#[classattr]` does not take any arguments\n       = help: did you mean `#[classattr] #[pyo3(signature = ())]`?\n   --> tests/ui/invalid_pymethods.rs:127:7\n    |\n127 |     #[classattr(signature = ())]\n    |       ^^^^^^^^^\n\nerror: Python functions cannot have generic type parameters\n   --> tests/ui/invalid_pymethods.rs:133:23\n    |\n133 |     fn generic_method<T>(_value: T) {}\n    |                       ^\n\nerror: Python functions cannot have `impl Trait` arguments\n   --> tests/ui/invalid_pymethods.rs:138:49\n    |\n138 |     fn impl_trait_method_first_arg(_impl_trait: impl AsRef<PyAny>) {}\n    |                                                 ^^^^\n\nerror: Python functions cannot have `impl Trait` arguments\n   --> tests/ui/invalid_pymethods.rs:140:57\n    |\n140 |     fn impl_trait_method_second_arg(&self, _impl_trait: impl AsRef<PyAny>) {}\n    |                                                         ^^^^\n\nerror: `pass_module` cannot be used on Python methods\n   --> tests/ui/invalid_pymethods.rs:145:12\n    |\n145 |     #[pyo3(pass_module)]\n    |            ^^^^^^^^^^^\n\nerror: Python objects are shared, so 'self' cannot be moved out of the Python interpreter.\n       Try `&self`, `&mut self, `slf: PyClassGuard<'_, Self>` or `slf: PyClassGuardMut<'_, Self>`.\n   --> tests/ui/invalid_pymethods.rs:151:29\n    |\n151 |     fn method_self_by_value(self) {}\n    |                             ^^^^\n\nerror: macros cannot be used as items in `#[pymethods]` impl blocks\n       = note: this was previously accepted and ignored\n   --> tests/ui/invalid_pymethods.rs:160:5\n    |\n160 |     macro_invocation!();\n    |     ^^^^^^^^^^^^^^^^\n\nerror: `#[staticmethod]` may not be combined with `#[classmethod]`\n   --> tests/ui/invalid_pymethods.rs:165:7\n    |\n165 |     #[staticmethod]\n    |       ^^^^^^^^^^^^\n\nerror: unexpected receiver\n   --> tests/ui/invalid_pymethods.rs:170:51\n    |\n170 |     fn multiple_errors_staticmethod_with_receiver(&self) {}\n    |                                                   ^\n\nerror: Expected `&Bound<PyType>` or `Py<PyType>` as the first argument to `#[classmethod]`\n   --> tests/ui/invalid_pymethods.rs:173:49\n    |\n173 |     fn multiple_errors_classmethod_with_receiver(&self) {}\n    |                                                 ^^^^^^^\n\nerror[E0277]: the trait bound `NotATypeObject: From<BoundRef<'_, '_, PyType>>` is not satisfied\n  --> tests/ui/invalid_pymethods.rs:33:45\n   |\n33 |     fn classmethod_wrong_first_argument(_t: NotATypeObject) -> Self {\n   |                                             ^^^^^^^^^^^^^^ unsatisfied trait bound\n   |\nhelp: the trait `From<BoundRef<'_, '_, PyType>>` is not implemented for `NotATypeObject`\n  --> tests/ui/invalid_pymethods.rs:28:1\n   |\n28 | struct NotATypeObject;\n   | ^^^^^^^^^^^^^^^^^^^^^\n   = note: required for `BoundRef<'_, '_, PyType>` to implement `Into<NotATypeObject>`\n"
  },
  {
    "path": "tests/ui/invalid_pymethods_buffer.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass]\nstruct MyClass {}\n\n#[pymethods]\nimpl MyClass {\n    #[pyo3(name = \"__getbuffer__\")]\n    fn getbuffer_must_be_unsafe(&self, _view: *mut pyo3::ffi::Py_buffer, _flags: std::ffi::c_int) {}\n}\n\n#[pymethods]\nimpl MyClass {\n    #[pyo3(name = \"__releasebuffer__\")]\n    fn releasebuffer_must_be_unsafe(&self, _view: *mut pyo3::ffi::Py_buffer) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymethods_buffer.stderr",
    "content": "error: `__getbuffer__` must be `unsafe fn`\n --> tests/ui/invalid_pymethods_buffer.rs:9:8\n  |\n9 |     fn getbuffer_must_be_unsafe(&self, _view: *mut pyo3::ffi::Py_buffer, _flags: std::ffi::c_int) {}\n  |        ^^^^^^^^^^^^^^^^^^^^^^^^\n\nerror: `__releasebuffer__` must be `unsafe fn`\n  --> tests/ui/invalid_pymethods_buffer.rs:15:8\n   |\n15 |     fn releasebuffer_must_be_unsafe(&self, _view: *mut pyo3::ffi::Py_buffer) {}\n   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "tests/ui/invalid_pymethods_duplicates.rs",
    "content": "//! These tests are located in a separate file because they cause conflicting implementation\n//! errors, which means other errors such as typechecking errors are not reported.\n\nuse pyo3::prelude::*;\n\n#[pyclass]\nstruct TwoNew {}\n\n#[pymethods]\nimpl TwoNew {\n    #[new]\n    fn new_1() -> Self {\n        Self {}\n    }\n\n    #[new]\n    fn new_2() -> Self {\n        Self {}\n    }\n}\n\n#[pyclass]\nstruct DuplicateMethod {}\n\n#[pymethods]\nimpl DuplicateMethod {\n    #[pyo3(name = \"func\")]\n    fn func_a(&self) {}\n\n    #[pyo3(name = \"func\")]\n    fn func_b(&self) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymethods_duplicates.stderr",
    "content": "error[E0119]: conflicting implementations of trait `PyClassNewTextSignature` for type `TwoNew`\n --> tests/ui/invalid_pymethods_duplicates.rs:9:1\n  |\n9 | #[pymethods]\n  | ^^^^^^^^^^^^\n  | |\n  | first implementation here\n  | conflicting implementation for `TwoNew`\n  |\n  = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0592]: duplicate definitions with name `__pymethod___new____`\n --> tests/ui/invalid_pymethods_duplicates.rs:9:1\n  |\n9 | #[pymethods]\n  | ^^^^^^^^^^^^\n  | |\n  | duplicate definitions for `__pymethod___new____`\n  | other definition for `__pymethod___new____`\n  |\n  = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0592]: duplicate definitions with name `__pymethod_func__`\n  --> tests/ui/invalid_pymethods_duplicates.rs:25:1\n   |\n25 | #[pymethods]\n   | ^^^^^^^^^^^^\n   | |\n   | duplicate definitions for `__pymethod_func__`\n   | other definition for `__pymethod_func__`\n   |\n   = note: this error originates in the attribute macro `pymethods` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "tests/ui/invalid_pymethods_warn.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass]\nstruct WarningMethodContainer {}\n\n#[pymethods]\nimpl WarningMethodContainer {\n    #[pyo3(warn(message = \"warn on __traverse__\"))]\n    fn __traverse__(&self) {}\n}\n\n#[pymethods]\nimpl WarningMethodContainer {\n    #[classattr]\n    #[pyo3(warn(message = \"warn for class attr\"))]\n    fn a_class_attr(_py: pyo3::Python<'_>) -> i64 {\n        5\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymethods_warn.stderr",
    "content": "error: __traverse__ cannot be used with #[pyo3(warn)]\n --> tests/ui/invalid_pymethods_warn.rs:8:12\n  |\n8 |     #[pyo3(warn(message = \"warn on __traverse__\"))]\n  |            ^^^^\n\nerror: #[classattr] cannot be used with #[pyo3(warn)]\n  --> tests/ui/invalid_pymethods_warn.rs:15:12\n   |\n15 |     #[pyo3(warn(message = \"warn for class attr\"))]\n   |            ^^^^\n"
  },
  {
    "path": "tests/ui/invalid_pymodule_args.rs",
    "content": "use pyo3::prelude::*;\n\n#[pymodule(some_arg)]\nfn module(m: &Bound<'_, PyModule>) -> PyResult<()> {\n    Ok(())\n}\n\n#[pyo3::pymodule(gil_used = false, gil_used = true, name = \"foo\", name = \"bar\")]\nfn module_fn_multiple_errors(m: &Bound<'_, PyModule>) -> PyResult<()> {\n    Ok(())\n}\n\n#[pyo3::pymodule(gil_used = false, gil_used = true, name = \"foo\", name = \"bar\")]\nmod pyo3_module_multiple_errors {}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymodule_args.stderr",
    "content": "error: expected one of: `name`, `crate`, `module`, `submodule`, `gil_used`\n --> tests/ui/invalid_pymodule_args.rs:3:12\n  |\n3 | #[pymodule(some_arg)]\n  |            ^^^^^^^^\n\nerror: `gil_used` may only be specified once\n --> tests/ui/invalid_pymodule_args.rs:8:36\n  |\n8 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = \"foo\", name = \"bar\")]\n  |                                    ^^^^^^^^\n\nerror: `name` may only be specified once\n --> tests/ui/invalid_pymodule_args.rs:8:67\n  |\n8 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = \"foo\", name = \"bar\")]\n  |                                                                   ^^^^\n\nerror: `gil_used` may only be specified once\n  --> tests/ui/invalid_pymodule_args.rs:13:36\n   |\n13 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = \"foo\", name = \"bar\")]\n   |                                    ^^^^^^^^\n\nerror: `name` may only be specified once\n  --> tests/ui/invalid_pymodule_args.rs:13:67\n   |\n13 | #[pyo3::pymodule(gil_used = false, gil_used = true, name = \"foo\", name = \"bar\")]\n   |                                                                   ^^^^\n"
  },
  {
    "path": "tests/ui/invalid_pymodule_glob.rs",
    "content": "#![allow(unused_imports)]\n\nuse pyo3::prelude::*;\n\n#[pyfunction]\nfn foo() -> usize {\n    0\n}\n\n#[pymodule]\nmod module {\n    #[pymodule_export]\n    use super::*;\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymodule_glob.stderr",
    "content": "error: #[pymodule] cannot import glob statements\n  --> tests/ui/invalid_pymodule_glob.rs:13:16\n   |\n13 |     use super::*;\n   |                ^\n"
  },
  {
    "path": "tests/ui/invalid_pymodule_in_root.rs",
    "content": "use pyo3::prelude::*;\n\n#[pymodule]\n#[path = \"empty.rs\"] // to silence error related to missing file\nmod invalid_pymodule_in_root_module;\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymodule_in_root.stderr",
    "content": "error[E0658]: file modules in proc macro input are unstable\n --> tests/ui/invalid_pymodule_in_root.rs:5:1\n  |\n5 | mod invalid_pymodule_in_root_module;\n  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  |\n  = note: see issue #54727 <https://github.com/rust-lang/rust/issues/54727> for more information\n\nerror: `#[pymodule]` can only be used on inline modules\n --> tests/ui/invalid_pymodule_in_root.rs:5:1\n  |\n5 | mod invalid_pymodule_in_root_module;\n  | ^^^\n"
  },
  {
    "path": "tests/ui/invalid_pymodule_trait.rs",
    "content": "use pyo3::prelude::*;\n\n#[pymodule]\nmod module {\n    #[pymodule_export]\n    trait Foo {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymodule_trait.stderr",
    "content": "error: `#[pymodule_export]` may only be used on `use` or `const` statements\n --> tests/ui/invalid_pymodule_trait.rs:5:5\n  |\n5 |     #[pymodule_export]\n  |     ^\n\nerror: cannot find attribute `pymodule_export` in this scope\n --> tests/ui/invalid_pymodule_trait.rs:5:7\n  |\n5 |     #[pymodule_export]\n  |       ^^^^^^^^^^^^^^^\n"
  },
  {
    "path": "tests/ui/invalid_pymodule_two_pymodule_init.rs",
    "content": "use pyo3::prelude::*;\n\n#[pymodule]\nmod module {\n    use pyo3::prelude::*;\n\n    #[pymodule_init]\n    fn init(_m: &Bound<'_, PyModule>) -> PyResult<()> {\n        Ok(())\n    }\n\n    #[pymodule_init]\n    fn init2(_m: &Bound<'_, PyModule>) -> PyResult<()> {\n        Ok(())\n    }\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/invalid_pymodule_two_pymodule_init.stderr",
    "content": "error: only one `#[pymodule_init]` may be specified\n  --> tests/ui/invalid_pymodule_two_pymodule_init.rs:13:5\n   |\n13 |     fn init2(_m: &Bound<'_, PyModule>) -> PyResult<()> {\n   |     ^^\n"
  },
  {
    "path": "tests/ui/invalid_result_conversion.rs",
    "content": "//! Testing https://github.com/PyO3/pyo3/issues/1106. A result type that\n//! *doesn't* implement `From<MyError> for PyErr` won't be automatically\n//! converted when using `#[pyfunction]`.\nuse pyo3::prelude::*;\n\nuse std::fmt;\n\n/// A basic error type for the tests. It's missing `From<MyError> for PyErr`,\n/// though, so it shouldn't work.\n#[derive(Debug)]\nstruct MyError {\n    pub descr: &'static str,\n}\n\nimpl fmt::Display for MyError {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"My error message: {}\", self.descr)\n    }\n}\n\n#[pyfunction]\nfn should_not_work() -> Result<(), MyError> {\n    Err(MyError {\n        descr: \"something went wrong\",\n    })\n}\n\nfn main() {\n    Python::attach(|py| {\n        wrap_pyfunction!(should_not_work)(py);\n    });\n}\n"
  },
  {
    "path": "tests/ui/invalid_result_conversion.stderr",
    "content": "error[E0277]: the trait bound `PyErr: From<MyError>` is not satisfied\n  --> tests/ui/invalid_result_conversion.rs:22:25\n   |\n22 | fn should_not_work() -> Result<(), MyError> {\n   |                         ^^^^^^ the trait `From<MyError>` is not implemented for `PyErr`\n   |\n   = help: the following other types implement trait `From<T>`:\n             `PyErr` implements `From<AddrParseError>`\n             `PyErr` implements `From<CastError<'_, '_>>`\n             `PyErr` implements `From<CastIntoError<'_>>`\n             `PyErr` implements `From<DowncastError<'_, '_>>`\n             `PyErr` implements `From<DowncastIntoError<'_>>`\n             `PyErr` implements `From<FromUtf8Error>`\n             `PyErr` implements `From<Infallible>`\n             `PyErr` implements `From<IntoInnerError<W>>`\n           and $N others\n   = note: required for `MyError` to implement `Into<PyErr>`\n"
  },
  {
    "path": "tests/ui/missing_intopy.rs",
    "content": "struct Blah;\n\n#[pyo3::pyfunction]\nfn blah() -> Blah {\n    Blah\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/missing_intopy.stderr",
    "content": "error[E0277]: `Blah` cannot be converted to a Python object\n --> tests/ui/missing_intopy.rs:4:14\n  |\n4 | fn blah() -> Blah {\n  |              ^^^^ unsatisfied trait bound\n  |\nhelp: the trait `IntoPyObject<'_>` is not implemented for `Blah`\n --> tests/ui/missing_intopy.rs:1:1\n  |\n1 | struct Blah;\n  | ^^^^^^^^^^^\n  = note: `IntoPyObject` is automatically implemented by the `#[pyclass]` macro\n  = note: if you do not wish to have a corresponding Python type, implement it manually\n  = note: if you do not own `Blah` you can perform a manual conversion to one of the types in `pyo3::types::*`\n  = help: the following other types implement trait `IntoPyObject<'py>`:\n            &&'a T\n            &&OsStr\n            &&Path\n            &&str\n            &'a (T0, T1)\n            &'a (T0, T1, T2)\n            &'a (T0, T1, T2, T3)\n            &'a (T0, T1, T2, T3, T4)\n          and $N others\nnote: required by a bound in `UnknownReturnType::<T>::wrap`\n --> src/impl_/wrap.rs\n  |\n  |     pub fn wrap<'py>(&self, _: T) -> T\n  |            ---- required by a bound in this associated function\n  |     where\n  |         T: IntoPyObject<'py>,\n  |            ^^^^^^^^^^^^^^^^^ required by this bound in `UnknownReturnType::<T>::wrap`\n\nerror[E0599]: no method named `map_err` found for struct `Blah` in the current scope\n --> tests/ui/missing_intopy.rs:4:14\n  |\n1 | struct Blah;\n  | ----------- method `map_err` not found for this struct\n...\n4 | fn blah() -> Blah {\n  |              ^^^^ method not found in `Blah`\n"
  },
  {
    "path": "tests/ui/not_send.rs",
    "content": "use pyo3::prelude::*;\n\nfn test_not_send_detach(py: Python<'_>) {\n    py.detach(|| { drop(py); });\n}\n\nfn main() {\n    Python::attach(|py| {\n        test_not_send_detach(py);\n    })\n}\n"
  },
  {
    "path": "tests/ui/not_send.stderr",
    "content": "error[E0277]: `*mut pyo3::Python<'static>` cannot be shared between threads safely\n --> tests/ui/not_send.rs:4:15\n  |\n4 |     py.detach(|| { drop(py); });\n  |        ------ ^^^^^^^^^^^^^^^^ `*mut pyo3::Python<'static>` cannot be shared between threads safely\n  |        |\n  |        required by a bound introduced by this call\n  |\n  = help: within `pyo3::Python<'_>`, the trait `Sync` is not implemented for `*mut pyo3::Python<'static>`\nnote: required because it appears within the type `PhantomData<*mut pyo3::Python<'static>>`\n --> $RUST/core/src/marker.rs\n  |\n  | pub struct PhantomData<T: PointeeSized>;\n  |            ^^^^^^^^^^^\nnote: required because it appears within the type `pyo3::marker::NotSend`\n --> src/marker.rs\n  |\n  | struct NotSend(PhantomData<*mut Python<'static>>);\n  |        ^^^^^^^\nnote: required because it appears within the type `PhantomData<pyo3::marker::NotSend>`\n --> $RUST/core/src/marker.rs\n  |\n  | pub struct PhantomData<T: PointeeSized>;\n  |            ^^^^^^^^^^^\nnote: required because it appears within the type `pyo3::Python<'_>`\n --> src/marker.rs\n  |\n  | pub struct Python<'py>(PhantomData<&'py AttachGuard>, PhantomData<NotSend>);\n  |            ^^^^^^\n  = note: required for `&pyo3::Python<'_>` to implement `Send`\nnote: required because it's used within this closure\n --> tests/ui/not_send.rs:4:15\n  |\n4 |     py.detach(|| { drop(py); });\n  |               ^^\n  = note: required for `{closure@$DIR/tests/ui/not_send.rs:4:15: 4:17}` to implement `Ungil`\nnote: required by a bound in `pyo3::Python::<'py>::detach`\n --> src/marker.rs\n  |\n  |     pub fn detach<T, F>(self, f: F) -> T\n  |            ------ required by a bound in this associated function\n  |     where\n  |         F: Ungil + FnOnce() -> T,\n  |            ^^^^^ required by this bound in `Python::<'py>::detach`\n"
  },
  {
    "path": "tests/ui/not_send2.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::PyString;\n\nfn main() {\n    Python::attach(|py| {\n        let string = PyString::new(py, \"foo\");\n\n        py.detach(|| {\n            println!(\"{:?}\", string);\n        });\n    });\n}\n"
  },
  {
    "path": "tests/ui/not_send2.stderr",
    "content": "error[E0277]: `*mut pyo3::Python<'static>` cannot be shared between threads safely\n  --> tests/ui/not_send2.rs:8:19\n   |\n 8 |           py.detach(|| {\n   |  ____________------_^\n   | |            |\n   | |            required by a bound introduced by this call\n 9 | |             println!(\"{:?}\", string);\n10 | |         });\n   | |_________^ `*mut pyo3::Python<'static>` cannot be shared between threads safely\n   |\n   = help: within `pyo3::Bound<'_, PyString>`, the trait `Sync` is not implemented for `*mut pyo3::Python<'static>`\nnote: required because it appears within the type `PhantomData<*mut pyo3::Python<'static>>`\n  --> $RUST/core/src/marker.rs\n   |\n   | pub struct PhantomData<T: PointeeSized>;\n   |            ^^^^^^^^^^^\nnote: required because it appears within the type `pyo3::marker::NotSend`\n  --> src/marker.rs\n   |\n   | struct NotSend(PhantomData<*mut Python<'static>>);\n   |        ^^^^^^^\nnote: required because it appears within the type `PhantomData<pyo3::marker::NotSend>`\n  --> $RUST/core/src/marker.rs\n   |\n   | pub struct PhantomData<T: PointeeSized>;\n   |            ^^^^^^^^^^^\nnote: required because it appears within the type `pyo3::Python<'_>`\n  --> src/marker.rs\n   |\n   | pub struct Python<'py>(PhantomData<&'py AttachGuard>, PhantomData<NotSend>);\n   |            ^^^^^^\nnote: required because it appears within the type `pyo3::Bound<'_, PyString>`\n  --> src/instance.rs\n   |\n   | pub struct Bound<'py, T>(Python<'py>, ManuallyDrop<Py<T>>);\n   |            ^^^^^\n   = note: required for `&pyo3::Bound<'_, PyString>` to implement `Send`\nnote: required because it's used within this closure\n  --> tests/ui/not_send2.rs:8:19\n   |\n 8 |         py.detach(|| {\n   |                   ^^\n   = note: required for `{closure@$DIR/tests/ui/not_send2.rs:8:19: 8:21}` to implement `Ungil`\nnote: required by a bound in `pyo3::Python::<'py>::detach`\n  --> src/marker.rs\n   |\n   |     pub fn detach<T, F>(self, f: F) -> T\n   |            ------ required by a bound in this associated function\n   |     where\n   |         F: Ungil + FnOnce() -> T,\n   |            ^^^^^ required by this bound in `Python::<'py>::detach`\n"
  },
  {
    "path": "tests/ui/pyclass_generic_enum.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass(generic)]\nenum NotGenericForEnum {\n    A,\n    B,\n}\n\n#[pyclass(generic)]\nenum NoGenericForComplexEnum {\n    A { x: f64 },\n    B { y: f64, z: f64 },\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/pyclass_generic_enum.stderr",
    "content": "error: enums do not support #[pyclass(generic)]\n --> tests/ui/pyclass_generic_enum.rs:3:11\n  |\n3 | #[pyclass(generic)]\n  |           ^^^^^^^\n\nerror: enums do not support #[pyclass(generic)]\n --> tests/ui/pyclass_generic_enum.rs:9:11\n  |\n9 | #[pyclass(generic)]\n  |           ^^^^^^^\n"
  },
  {
    "path": "tests/ui/pyclass_probe.rs",
    "content": "#![deny(unused_imports)]\r\nuse pyo3::prelude::*;\r\n\r\n#[pymodule]\r\nmod probe_no_fields {\r\n    use pyo3::prelude::*;\r\n    #[pyclass]\r\n    pub struct Probe {}\r\n    \r\n    #[pymethods]\r\n    impl Probe {\r\n        #[new]\r\n        fn new() -> Self {\r\n            Self {}\r\n        }\r\n    }\r\n}\r\n\r\n#[pymodule]\r\nmod probe_with_fields {\r\n    use pyo3::prelude::*;\r\n    #[pyclass(get_all)]\r\n    pub struct Probe {\r\n        field: u8,\r\n    }\r\n    \r\n    #[pymethods]\r\n    impl Probe {\r\n        #[new]\r\n        fn new() -> Self {\r\n            Self { field: 0 }\r\n        }\r\n    }\r\n}\r\n\r\n#[pyclass]\r\nstruct Check5029();\r\n\r\nmacro_rules! impl_methods {\r\n    ($name:ident) => {\r\n        #[pymethods]\r\n        impl Check5029 {\r\n            fn $name(&self, _value: Option<&str>) -> PyResult<()> {\r\n                Ok(())\r\n            }\r\n        }\r\n    };\r\n}\r\n\r\nimpl_methods!(some_method);\r\n\r\nfn main() {}\r\n"
  },
  {
    "path": "tests/ui/pyclass_send.rs",
    "content": "use pyo3::prelude::*;\nuse std::ffi::c_void;\n\n#[pyclass]\nstruct NotSyncNotSend(*mut c_void);\n\n#[pyclass]\nstruct SendNotSync(*mut c_void);\nunsafe impl Send for SendNotSync {}\n\n#[pyclass]\nstruct SyncNotSend(*mut c_void);\nunsafe impl Sync for SyncNotSend {}\n\n// None of the `unsendable` forms below should fail to compile\n\n#[pyclass(unsendable)]\nstruct NotSyncNotSendUnsendable(*mut c_void);\n\n#[pyclass(unsendable)]\nstruct SendNotSyncUnsendable(*mut c_void);\nunsafe impl Send for SendNotSyncUnsendable {}\n\n#[pyclass(unsendable)]\nstruct SyncNotSendUnsendable(*mut c_void);\nunsafe impl Sync for SyncNotSendUnsendable {}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/pyclass_send.stderr",
    "content": "error[E0277]: `*mut c_void` cannot be sent between threads safely\n --> tests/ui/pyclass_send.rs:5:8\n  |\n5 | struct NotSyncNotSend(*mut c_void);\n  |        ^^^^^^^^^^^^^^ `*mut c_void` cannot be sent between threads safely\n  |\n  = help: within `NotSyncNotSend`, the trait `Send` is not implemented for `*mut c_void`\nnote: required because it appears within the type `NotSyncNotSend`\n --> tests/ui/pyclass_send.rs:5:8\n  |\n5 | struct NotSyncNotSend(*mut c_void);\n  |        ^^^^^^^^^^^^^^\nnote: required by a bound in `assert_pyclass_send_sync`\n --> src/impl_/pyclass/assertions.rs\n  |\n  | pub const fn assert_pyclass_send_sync<T>()\n  |              ------------------------ required by a bound in this function\n  | where\n  |     T: Send + Sync,\n  |        ^^^^ required by this bound in `assert_pyclass_send_sync`\n\nerror[E0277]: `*mut c_void` cannot be shared between threads safely\n --> tests/ui/pyclass_send.rs:5:8\n  |\n5 | struct NotSyncNotSend(*mut c_void);\n  |        ^^^^^^^^^^^^^^ `*mut c_void` cannot be shared between threads safely\n  |\n  = help: within `NotSyncNotSend`, the trait `Sync` is not implemented for `*mut c_void`\nnote: required because it appears within the type `NotSyncNotSend`\n --> tests/ui/pyclass_send.rs:5:8\n  |\n5 | struct NotSyncNotSend(*mut c_void);\n  |        ^^^^^^^^^^^^^^\nnote: required by a bound in `assert_pyclass_send_sync`\n --> src/impl_/pyclass/assertions.rs\n  |\n  | pub const fn assert_pyclass_send_sync<T>()\n  |              ------------------------ required by a bound in this function\n  | where\n  |     T: Send + Sync,\n  |               ^^^^ required by this bound in `assert_pyclass_send_sync`\n\nerror[E0277]: `*mut c_void` cannot be shared between threads safely\n --> tests/ui/pyclass_send.rs:8:8\n  |\n8 | struct SendNotSync(*mut c_void);\n  |        ^^^^^^^^^^^ `*mut c_void` cannot be shared between threads safely\n  |\n  = help: within `SendNotSync`, the trait `Sync` is not implemented for `*mut c_void`\nnote: required because it appears within the type `SendNotSync`\n --> tests/ui/pyclass_send.rs:8:8\n  |\n8 | struct SendNotSync(*mut c_void);\n  |        ^^^^^^^^^^^\nnote: required by a bound in `assert_pyclass_send_sync`\n --> src/impl_/pyclass/assertions.rs\n  |\n  | pub const fn assert_pyclass_send_sync<T>()\n  |              ------------------------ required by a bound in this function\n  | where\n  |     T: Send + Sync,\n  |               ^^^^ required by this bound in `assert_pyclass_send_sync`\n\nerror[E0277]: `*mut c_void` cannot be sent between threads safely\n  --> tests/ui/pyclass_send.rs:12:8\n   |\n12 | struct SyncNotSend(*mut c_void);\n   |        ^^^^^^^^^^^ `*mut c_void` cannot be sent between threads safely\n   |\n   = help: within `SyncNotSend`, the trait `Send` is not implemented for `*mut c_void`\nnote: required because it appears within the type `SyncNotSend`\n  --> tests/ui/pyclass_send.rs:12:8\n   |\n12 | struct SyncNotSend(*mut c_void);\n   |        ^^^^^^^^^^^\nnote: required by a bound in `assert_pyclass_send_sync`\n  --> src/impl_/pyclass/assertions.rs\n   |\n   | pub const fn assert_pyclass_send_sync<T>()\n   |              ------------------------ required by a bound in this function\n   | where\n   |     T: Send + Sync,\n   |        ^^^^ required by this bound in `assert_pyclass_send_sync`\n"
  },
  {
    "path": "tests/ui/pymodule_missing_docs.rs",
    "content": "#![deny(missing_docs)]\n//! Some crate docs\n\nuse pyo3::prelude::*;\n\n/// Some module documentation\n#[pymodule]\npub fn python_module(_m: &Bound<'_, PyModule>) -> PyResult<()> {\n    Ok(())\n}\n\n/// Some module documentation\n#[pymodule]\npub mod declarative_python_module {}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/reject_generics.rs",
    "content": "use pyo3::prelude::*;\n\n#[pyclass]\nstruct ClassWithGenerics<A> {\n    a: A,\n}\n\n#[pyclass]\nstruct ClassWithLifetimes<'a> {\n    a: &'a str,\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/reject_generics.stderr",
    "content": "error: #[pyclass] cannot have generic parameters. For an explanation, see https://pyo3.rs/v0.28.2/class.html#no-generic-parameters\n --> tests/ui/reject_generics.rs:4:25\n  |\n4 | struct ClassWithGenerics<A> {\n  |                         ^\n\nerror: #[pyclass] cannot have lifetime parameters. For an explanation, see https://pyo3.rs/v0.28.2/class.html#no-lifetime-parameters\n --> tests/ui/reject_generics.rs:9:27\n  |\n9 | struct ClassWithLifetimes<'a> {\n  |                           ^^\n"
  },
  {
    "path": "tests/ui/static_ref.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::types::PyList;\n\n#[pyfunction]\nfn static_ref(list: &'static Bound<'_, PyList>) -> usize {\n    list.len()\n}\n\n#[pyfunction]\nfn static_py(list: &Bound<'static, PyList>) -> usize {\n    list.len()\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/static_ref.stderr",
    "content": "error[E0521]: borrowed data escapes outside of function\n --> tests/ui/static_ref.rs:4:1\n  |\n4 | #[pyfunction]\n  | ^^^^^^^^^^^^^\n  | |\n  | `py` is a reference that is only valid in the function body\n  | `py` escapes the function body here\n  | lifetime `'py` defined here\n  | argument requires that `'py` must outlive `'static`\n  |\n  = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0716]: temporary value dropped while borrowed\n --> tests/ui/static_ref.rs:4:1\n  |\n4 | #[pyfunction]\n  | ^^^^^^^^^^^^-\n  | |           |\n  | |           temporary value is freed at the end of this statement\n  | creates a temporary value which is freed while still in use\n  | argument requires that borrow lasts for `'static`\n  |\n  = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)\n\nerror[E0521]: borrowed data escapes outside of function\n --> tests/ui/static_ref.rs:9:1\n  |\n9 | #[pyfunction]\n  | ^^^^^^^^^^^^^\n  | |\n  | `py` is a reference that is only valid in the function body\n  | `py` escapes the function body here\n  | lifetime `'py` defined here\n  | argument requires that `'py` must outlive `'static`\n  |\n  = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)\n"
  },
  {
    "path": "tests/ui/traverse.rs",
    "content": "use pyo3::prelude::*;\nuse pyo3::PyTraverseError;\nuse pyo3::PyVisit;\n\n#[pyclass]\nstruct TraverseTriesToTakePyRef {}\n\n#[pymethods]\nimpl TraverseTriesToTakePyRef {\n    fn __traverse__(_slf: PyRef<Self>, _visit: PyVisit) -> Result<(), PyTraverseError> {\n        Ok(())\n    }\n}\n\n#[pyclass]\nstruct TraverseTriesToTakePyRefMut {}\n\n#[pymethods]\nimpl TraverseTriesToTakePyRefMut {\n    fn __traverse__(_slf: PyRefMut<Self>, _visit: PyVisit) -> Result<(), PyTraverseError> {\n        Ok(())\n    }\n}\n\n#[pyclass]\nstruct TraverseTriesToTakeBound {}\n\n#[pymethods]\nimpl TraverseTriesToTakeBound {\n    fn __traverse__(_slf: Bound<'_, Self>, _visit: PyVisit) -> Result<(), PyTraverseError> {\n        Ok(())\n    }\n}\n\n#[pyclass]\nstruct TraverseTriesToTakeMutSelf {}\n\n#[pymethods]\nimpl TraverseTriesToTakeMutSelf {\n    fn __traverse__(&mut self, _visit: PyVisit) -> Result<(), PyTraverseError> {\n        Ok(())\n    }\n}\n\n#[pyclass]\nstruct TraverseTriesToTakeSelf {}\n\n#[pymethods]\nimpl TraverseTriesToTakeSelf {\n    fn __traverse__(&self, _visit: PyVisit) -> Result<(), PyTraverseError> {\n        Ok(())\n    }\n}\n\n#[pyclass]\nstruct Class;\n\n#[pymethods]\nimpl Class {\n    fn __traverse__(&self, _py: Python<'_>, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n        Ok(())\n    }\n\n    fn __clear__(&mut self) {}\n}\n\nfn main() {}\n"
  },
  {
    "path": "tests/ui/traverse.stderr",
    "content": "error: __traverse__ may not take a receiver other than `&self`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic.\n  --> tests/ui/traverse.rs:10:27\n   |\n10 |     fn __traverse__(_slf: PyRef<Self>, _visit: PyVisit) -> Result<(), PyTraverseError> {\n   |                           ^^^^^\n\nerror: __traverse__ may not take a receiver other than `&self`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic.\n  --> tests/ui/traverse.rs:20:27\n   |\n20 |     fn __traverse__(_slf: PyRefMut<Self>, _visit: PyVisit) -> Result<(), PyTraverseError> {\n   |                           ^^^^^^^^\n\nerror: __traverse__ may not take a receiver other than `&self`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic.\n  --> tests/ui/traverse.rs:30:27\n   |\n30 |     fn __traverse__(_slf: Bound<'_, Self>, _visit: PyVisit) -> Result<(), PyTraverseError> {\n   |                           ^^^^^\n\nerror: __traverse__ may not take a receiver other than `&self`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic.\n  --> tests/ui/traverse.rs:40:21\n   |\n40 |     fn __traverse__(&mut self, _visit: PyVisit) -> Result<(), PyTraverseError> {\n   |                     ^\n\nerror: __traverse__ may not take `Python`. Usually, an implementation of `__traverse__(&self, visit: PyVisit<'_>) -> Result<(), PyTraverseError>` should do nothing but calls to `visit.call`. Most importantly, safe access to the Python interpreter is prohibited inside implementations of `__traverse__`, i.e. `Python::attach` will panic.\n  --> tests/ui/traverse.rs:60:33\n   |\n60 |     fn __traverse__(&self, _py: Python<'_>, _visit: PyVisit<'_>) -> Result<(), PyTraverseError> {\n   |                                 ^^^^^^^^^^\n"
  },
  {
    "path": "tests/ui/wrong_aspyref_lifetimes.rs",
    "content": "use pyo3::{types::PyDict, Bound, Py, Python};\n\nfn main() {\n    let dict: Py<PyDict> = Python::attach(|py| PyDict::new(py).unbind());\n\n    // Should not be able to get access to Py contents outside of `attach`.\n    let dict: &Bound<'_, PyDict> = Python::attach(|py| dict.bind(py));\n\n    let _py: Python = dict.py(); // Obtain a Python<'p> without GIL.\n}\n"
  },
  {
    "path": "tests/ui/wrong_aspyref_lifetimes.stderr",
    "content": "error: lifetime may not live long enough\n --> tests/ui/wrong_aspyref_lifetimes.rs:7:56\n  |\n7 |     let dict: &Bound<'_, PyDict> = Python::attach(|py| dict.bind(py));\n  |                                                    --- ^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`\n  |                                                    | |\n  |                                                    | return type of closure is &'2 pyo3::Bound<'_, PyDict>\n  |                                                    has type `Python<'1>`\n"
  }
]